diff options
38 files changed, 2105 insertions, 908 deletions
diff --git a/configure.ac b/configure.ac index e62502c5..254fef4b 100644 --- a/configure.ac +++ b/configure.ac @@ -202,6 +202,10 @@ if test "$DRI" = yes; then PKG_CHECK_MODULES(DRI, [xf86driproto glproto]) 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.4.0],[DRI_MM=yes], [DRI_MM=no]) + if test "x$DRI_MM" = xyes; then + AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management]) + fi if test "$have_damage_h" = yes; then AC_DEFINE(DAMAGE,1,[Use Damage extension]) fi diff --git a/src/Makefile.am b/src/Makefile.am index 6b812f94..e3bbdcea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,6 +37,10 @@ AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \ intel_drv_la_LTLIBRARIES = intel_drv.la intel_drv_la_LDFLAGS = -module -avoid-version intel_drv_ladir = @moduledir@/drivers +intel_drv_la_LIBADD = +if XSERVER_LIBPCIACCESS +intel_drv_la_LIBADD += @PCIACCESS_LIBS@ +endif XMODE_SRCS=\ local_xf86Rename.h \ @@ -103,6 +107,7 @@ intel_drv_la_SOURCES = \ i830_driver.c \ i830_dvo.c \ i830.h \ + i830_hdmi.c \ i830_i2c.c \ i830_io.c \ i830_lvds.c \ @@ -186,7 +191,7 @@ if HAVE_GEN4ASM SUFFIXES = .g4a .g4b .g4a.g4b: - m4 -s $*.g4a > $*.g4m && intel-gen4asm -o $@ $*.g4m && rm $*.g4m + m4 -I$(srcdir) -s $< > $*.g4m && intel-gen4asm -o $@ $*.g4m && rm $*.g4m $(INTEL_G4B): $(INTEL_G4I) @@ -204,6 +209,8 @@ endif if DRI intel_drv_la_SOURCES += \ $(INTEL_DRI_SRCS) +intel_drv_la_LIBADD += \ + $(DRI_LIBS) endif if XVMC diff --git a/src/common.h b/src/common.h index 9a3e0ac3..57db6cb0 100644 --- a/src/common.h +++ b/src/common.h @@ -303,9 +303,24 @@ extern int I810_DEBUG; #define PCI_CHIP_Q33_G_BRIDGE 0x29D0 #endif -#ifndef PCI_CHIP_IGD_GM -#define PCI_CHIP_IGD_GM 0x2A42 -#define PCI_CHIP_IGD_GM_BRIDGE 0x2A40 +#ifndef PCI_CHIP_GM45_GM +#define PCI_CHIP_GM45_GM 0x2A42 +#define PCI_CHIP_GM45_BRIDGE 0x2A40 +#endif + +#ifndef PCI_CHIP_IGD_E_G +#define PCI_CHIP_IGD_E_G 0x2E02 +#define PCI_CHIP_IGD_E_G_BRIDGE 0x2E00 +#endif + +#ifndef PCI_CHIP_G45_G +#define PCI_CHIP_G45_G 0x2E22 +#define PCI_CHIP_G45_G_BRIDGE 0x2E20 +#endif + +#ifndef PCI_CHIP_Q45_G +#define PCI_CHIP_Q45_G 0x2E12 +#define PCI_CHIP_Q45_G_BRIDGE 0x2E10 #endif #if XSERVER_LIBPCIACCESS @@ -339,19 +354,26 @@ extern int I810_DEBUG; #define IS_I915GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I915_GM) #define IS_I945G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I945_G) #define IS_I945GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I945_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I945_GME) -#define IS_IGD_GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGD_GM) +#define IS_GM45(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_GM45_GM) +#define IS_G4X(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_IGD_E_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G45_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q45_G) #define IS_I965GM(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME) -#define IS_I965G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G35_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_Q || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I946_GZ || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME || IS_IGD_GM(pI810)) +#define IS_I965G(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G35_G || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_Q || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I946_GZ || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GM || DEVICE_ID(pI810->PciInfo) == PCI_CHIP_I965_GME || IS_GM45(pI810) || IS_G4X(pI810)) #define IS_G33CLASS(pI810) (DEVICE_ID(pI810->PciInfo) == PCI_CHIP_G33_G ||\ DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q35_G ||\ DEVICE_ID(pI810->PciInfo) == PCI_CHIP_Q33_G) #define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810) || IS_G33CLASS(pI810)) +#define IS_I915(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_G33CLASS(pI810)) -#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_I965GM(pI810) || IS_IGD_GM(pI810)) +#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810) || IS_I965GM(pI810) || IS_GM45(pI810)) /* mark chipsets for using gfx VM offset for overlay */ #define OVERLAY_NOPHYSICAL(pI810) (IS_G33CLASS(pI810) || IS_I965G(pI810)) +/* mark chipsets without overlay hw */ +#define OVERLAY_NOEXIST(pI810) (IS_GM45(pI810) || IS_G4X(pI810)) /* chipsets require graphics mem for hardware status page */ -#define HWS_NEED_GFX(pI810) (IS_G33CLASS(pI810) || IS_IGD_GM(pI810)) +#define HWS_NEED_GFX(pI810) (IS_G33CLASS(pI810) || IS_GM45(pI810) || IS_G4X(pI810)) +/* chipsets require status page in non stolen memory */ +#define HWS_NEED_NONSTOLEN(pI810) (IS_GM45(pI810) || IS_G4X(pI810)) +#define SUPPORTS_INTEGRATED_HDMI(pI810) (IS_GM45(pI810) || IS_G4X(pI810)) #define GTT_PAGE_SIZE KB(4) #define ROUND_TO(x, y) (((x) + (y) - 1) / (y) * (y)) diff --git a/src/i810_driver.c b/src/i810_driver.c index 4b716608..8540646d 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -152,7 +152,10 @@ static const struct pci_id_match intel_device_match[] = { INTEL_DEVICE_MATCH (PCI_CHIP_G33_G, 0 ), INTEL_DEVICE_MATCH (PCI_CHIP_Q35_G, 0 ), INTEL_DEVICE_MATCH (PCI_CHIP_Q33_G, 0 ), - INTEL_DEVICE_MATCH (PCI_CHIP_IGD_GM, 0 ), + INTEL_DEVICE_MATCH (PCI_CHIP_GM45_GM, 0 ), + INTEL_DEVICE_MATCH (PCI_CHIP_IGD_E_G, 0 ), + INTEL_DEVICE_MATCH (PCI_CHIP_G45_G, 0 ), + INTEL_DEVICE_MATCH (PCI_CHIP_Q45_G, 0 ), { 0, 0, 0 }, }; @@ -205,7 +208,10 @@ static SymTabRec I810Chipsets[] = { {PCI_CHIP_G33_G, "G33"}, {PCI_CHIP_Q35_G, "Q35"}, {PCI_CHIP_Q33_G, "Q33"}, - {PCI_CHIP_IGD_GM, "Intel Integrated Graphics Device"}, + {PCI_CHIP_GM45_GM, "Mobile IntelĀ® GM45 Express Chipset"}, + {PCI_CHIP_IGD_E_G, "Intel Integrated Graphics Device"}, + {PCI_CHIP_G45_G, "G45/G43"}, + {PCI_CHIP_Q45_G, "Q45/Q43"}, {-1, NULL} }; @@ -235,7 +241,10 @@ static PciChipsets I810PciChipsets[] = { {PCI_CHIP_G33_G, PCI_CHIP_G33_G, RES_SHARED_VGA}, {PCI_CHIP_Q35_G, PCI_CHIP_Q35_G, RES_SHARED_VGA}, {PCI_CHIP_Q33_G, PCI_CHIP_Q33_G, RES_SHARED_VGA}, - {PCI_CHIP_IGD_GM, PCI_CHIP_IGD_GM, RES_SHARED_VGA}, + {PCI_CHIP_GM45_GM, PCI_CHIP_GM45_GM, RES_SHARED_VGA}, + {PCI_CHIP_IGD_E_G, PCI_CHIP_IGD_E_G, RES_SHARED_VGA}, + {PCI_CHIP_G45_G, PCI_CHIP_G45_G, RES_SHARED_VGA}, + {PCI_CHIP_Q45_G, PCI_CHIP_Q45_G, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED } }; @@ -799,7 +808,10 @@ I810Probe(DriverPtr drv, int flags) case PCI_CHIP_G33_G: case PCI_CHIP_Q35_G: case PCI_CHIP_Q33_G: - case PCI_CHIP_IGD_GM: + case PCI_CHIP_GM45_GM: + case PCI_CHIP_IGD_E_G: + case PCI_CHIP_G45_G: + case PCI_CHIP_Q45_G: xf86SetEntitySharable(usedChips[i]); /* Allocate an entity private if necessary */ diff --git a/src/i810_reg.h b/src/i810_reg.h index 6a82c19b..4b9ce9bd 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -1218,6 +1218,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define FP_M2_DIV_SHIFT 0 #define PORT_HOTPLUG_EN 0x61110 +# define HDMIB_HOTPLUG_INT_EN (1 << 29) +# define HDMIC_HOTPLUG_INT_EN (1 << 28) +# define HDMID_HOTPLUG_INT_EN (1 << 27) # define SDVOB_HOTPLUG_INT_EN (1 << 26) # define SDVOC_HOTPLUG_INT_EN (1 << 25) # define TV_HOTPLUG_INT_EN (1 << 18) @@ -1225,6 +1228,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # define CRT_HOTPLUG_FORCE_DETECT (1 << 3) #define PORT_HOTPLUG_STAT 0x61114 +# define HDMIB_HOTPLUG_INT_STATUS (1 << 29) +# define HDMIC_HOTPLUG_INT_STATUS (1 << 28) +# define HDMID_HOTPLUG_INT_STATUS (1 << 27) # define CRT_HOTPLUG_INT_STATUS (1 << 11) # define TV_HOTPLUG_INT_STATUS (1 << 10) # define CRT_HOTPLUG_MONITOR_MASK (3 << 8) @@ -1253,9 +1259,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SDVO_PHASE_SELECT_DEFAULT (6 << 19) #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) #define SDVOC_GANG_MODE (1 << 16) +#define SDVO_ENCODING_SDVO (0x0 << 10) +#define SDVO_ENCODING_HDMI (0x2 << 10) +/** Requird for HDMI operation */ +#define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) #define SDVO_BORDER_ENABLE (1 << 7) -/** new with 965, default is to be set */ +/** New with 965, default is to be set */ #define SDVO_VSYNC_ACTIVE_HIGH (1 << 4) +/** New with 965, default is to be set */ #define SDVO_HSYNC_ACTIVE_HIGH (1 << 3) /** 915/945 only, read-only bit */ #define SDVOB_PCIE_CONCURRENCY (1 << 3) @@ -1453,6 +1464,30 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /** @} */ +#define DP_B 0x64100 +#define DPB_AUX_CH_CTL 0x64110 +#define DPB_AUX_CH_DATA1 0x64114 +#define DPB_AUX_CH_DATA2 0x64118 +#define DPB_AUX_CH_DATA3 0x6411c +#define DPB_AUX_CH_DATA4 0x64120 +#define DPB_AUX_CH_DATA5 0x64124 + +#define DP_C 0x64200 +#define DPC_AUX_CH_CTL 0x64210 +#define DPC_AUX_CH_DATA1 0x64214 +#define DPC_AUX_CH_DATA2 0x64218 +#define DPC_AUX_CH_DATA3 0x6421c +#define DPC_AUX_CH_DATA4 0x64220 +#define DPC_AUX_CH_DATA5 0x64224 + +#define DP_D 0x64300 +#define DPD_AUX_CH_CTL 0x64310 +#define DPD_AUX_CH_DATA1 0x64314 +#define DPD_AUX_CH_DATA2 0x64318 +#define DPD_AUX_CH_DATA3 0x6431c +#define DPD_AUX_CH_DATA4 0x64320 +#define DPD_AUX_CH_DATA5 0x64324 + /* * Two channel clock control. Turn this on if you need clkb for two channel mode * Overridden by global LVDS power sequencing @@ -2272,6 +2307,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define I915G_GMCH_GMS_STOLEN_64M (0x7 << 4) #define G33_GMCH_GMS_STOLEN_128M (0x8 << 4) #define G33_GMCH_GMS_STOLEN_256M (0x9 << 4) +#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4) +#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4) +#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4) +#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) + #define I85X_CAPID 0x44 #define I85X_VARIANT_MASK 0x7 @@ -236,6 +236,7 @@ typedef struct { #define I830_OUTPUT_SDVO 5 #define I830_OUTPUT_LVDS 6 #define I830_OUTPUT_TVOUT 7 +#define I830_OUTPUT_HDMI 8 struct _I830DVODriver { int type; @@ -427,7 +428,6 @@ typedef struct _I830Rec { #ifdef INTEL_XVMC /* For XvMC */ Bool XvMCEnabled; - Bool IsXvMCSurface; #endif XF86ModReqInfo shadowReq; /* to test for later libshadow */ @@ -567,6 +567,10 @@ typedef struct _I830Rec { OptionInfoPtr Options; Bool lvds_24_bit_mode; + Bool lvds_use_ssc; + int lvds_ssc_freq; /* in MHz */ + + Bool tv_present; /* TV connector present (from VBIOS) */ Bool StolenOnly; @@ -819,6 +823,9 @@ void i830_crt_init(ScrnInfoPtr pScrn); /* i830_dvo.c */ void i830_dvo_init(ScrnInfoPtr pScrn); +/* i830_hdmi.c */ +void i830_hdmi_init(ScrnInfoPtr pScrn, int output_reg); + /* i830_lvds.c */ void i830_lvds_init(ScrnInfoPtr pScrn); diff --git a/src/i830_bios.c b/src/i830_bios.c index 57ee2782..a8193fc5 100644 --- a/src/i830_bios.c +++ b/src/i830_bios.c @@ -70,6 +70,32 @@ i830DumpBIOSToFile(ScrnInfoPtr pScrn, unsigned char *bios) fclose(f); } +static void * +find_section(struct bdb_header *bdb, int section_id) +{ + unsigned char *base = (unsigned char *)bdb; + int index = 0; + uint16_t total, current_size; + unsigned char current_id; + + /* skip to first section */ + index += bdb->header_size; + total = bdb->bdb_size; + + /* walk the sections looking for section_id */ + while (index < total) { + current_id = *(base + index); + index++; + current_size = *((uint16_t *)(base + index)); + index += 2; + if (current_id == section_id) + return base + index; + index += current_size; + } + + return NULL; +} + /** * Loads the Video BIOS and checks that the VBT exists. * @@ -127,6 +153,70 @@ i830_bios_get (ScrnInfoPtr pScrn) return bios; } +void +i830_bios_get_ssc(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + struct vbt_header *vbt; + struct bdb_header *bdb; + struct bdb_general_features *bdb_features; + int vbt_off, bdb_off; + unsigned char *bios; + + bios = i830_bios_get(pScrn); + + if (bios == NULL) + return; + + vbt_off = INTEL_BIOS_16(0x1a); + vbt = (struct vbt_header *)(bios + vbt_off); + bdb_off = vbt_off + vbt->bdb_offset; + bdb = (struct bdb_header *)(bios + bdb_off); + + bdb_features = find_section(bdb, BDB_GENERAL_FEATURES); + if (!bdb_features) + return; + + pI830->lvds_use_ssc = bdb_features->enable_ssc; + if (pI830->lvds_use_ssc) { + if (IS_I855(pI830)) + pI830->lvds_ssc_freq = bdb_features->ssc_freq ? 66 : 48; + else + pI830->lvds_ssc_freq = bdb_features->ssc_freq ? 100 : 96; + } + + xfree(bios); +} + +void +i830_bios_get_tv(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + struct vbt_header *vbt; + struct bdb_header *bdb; + struct bdb_general_features *bdb_features; + int vbt_off, bdb_off; + unsigned char *bios; + + bios = i830_bios_get(pScrn); + + if (bios == NULL) + return; + + vbt_off = INTEL_BIOS_16(0x1a); + vbt = (struct vbt_header *)(bios + vbt_off); + bdb_off = vbt_off + vbt->bdb_offset; + bdb = (struct bdb_header *)(bios + bdb_off); + + bdb_features = find_section(bdb, BDB_GENERAL_FEATURES); + if (!bdb_features) + return; + + pI830->tv_present = bdb_features->int_tv_support; + + xfree(bios); +} + /** * Returns the BIOS's fixed panel mode. * diff --git a/src/i830_bios.h b/src/i830_bios.h index 95230f5a..c1ba50d7 100644 --- a/src/i830_bios.h +++ b/src/i830_bios.h @@ -49,6 +49,97 @@ struct bdb_header { uint16_t bdb_size; /**< in bytes */ } __attribute__((packed)); +/* + * There are several types of BIOS data blocks (BDBs), each block has + * an ID and size in the first 3 bytes (ID in first, size in next 2). + * Known types are listed below. + */ +#define BDB_GENERAL_FEATURES 1 +#define BDB_GENERAL_DEFINITIONS 2 +#define BDB_OLD_TOGGLE_LIST 3 +#define BDB_MODE_SUPPORT_LIST 4 +#define BDB_GENERIC_MODE_TABLE 5 +#define BDB_EXT_MMIO_REGS 6 +#define BDB_SWF_IO 7 +#define BDB_SWF_MMIO 8 +#define BDB_DOT_CLOCK_TABLE 9 +#define BDB_MODE_REMOVAL_TABLE 10 +#define BDB_CHILD_DEVICE_TABLE 11 +#define BDB_DRIVER_FEATURES 12 +#define BDB_DRIVER_PERSISTENCE 13 +#define BDB_EXT_TABLE_PTRS 14 +#define BDB_DOT_CLOCK_OVERRIDE 15 +#define BDB_DISPLAY_SELECT 16 +/* 17 rsvd */ +#define BDB_DRIVER_ROTATION 18 +#define BDB_DISPLAY_REMOVE 19 +#define BDB_OEM_CUSTOM 20 +#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */ +#define BDB_SDVO_LVDS_OPTIONS 22 +#define BDB_SDVO_PANEL_DTDS 23 +#define BDB_SDVO_LVDS_PNP_IDS 24 +#define BDB_SDVO_LVDS_POWER_SEQ 25 +#define BDB_TV_OPTIONS 26 +#define BDB_LVDS_OPTIONS 40 +#define BDB_LVDS_LFP_DATA_PTRS 41 +#define BDB_LVDS_LFP_DATA 42 +#define BDB_LVDS_BACKLIGHT 43 +#define BDB_LVDS_POWER 44 +#define BDB_SKIP 254 /* VBIOS private block, ignore */ + +struct bdb_general_features { + /* bits 1 */ + unsigned char panel_fitting:2; + unsigned char flexaim:1; + unsigned char msg_enable:1; + unsigned char clear_screen:3; + unsigned char color_flip:1; + + /* bits 2 */ + unsigned char download_ext_vbt:1; + unsigned char enable_ssc:1; + unsigned char ssc_freq:1; + unsigned char enable_lfp_on_override:1; + unsigned char disable_ssc_ddt:1; + unsigned char rsvd8:3; /* finish byte */ + + /* bits 3 */ + unsigned char disable_smooth_vision:1; + unsigned char single_dvi:1; + unsigned char rsvd9:6; /* finish byte */ + + /* bits 4 */ + unsigned char legacy_monitor_detect; + + /* bits 5 */ + unsigned char int_crt_support:1; + unsigned char int_tv_support:1; + unsigned char rsvd11:6; /* finish byte */ +} __attribute__((packed)); + +struct bdb_general_definitions { + /* DDC GPIO */ + unsigned char crt_ddc_gmbus_pin; + + /* DPMS bits */ + unsigned char dpms_acpi:1; + unsigned char skip_boot_crt_detect:1; + unsigned char dpms_aim:1; + unsigned char rsvd1:5; /* finish byte */ + + /* boot device bits */ + unsigned char boot_display[2]; + unsigned char child_dev_size; + + /* device info */ + unsigned char tv_or_lvds_info[33]; + unsigned char dev1[33]; + unsigned char dev2[33]; + unsigned char dev3[33]; + unsigned char dev4[33]; + /* may be another device block here on some platforms */ +}; + #define LVDS_CAP_EDID (1 << 6) #define LVDS_CAP_DITHER (1 << 5) #define LVDS_CAP_PFIT_AUTO_RATIO (1 << 4) @@ -150,6 +241,8 @@ struct vch_bdb_22 { unsigned char * i830_bios_get (ScrnInfoPtr pScrn); +void i830_bios_get_ssc(ScrnInfoPtr pScrn); +void i830_bios_get_tv(ScrnInfoPtr pScrn); DisplayModePtr i830_bios_get_panel_mode(ScrnInfoPtr pScrn, Bool *wants_dither); unsigned char * diff --git a/src/i830_debug.c b/src/i830_debug.c index e90ea22a..21e52504 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -537,15 +537,6 @@ static struct i830SnapshotRec { DEFINEREG2(PIPEASRC, i830_debug_yxminus1), DEFINEREG2(PIPEASTAT, i830_debug_pipestat), - DEFINEREG(FBC_CFB_BASE), - DEFINEREG(FBC_LL_BASE), - DEFINEREG(FBC_CONTROL), - DEFINEREG(FBC_COMMAND), - DEFINEREG(FBC_STATUS), - DEFINEREG(FBC_CONTROL2), - DEFINEREG(FBC_FENCE_OFF), - DEFINEREG(FBC_MOD_NUM), - DEFINEREG2(FPA0, i830_debug_fp), DEFINEREG2(FPA1, i830_debug_fp), DEFINEREG2(DPLL_A, i830_debug_dpll), @@ -623,11 +614,45 @@ static struct i830SnapshotRec { DEFINEREG(TV_H_CHROMA_0), DEFINEREG(TV_H_CHROMA_59), + DEFINEREG(FBC_CFB_BASE), + DEFINEREG(FBC_LL_BASE), + DEFINEREG(FBC_CONTROL), + DEFINEREG(FBC_COMMAND), + DEFINEREG(FBC_STATUS), + DEFINEREG(FBC_CONTROL2), + DEFINEREG(FBC_FENCE_OFF), + DEFINEREG(FBC_MOD_NUM), + DEFINEREG(MI_MODE), /* DEFINEREG(MI_DISPLAY_POWER_DOWN), CRL only */ DEFINEREG(MI_ARB_STATE), DEFINEREG(MI_RDRET_STATE), DEFINEREG(ECOSKPD), + + DEFINEREG(DP_B), + DEFINEREG(DPB_AUX_CH_CTL), + DEFINEREG(DPB_AUX_CH_DATA1), + DEFINEREG(DPB_AUX_CH_DATA2), + DEFINEREG(DPB_AUX_CH_DATA3), + DEFINEREG(DPB_AUX_CH_DATA4), + DEFINEREG(DPB_AUX_CH_DATA5), + + DEFINEREG(DP_C), + DEFINEREG(DPC_AUX_CH_CTL), + DEFINEREG(DPC_AUX_CH_DATA1), + DEFINEREG(DPC_AUX_CH_DATA2), + DEFINEREG(DPC_AUX_CH_DATA3), + DEFINEREG(DPC_AUX_CH_DATA4), + DEFINEREG(DPC_AUX_CH_DATA5), + + DEFINEREG(DP_D), + DEFINEREG(DPD_AUX_CH_CTL), + DEFINEREG(DPD_AUX_CH_DATA1), + DEFINEREG(DPD_AUX_CH_DATA2), + DEFINEREG(DPD_AUX_CH_DATA3), + DEFINEREG(DPD_AUX_CH_DATA4), + DEFINEREG(DPD_AUX_CH_DATA5), + #if 0 DEFINEREG2(FENCE_NEW + 0, i810_debug_fence_new), DEFINEREG2(FENCE_NEW + 8, i810_debug_fence_new), @@ -697,6 +722,7 @@ void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where) } #endif /* !REG_DUMPER */ +#if 0 static void i830DumpIndexed (ScrnInfoPtr pScrn, char *name, int id, int val, int min, int max) { I830Ptr pI830 = I830PTR(pScrn); @@ -737,6 +763,7 @@ static void i830DumpAR(ScrnInfoPtr pScrn) OUTREG8(0x3c0, orig_arx); INREG8(st01); /* switch back to index mode */ } +#endif void i830DumpRegs (ScrnInfoPtr pScrn) { @@ -748,8 +775,10 @@ void i830DumpRegs (ScrnInfoPtr pScrn) int ref; int dot; int phase; +#if 0 int msr; int crt; +#endif xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsBegin\n"); for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) { @@ -767,6 +796,7 @@ void i830DumpRegs (ScrnInfoPtr pScrn) i830_snapshot[i].name, (unsigned int)val); } } +#if 0 i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7); msr = INREG8(0x3cc); xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%02x\n", @@ -778,6 +808,7 @@ void i830DumpRegs (ScrnInfoPtr pScrn) else crt = 0x3b0; i830DumpIndexed (pScrn, "CR", crt + 4, crt + 5, 0, 0x24); +#endif for (pipe = 0; pipe <= 1; pipe++) { fp = INREG(pipe == 0 ? FPA0 : FPB0); diff --git a/src/i830_display.c b/src/i830_display.c index 56a718de..3967b69b 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -35,6 +35,7 @@ #include <assert.h> #include <stdlib.h> #include <math.h> +#include <sys/ioctl.h> #include "xf86.h" #include "i830.h" @@ -667,7 +668,7 @@ i830_enable_fb_compression(xf86CrtcPtr crtc) ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); - if (IS_IGD_GM(pI830)) + if (IS_GM45(pI830)) return i830_enable_fb_compression2(crtc); i830_enable_fb_compression_8xx(crtc); @@ -679,7 +680,7 @@ i830_disable_fb_compression(xf86CrtcPtr crtc) ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); - if (IS_IGD_GM(pI830)) + if (IS_GM45(pI830)) return i830_disable_fb_compression2(crtc); i830_disable_fb_compression_8xx(crtc); @@ -692,6 +693,7 @@ i830_use_fb_compression(xf86CrtcPtr crtc) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + unsigned long uncompressed_size; int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB); int i, count = 0; @@ -723,6 +725,19 @@ i830_use_fb_compression(xf86CrtcPtr crtc) pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */ return FALSE; + /* Can't cache more lines than we can track */ + if (crtc->mode.VDisplay > FBC_LL_SIZE) + return FALSE; + + /* + * Make sure the compressor doesn't go past the end of our compressed + * buffer if the uncompressed size is large. + */ + uncompressed_size = crtc->mode.HDisplay * crtc->mode.VDisplay * + pI830->cpp; + if (pI830->compressed_front_buffer->size < uncompressed_size) + return FALSE; + /* * No checks for pixel multiply, incl. horizontal, or interlaced modes * since they're currently unused. @@ -730,6 +745,37 @@ i830_use_fb_compression(xf86CrtcPtr crtc) return TRUE; } +#if defined(DRM_IOCTL_MODESET_CTL) && defined(XF86DRI) +static void i830_modeset_ctl(xf86CrtcPtr crtc, int pre) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + struct drm_modeset_ctl modeset; + + modeset.crtc = intel_crtc->plane; + + /* + * DPMS will be called many times (especially off), but we only + * want to catch the transition from on->off and off->on. + */ + if (pre && intel_crtc->dpms_mode != DPMSModeOff) { + /* On -> off is a pre modeset */ + modeset.cmd = _DRM_PRE_MODESET; + ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset); + } else if (!pre && intel_crtc->dpms_mode == DPMSModeOff) { + /* Off -> on means post modeset */ + modeset.cmd = _DRM_POST_MODESET; + ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset); + } +} +#else +static void i830_modeset_ctl(xf86CrtcPtr crtc, int dpms_state) +{ + return; +} +#endif /* DRM_IOCTL_MODESET_CTL && XF86DRI */ + /** * Sets the power management mode of the pipe and plane. * @@ -797,8 +843,10 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Reenable compression if needed */ if (i830_use_fb_compression(crtc)) i830_enable_fb_compression(crtc); + i830_modeset_ctl(crtc, 0); break; case DPMSModeOff: + i830_modeset_ctl(crtc, 1); /* Shut off compression if in use */ if (i830_use_fb_compression(crtc)) i830_disable_fb_compression(crtc); @@ -1080,7 +1128,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS; int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE; int pipestat_reg = (pipe == 0) ? PIPEASTAT : PIPEBSTAT; - int i; + int i, num_outputs = 0; int refclk; intel_clock_t clock; uint32_t dpll = 0, fp = 0, dspcntr, pipeconf, lvds_bits = 0; @@ -1103,6 +1151,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, lvds_bits = intel_output->lvds_bits; break; case I830_OUTPUT_SDVO: + case I830_OUTPUT_HDMI: is_sdvo = TRUE; if (intel_output->needs_tv_clock) is_tv = TRUE; @@ -1119,9 +1168,19 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, is_crt = TRUE; break; } + + num_outputs++; } - if (IS_I9XX(pI830)) { + if (num_outputs > 1) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "clone detected, disabling SSC\n"); + + /* Don't use SSC when cloned */ + if (pI830->lvds_use_ssc && num_outputs < 2) { + refclk = pI830->lvds_ssc_freq * 1000; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "using SSC reference clock of %d MHz\n", refclk / 1000); + } else if (IS_I9XX(pI830)) { refclk = 96000; } else { refclk = 48000; @@ -1174,7 +1233,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } - if (IS_I965G(pI830)) + if (IS_I965G(pI830) && !IS_GM45(pI830)) dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); } else { if (is_lvds) { @@ -1197,10 +1256,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ dpll |= 3; } -#if 0 - else if (is_lvds) + else if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; -#endif else dpll |= PLL_REF_INPUT_DREFCLK; diff --git a/src/i830_dri.c b/src/i830_dri.c index 2f3c5d39..387e9876 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -995,26 +995,35 @@ static void I830DRIDoRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox, uint32_t dst) { I830Ptr pI830 = I830PTR(pScrn); - int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16); + unsigned int i, cmd, pitch, flags; + + pitch = pScrn->displayWidth * pI830->cpp; + flags = 0xcc << 16; /* ROP_S */ if (pScrn->bitsPerPixel == 32) { cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB); - br13 |= 3 << 24; + flags |= 3 << 24; } else { cmd = (XY_SRC_COPY_BLT_CMD); - br13 |= 1 << 24; + flags |= 1 << 24; + } + + /* We can assume tiled buffers if page flipping is on */ + if (IS_I965G(pI830)) { + cmd |= XY_SRC_COPY_BLT_DST_TILED | XY_SRC_COPY_BLT_SRC_TILED; + pitch >>= 2; } for (i = 0 ; i < num ; i++, pbox++) { BEGIN_BATCH(8); OUT_BATCH(cmd); - OUT_BATCH(br13); + OUT_BATCH(flags | pitch); OUT_BATCH((pbox->y1 << 16) | pbox->x1); OUT_BATCH((pbox->y2 << 16) | pbox->x2); OUT_BATCH(dst); OUT_BATCH((pbox->y1 << 16) | pbox->x1); - OUT_BATCH(br13 & 0xffff); + OUT_BATCH(pitch); OUT_BATCH(pI830->front_buffer->offset); ADVANCE_BATCH(); } diff --git a/src/i830_driver.c b/src/i830_driver.c index 5525aec4..b44db7ec 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -249,7 +249,10 @@ static SymTabRec I830Chipsets[] = { {PCI_CHIP_G33_G, "G33"}, {PCI_CHIP_Q35_G, "Q35"}, {PCI_CHIP_Q33_G, "Q33"}, - {PCI_CHIP_IGD_GM, "Intel Integrated Graphics Device"}, + {PCI_CHIP_GM45_GM, "Mobile IntelĀ® GM45 Express Chipset"}, + {PCI_CHIP_IGD_E_G, "Intel Integrated Graphics Device"}, + {PCI_CHIP_G45_G, "G45/G43"}, + {PCI_CHIP_Q45_G, "Q45/Q43"}, {-1, NULL} }; @@ -273,7 +276,10 @@ static PciChipsets I830PciChipsets[] = { {PCI_CHIP_G33_G, PCI_CHIP_G33_G, RES_SHARED_VGA}, {PCI_CHIP_Q35_G, PCI_CHIP_Q35_G, RES_SHARED_VGA}, {PCI_CHIP_Q33_G, PCI_CHIP_Q33_G, RES_SHARED_VGA}, - {PCI_CHIP_IGD_GM, PCI_CHIP_IGD_GM, RES_SHARED_VGA}, + {PCI_CHIP_GM45_GM, PCI_CHIP_GM45_GM, RES_SHARED_VGA}, + {PCI_CHIP_IGD_E_G, PCI_CHIP_IGD_E_G, RES_SHARED_VGA}, + {PCI_CHIP_G45_G, PCI_CHIP_G45_G, RES_SHARED_VGA}, + {PCI_CHIP_Q45_G, PCI_CHIP_Q45_G, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED} }; @@ -509,6 +515,10 @@ I830DetectMemory(ScrnInfoPtr pScrn) */ range = gtt_size + 4; + /* new 4 series hardware has seperate GTT stolen with GFX stolen */ + if (IS_G4X(pI830)) + range = 0; + if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) { switch (gmch_ctrl & I855_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: @@ -542,6 +552,22 @@ I830DetectMemory(ScrnInfoPtr pScrn) if (IS_I9XX(pI830)) memsize = MB(256) - KB(range); break; + case INTEL_GMCH_GMS_STOLEN_96M: + if (IS_I9XX(pI830)) + memsize = MB(96) - KB(range); + break; + case INTEL_GMCH_GMS_STOLEN_160M: + if (IS_I9XX(pI830)) + memsize = MB(160) - KB(range); + break; + case INTEL_GMCH_GMS_STOLEN_224M: + if (IS_I9XX(pI830)) + memsize = MB(224) - KB(range); + break; + case INTEL_GMCH_GMS_STOLEN_352M: + if (IS_I9XX(pI830)) + memsize = MB(352) - KB(range); + break; } } else { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { @@ -625,7 +651,7 @@ I830MapMMIO(ScrnInfoPtr pScrn) if (IS_I965G(pI830)) { - if (IS_IGD_GM(pI830)) { + if (IS_GM45(pI830) || IS_G4X(pI830)) { gttaddr = pI830->MMIOAddr + MB(2); pI830->GTTMapSize = MB(2); } else { @@ -896,12 +922,23 @@ I830SetupOutputs(ScrnInfoPtr pScrn) i830_lvds_init(pScrn); if (IS_I9XX(pI830)) { - i830_sdvo_init(pScrn, SDVOB); - i830_sdvo_init(pScrn, SDVOC); + if (INREG(SDVOB) & SDVO_DETECTED) { + Bool found = i830_sdvo_init(pScrn, SDVOB); + + if (!found && SUPPORTS_INTEGRATED_HDMI(pI830)) + i830_hdmi_init(pScrn, SDVOB); + } + + if (INREG(SDVOC) & SDVO_DETECTED) { + Bool found = i830_sdvo_init(pScrn, SDVOC); + + if (!found && SUPPORTS_INTEGRATED_HDMI(pI830)) + i830_hdmi_init(pScrn, SDVOC); + } } else { i830_dvo_init(pScrn); } - if (IS_I9XX(pI830) && !IS_I915G(pI830)) + if (IS_I9XX(pI830) && IS_MOBILE(pI830)) i830_tv_init(pScrn); for (o = 0; o < config->num_output; o++) @@ -934,7 +971,7 @@ i830_init_clock_gating(ScrnInfoPtr pScrn) /* Disable clock gating reported to work incorrectly according to the specs. */ - if (IS_IGD_GM(pI830)) { + if (IS_GM45(pI830)) { OUTREG(RENCLK_GATE_D1, 0); OUTREG(RENCLK_GATE_D2, 0); OUTREG(RAMCLK_GATE_D, 0); @@ -1179,9 +1216,18 @@ i830_detect_chipset(ScrnInfoPtr pScrn) case PCI_CHIP_Q33_G: chipname = "Q33"; break; - case PCI_CHIP_IGD_GM: + case PCI_CHIP_GM45_GM: + chipname = "Mobile IntelĀ® GM45 Express Chipset"; + break; + case PCI_CHIP_IGD_E_G: chipname = "Intel Integrated Graphics Device"; break; + case PCI_CHIP_G45_G: + chipname = "G45/G43"; + break; + case PCI_CHIP_Q45_G: + chipname = "Q45/Q43"; + break; default: chipname = "unknown chipset"; break; @@ -1939,14 +1985,23 @@ i830_set_dsparb(ScrnInfoPtr pScrn) * FIFO RAM entries equally between planes A and B. */ if (IS_I9XX(pI830)) { - if (IS_I965GM(pI830) || IS_IGD_GM(pI830)) + if (IS_I965GM(pI830) || IS_GM45(pI830)) OUTREG(DSPARB, (127 << DSPARB_CSTART_SHIFT) | (64 << DSPARB_BSTART_SHIFT)); else OUTREG(DSPARB, (95 << DSPARB_CSTART_SHIFT) | (48 << DSPARB_BSTART_SHIFT)); } else { - OUTREG(DSPARB, 254 << DSPARB_BEND_SHIFT | 128 << DSPARB_AEND_SHIFT); + if (IS_MOBILE(pI830)) { + /* The 830 has 288 entries, and the 855 has 256. */ + OUTREG(DSPARB, 254 << DSPARB_BEND_SHIFT | 128 << DSPARB_AEND_SHIFT); + } else { + /* The 845/865 only have a AEND field. Though the field size would + * allow 128 entries, the 865 rendered the cursor wrong then. + * The BIOS set it up for 96. + */ + OUTREG(DSPARB, 95 << DSPARB_AEND_SHIFT); + } } } @@ -2097,7 +2152,7 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->saveRAMCLK_GATE_D = INREG(RAMCLK_GATE_D); } - if (IS_I965GM(pI830) || IS_IGD_GM(pI830)) + if (IS_I965GM(pI830) || IS_GM45(pI830)) pI830->savePWRCTXA = INREG(PWRCTXA); if (IS_MOBILE(pI830) && !IS_I830(pI830)) @@ -2167,7 +2222,7 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(RAMCLK_GATE_D, pI830->saveRAMCLK_GATE_D); } - if (IS_I965GM(pI830) || IS_IGD_GM(pI830)) + if (IS_I965GM(pI830) || IS_GM45(pI830)) OUTREG(PWRCTXA, pI830->savePWRCTXA); /* @@ -2584,7 +2639,7 @@ i830_try_memory_allocation(ScrnInfoPtr pScrn) if (!i830_allocate_2d_memory(pScrn)) goto failed; - if (IS_I965GM(pI830) || IS_IGD_GM(pI830)) + if (IS_I965GM(pI830) || IS_GM45(pI830)) if (!i830_allocate_pwrctx(pScrn)) goto failed; @@ -3018,7 +3073,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) "needs 2D acceleration.\n"); pI830->XvEnabled = FALSE; } - if (!IS_IGD_GM(pI830) && pI830->overlay_regs == NULL) { + if (!OVERLAY_NOEXIST(pI830) && pI830->overlay_regs == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because the overlay register buffer " "allocation failed.\n"); @@ -3058,7 +3113,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) * alone in that case. * Also make sure the DRM can handle the swap. */ - if (I830LVDSPresent(pScrn) && !IS_I965GM(pI830) && !IS_IGD_GM(pI830) && + if (I830LVDSPresent(pScrn) && !IS_I965GM(pI830) && !IS_GM45(pI830) && (!pI830->directRenderingEnabled || (pI830->directRenderingEnabled && pI830->drmMinor >= 10))) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "adjusting plane->pipe mappings " diff --git a/src/i830_hdmi.c b/src/i830_hdmi.c new file mode 100644 index 00000000..b738463c --- /dev/null +++ b/src/i830_hdmi.c @@ -0,0 +1,233 @@ +/* + * Copyright Ā© 2007 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 <eric@anholt.net> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "i830.h" +#include "xf86Modes.h" +#include "i830_display.h" + +struct i830_hdmi_priv { + uint32_t output_reg; + + uint32_t save_SDVO; +}; + +static int +i830_hdmi_mode_valid(xf86OutputPtr output, DisplayModePtr mode) +{ + if (mode->Clock > 165000) + return MODE_CLOCK_HIGH; + + if (mode->Clock < 20000) + return MODE_CLOCK_LOW; + + return MODE_OK; +} + +static Bool +i830_hdmi_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + /* The HDMI output doesn't need the pixel multiplication that SDVO does, + * so no fixup. + */ + return TRUE; +} + +static void +i830_hdmi_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_hdmi_priv *dev_priv = intel_output->dev_priv; + I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcPtr crtc = output->crtc; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + uint32_t sdvox; + + sdvox = SDVO_ENCODING_HDMI | + SDVO_BORDER_ENABLE | + SDVO_VSYNC_ACTIVE_HIGH | + SDVO_HSYNC_ACTIVE_HIGH; + if (intel_crtc->pipe == 1) + sdvox |= SDVO_PIPE_B_SELECT; + + OUTREG(dev_priv->output_reg, sdvox); + POSTING_READ(dev_priv->output_reg); +} + +static void +i830_hdmi_dpms(xf86OutputPtr output, int mode) +{ + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_hdmi_priv *dev_priv = intel_output->dev_priv; + I830Ptr pI830 = I830PTR(pScrn); + uint32_t temp; + + if (mode == DPMSModeOff) { + temp = INREG(dev_priv->output_reg); + OUTREG(dev_priv->output_reg, temp & ~SDVO_ENABLE); + } else { + temp = INREG(dev_priv->output_reg); + OUTREG(dev_priv->output_reg, temp | SDVO_ENABLE); + } +} + +static void +i830_hdmi_save(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_hdmi_priv *dev_priv = intel_output->dev_priv; + I830Ptr pI830 = I830PTR(pScrn); + + dev_priv->save_SDVO = INREG(dev_priv->output_reg); +} + +static void +i830_hdmi_restore(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_hdmi_priv *dev_priv = intel_output->dev_priv; + I830Ptr pI830 = I830PTR(pScrn); + + OUTREG(dev_priv->output_reg, dev_priv->save_SDVO); +} + +/** + * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect HDMI connection. + * + * \return TRUE if HDMI port is connected. + * \return FALSE if HDMI port is disconnected. + */ +static xf86OutputStatus +i830_hdmi_detect(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_hdmi_priv *dev_priv = intel_output->dev_priv; + I830Ptr pI830 = I830PTR(pScrn); + uint32_t temp, bit; + + temp = INREG(PORT_HOTPLUG_EN); + + OUTREG(PORT_HOTPLUG_EN, + temp | + HDMIB_HOTPLUG_INT_EN | + HDMIC_HOTPLUG_INT_EN | + HDMID_HOTPLUG_INT_EN); + + POSTING_READ(PORT_HOTPLUG_EN); + + switch (dev_priv->output_reg) { + case SDVOB: + bit = HDMIB_HOTPLUG_INT_STATUS; + break; + case SDVOC: + bit = HDMIC_HOTPLUG_INT_STATUS; + break; + default: + return XF86OutputStatusUnknown; + } + + if ((INREG(PORT_HOTPLUG_STAT) & bit) != 0) + return XF86OutputStatusConnected; + else + return XF86OutputStatusDisconnected; +} + +static void +i830_hdmi_destroy (xf86OutputPtr output) +{ + I830OutputPrivatePtr intel_output = output->driver_private; + + if (intel_output != NULL) { + xf86DestroyI2CBusRec(intel_output->pDDCBus, FALSE, FALSE); + xfree(intel_output); + } +} + +static const xf86OutputFuncsRec i830_hdmi_output_funcs = { + .dpms = i830_hdmi_dpms, + .save = i830_hdmi_save, + .restore = i830_hdmi_restore, + .mode_valid = i830_hdmi_mode_valid, + .mode_fixup = i830_hdmi_mode_fixup, + .prepare = i830_output_prepare, + .mode_set = i830_hdmi_mode_set, + .commit = i830_output_commit, + .detect = i830_hdmi_detect, + .get_modes = i830_ddc_get_modes, + .destroy = i830_hdmi_destroy +}; + +void +i830_hdmi_init(ScrnInfoPtr pScrn, int output_reg) +{ + xf86OutputPtr output; + I830OutputPrivatePtr intel_output; + struct i830_hdmi_priv *dev_priv; + + output = xf86OutputCreate(pScrn, &i830_hdmi_output_funcs, + (output_reg == SDVOB) ? "HDMI-1" : "HDMI-2"); + if (!output) + return; + intel_output = xnfcalloc(sizeof (I830OutputPrivateRec) + + sizeof (struct i830_hdmi_priv), 1); + if (intel_output == NULL) { + xf86OutputDestroy(output); + return; + } + output->driver_private = intel_output; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; + + dev_priv = (struct i830_hdmi_priv *)(intel_output + 1); + dev_priv->output_reg = output_reg; + + intel_output->dev_priv = dev_priv; + intel_output->type = I830_OUTPUT_HDMI; + intel_output->pipe_mask = ((1 << 0) | (1 << 1)); + intel_output->clone_mask = (1 << I830_OUTPUT_HDMI); + + /* Set up the DDC bus. */ + if (output_reg == SDVOB) + I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOE, "HDMIDDC_B"); + else + I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "HDMIDDC_C"); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "HDMI output %d detected\n", + 1 + (output_reg - SDVOB)); +} diff --git a/src/i830_hwmc.c b/src/i830_hwmc.c index 7586ff71..787d93da 100644 --- a/src/i830_hwmc.c +++ b/src/i830_hwmc.c @@ -56,7 +56,7 @@ Bool intel_xvmc_probe(ScrnInfoPtr pScrn) return FALSE; if (IS_I9XX(pI830)) { - if (!IS_I965G(pI830)) + if (IS_I915(pI830)) ret = intel_xvmc_set_driver(&i915_xvmc_driver); /* else @@ -122,9 +122,10 @@ Bool intel_xvmc_screen_init(ScreenPtr pScreen) Bool intel_xvmc_init_batch(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + int size = KB(64); if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC] batch buffer", - &(xvmc_driver->batch), 8 * 1024, + &(xvmc_driver->batch), size, ALIGN_BOTH_ENDS)) return FALSE; diff --git a/src/i830_hwmc.h b/src/i830_hwmc.h index 6920e016..4db9aea6 100644 --- a/src/i830_hwmc.h +++ b/src/i830_hwmc.h @@ -47,6 +47,13 @@ #define XVMC_I945_MPEG2_VLD 0x04 #define XVMC_I965_MPEG2_VLD 0x08 +/* supported surface types */ +enum { + SURFACE_TYPE_MPEG2_MPML = FOURCC_XVMC, /* mpeg2 MP@ML */ + SURFACE_TYPE_MPEG1_MPML, /* mpeg1 MP@ML */ + SURFACE_TYPE_MAX +}; + /* common header for context private */ struct hwmc_buffer { diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 899c6cbf..c7f24342 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -63,6 +63,9 @@ struct i830_lvds_priv { /* The panel needs dithering enabled */ Bool panel_wants_dither; + /* The panel is in DPMS off */ + Bool dpmsoff; + /* restore backlight to this value */ int backlight_duty_cycle; @@ -80,6 +83,8 @@ struct i830_lvds_priv { * List of available kernel interfaces in priority order */ static char *backlight_interfaces[] = { + "asus-laptop", + "eeepc", "thinkpad_screen", "acpi_video1", "acpi_video0", @@ -129,7 +134,7 @@ i830_set_lvds_backlight_method(xf86OutputPtr output) if (i830_kernel_backlight_available(output)) { method = BCM_KERNEL; - } else if (IS_I965GM(pI830) || IS_IGD_GM(pI830)) { + } else if (IS_I965GM(pI830) || IS_GM45(pI830)) { blc_pwm_ctl2 = INREG(BLC_PWM_CTL2); if (blc_pwm_ctl2 & BLM_LEGACY_MODE2) method = BCM_COMBO; @@ -177,7 +182,7 @@ i830_lvds_get_backlight_max_native(xf86OutputPtr output) uint32_t pwm_ctl = INREG(BLC_PWM_CTL); int val; - if (IS_I965GM(pI830) || IS_IGD_GM(pI830)) { + if (IS_I965GM(pI830) || IS_GM45(pI830)) { val = ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK2) >> BACKLIGHT_MODULATION_FREQ_SHIFT2); } else { @@ -334,6 +339,7 @@ i830_lvds_get_backlight_kernel(xf86OutputPtr output) return 0; } + memset(val, 0, sizeof(val)); if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1) goto out_err; @@ -388,6 +394,10 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on) uint32_t pp_status; if (on) { + /* if we're going from on->on, be aware to current level. */ + if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff) + dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output); + /* * If we're going from off->on we may need to turn on the backlight. * We should use the saved value whenever possible, but on some @@ -405,12 +415,13 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on) } while ((pp_status & PP_ON) == 0); dev_priv->set_backlight(output, dev_priv->backlight_duty_cycle); + dev_priv->dpmsoff = FALSE; } else { /* * Only save the current backlight value if we're going from * on to off. */ - if (INREG(PP_CONTROL) & POWER_TARGET_ON) + if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff) dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output); dev_priv->set_backlight(output, 0); @@ -418,6 +429,8 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on) do { pp_status = INREG(PP_STATUS); } while (pp_status & PP_ON); + + dev_priv->dpmsoff = TRUE; } } @@ -440,14 +453,15 @@ i830_lvds_save (xf86OutputPtr output) ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); - if (IS_I965GM(pI830) || IS_IGD_GM(pI830)) + if (IS_I965GM(pI830) || IS_GM45(pI830)) pI830->saveBLC_PWM_CTL2 = INREG(BLC_PWM_CTL2); pI830->savePP_ON = INREG(LVDSPP_ON); pI830->savePP_OFF = INREG(LVDSPP_OFF); pI830->savePP_CONTROL = INREG(PP_CONTROL); pI830->savePP_CYCLE = INREG(PP_CYCLE); pI830->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL); - dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output); + if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff) + dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output); } static void @@ -456,7 +470,7 @@ i830_lvds_restore(xf86OutputPtr output) ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); - if (IS_I965GM(pI830) || IS_IGD_GM(pI830)) + if (IS_I965GM(pI830) || IS_GM45(pI830)) OUTREG(BLC_PWM_CTL2, pI830->saveBLC_PWM_CTL2); OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL); OUTREG(LVDSPP_ON, pI830->savePP_ON); @@ -1081,7 +1095,10 @@ i830_lvds_set_property(xf86OutputPtr output, Atom property, "RRConfigureOutputProperty error, %d\n", ret); } /* Set the current value of the backlight property */ - data = dev_priv->get_backlight(output); + if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff) + data = dev_priv->get_backlight(output); + else + data = dev_priv->backlight_duty_cycle; ret = RRChangeOutputProperty(output->randr_output, backlight_atom, XA_INTEGER, 32, PropModeReplace, 1, &data, FALSE, TRUE); @@ -1130,6 +1147,8 @@ i830_lvds_set_property(xf86OutputPtr output, Atom property, static Bool i830_lvds_get_property(xf86OutputPtr output, Atom property) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; struct i830_lvds_priv *dev_priv = intel_output->dev_priv; int ret; @@ -1140,8 +1159,11 @@ i830_lvds_get_property(xf86OutputPtr output, Atom property) */ if (property == backlight_atom) { int val; - val = dev_priv->get_backlight(output); - dev_priv->backlight_duty_cycle = val; + if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff) { + val = dev_priv->get_backlight(output); + dev_priv->backlight_duty_cycle = val; + } else + val = dev_priv->backlight_duty_cycle; ret = RRChangeOutputProperty(output->randr_output, backlight_atom, XA_INTEGER, 32, PropModeReplace, 1, &val, FALSE, TRUE); @@ -1319,6 +1341,9 @@ i830_lvds_init(ScrnInfoPtr pScrn) goto disable_exit; } + /* Update pI830 w/SSC info, if any */ + i830_bios_get_ssc(pScrn); + skip_panel_fixed_mode_setup: /* Blacklist machines with BIOSes that list an LVDS panel without actually diff --git a/src/i830_memory.c b/src/i830_memory.c index 3d6e245f..08a22019 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -450,7 +450,7 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size) /* Overlay and cursors, if physical, need to be allocated outside * of the kernel memory manager. */ - if (!OVERLAY_NOPHYSICAL(pI830) && !IS_IGD_GM(pI830)) { + if (!OVERLAY_NOPHYSICAL(pI830) && !OVERLAY_NOEXIST(pI830)) { mmsize -= ROUND_TO(OVERLAY_SIZE, GTT_PAGE_SIZE); } if (pI830->CursorNeedsPhysical) { @@ -462,7 +462,8 @@ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size) /* Can't do GEM on stolen memory */ mmsize -= pI830->stolen_size; - if (HWS_NEED_GFX(pI830) && IS_IGD_GM(pI830)) + /* new chipsets need non-stolen status page */ + if (HWS_NEED_GFX(pI830) && HWS_NEED_NONSTOLEN(pI830)) mmsize -= HWSTATUS_PAGE_SIZE; /* Create the aperture allocation */ @@ -1050,7 +1051,7 @@ i830_allocate_overlay(ScrnInfoPtr pScrn) if (!pI830->XvEnabled) return TRUE; - if (IS_IGD_GM(pI830)) + if (OVERLAY_NOEXIST(pI830)) return TRUE; if (!OVERLAY_NOPHYSICAL(pI830)) @@ -1304,7 +1305,7 @@ static void i830_setup_fb_compression(ScrnInfoPtr pScrn) goto out; } - if (IS_IGD_GM(pI830)) { + if (IS_GM45(pI830)) { /* Update i830_display.c too if compression ratio changes */ compressed_size = fb_height * (pScrn->displayWidth / 4); } else { @@ -1331,7 +1332,7 @@ static void i830_setup_fb_compression(ScrnInfoPtr pScrn) goto out; } - if (!IS_IGD_GM(pI830)) { + if (!IS_GM45(pI830)) { pI830->compressed_ll_buffer = i830_allocate_memory(pScrn, "compressed ll buffer", FBC_LL_SIZE + FBC_LL_PAD, KB(4), @@ -1681,7 +1682,7 @@ i830_allocate_hwstatus(ScrnInfoPtr pScrn) * (i.e. not through buffer objects). */ flags = NEED_LIFETIME_FIXED; - if (IS_IGD_GM(pI830)) + if (HWS_NEED_NONSTOLEN(pI830)) flags |= NEED_NON_STOLEN; pI830->hw_status = i830_allocate_memory(pScrn, "HW status", HWSTATUS_PAGE_SIZE, GTT_PAGE_SIZE, flags); @@ -2054,6 +2055,7 @@ I830CheckAvailableMemory(ScrnInfoPtr pScrn) return maxPages * 4; } +#ifdef INTEL_XVMC /* * Allocate memory for MC compensation */ @@ -2075,3 +2077,4 @@ Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name, return TRUE; } +#endif diff --git a/src/i830_quirks.c b/src/i830_quirks.c index 1bd8885c..5eb01be5 100644 --- a/src/i830_quirks.c +++ b/src/i830_quirks.c @@ -266,7 +266,9 @@ static i830_quirk i830_quirk_list[] = { { PCI_CHIP_I965_GM, 0x144d, 0xc510, quirk_ignore_tv }, /* HP Compaq 6730s has no TV output */ - { PCI_CHIP_IGD_GM, 0x103c, 0x30e8, quirk_ignore_tv }, + { PCI_CHIP_GM45_GM, 0x103c, 0x30e8, quirk_ignore_tv }, + /* HP Pavilion ze4944ea needs pipe A force quirk (See LP: #242389) */ + { PCI_CHIP_GM45_GM, 0x103c, 0x3084, quirk_pipea_force }, /* Thinkpad R31 needs pipe A force quirk */ { PCI_CHIP_I830_M, 0x1014, 0x0505, quirk_pipea_force }, @@ -284,10 +286,15 @@ static i830_quirk i830_quirk_list[] = { { PCI_CHIP_I915_GM, 0x1179, 0x0001, quirk_pipea_force }, /* Intel 855GM hardware (See LP: #216490) */ { PCI_CHIP_I855_GM, 0x1028, 0x00c8, quirk_pipea_force }, + /* Intel 855GM hardware (See Novell Bugzilla #406123) */ + { PCI_CHIP_I855_GM, 0x10cf, 0x1215, quirk_pipea_force }, /* ThinkPad X40 needs pipe A force quirk */ { PCI_CHIP_I855_GM, 0x1014, 0x0557, quirk_pipea_force }, + /* ThinkPad T60 needs pipe A force quirk (bug #16494) */ + { PCI_CHIP_I945_GM, 0x17aa, 0x201a, quirk_pipea_force }, + /* Sony vaio PCG-r600HFP (fix bug 13722) */ { PCI_CHIP_I830_M, 0x104d, 0x8100, quirk_ivch_dvob }, /* Sony vaio VGN-SZ4MN (See LP: #212163) */ diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 331059bf..d9b76d40 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -92,6 +92,9 @@ struct i830_sdvo_priv { */ struct i830_sdvo_tv_format tv_format; + /** supported encoding mode, used to determine whether HDMI is supported */ + struct i830_sdvo_encode encode; + /** DDC bus used by this SDVO output */ uint8_t ddc_bus; @@ -229,6 +232,19 @@ const static struct _sdvo_cmd_name { SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT), SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS), + /* HDMI op code */ + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE), }; static I2CSlaveAddr slaveAddr; @@ -741,6 +757,190 @@ i830_sdvo_get_mode_from_dtd(DisplayModePtr mode, struct i830_sdvo_dtd *dtd) } static Bool +i830_sdvo_get_supp_encode(xf86OutputPtr output, struct i830_sdvo_encode *encode) +{ + uint8_t status; + + i830_sdvo_write_cmd(output, SDVO_CMD_GET_SUPP_ENCODE, NULL, 0); + status = i830_sdvo_read_response(output, encode, sizeof(*encode)); + if (status != SDVO_CMD_STATUS_SUCCESS) { + memset(encode, 0, sizeof(*encode)); + return FALSE; + } + + return TRUE; +} + +static Bool +i830_sdvo_set_encode(xf86OutputPtr output, uint8_t mode) +{ + uint8_t status; + + i830_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODE, &mode, 1); + status = i830_sdvo_read_response(output, NULL, 0); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static Bool +i830_sdvo_set_colorimetry(xf86OutputPtr output, uint8_t mode) +{ + uint8_t status; + + i830_sdvo_write_cmd(output, SDVO_CMD_SET_COLORIMETRY, &mode, 1); + status = i830_sdvo_read_response(output, NULL, 0); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +#if 0 +static Bool +i830_sdvo_set_pixel_repli(xf86OutputPtr output, uint8_t repli) +{ + uint8_t status; + + i830_sdvo_write_cmd(output, SDVO_CMD_SET_PIXEL_REPLI, &repli, 1); + status = i830_sdvo_read_response(output, NULL, 0); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} +#endif + +static void i830_sdvo_dump_hdmi_buf(xf86OutputPtr output) +{ + int i, j; + uint8_t set_buf_index[2]; + uint8_t av_split; + uint8_t buf_size; + uint8_t buf[48]; + uint8_t *pos; + + i830_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_AV_SPLIT, NULL, 0); + i830_sdvo_read_response(output, &av_split, 1); + + for (i = 0; i <= av_split; i++) { + set_buf_index[0] = i; set_buf_index[1] = 0; + i830_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_INDEX, + set_buf_index, 2); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_INFO, NULL, 0); + i830_sdvo_read_response(output, &buf_size, 1); + + pos = buf; + for (j = 0; j <= buf_size; j += 8) { + i830_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_DATA, NULL, 0); + i830_sdvo_read_response(output, pos, 8); + pos += 8; + } + } +} + +static void i830_sdvo_set_hdmi_buf(xf86OutputPtr output, int index, + uint8_t *data, int8_t size, uint8_t tx_rate) +{ + uint8_t set_buf_index[2]; + + set_buf_index[0] = index; + set_buf_index[1] = 0; + + i830_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_INDEX, set_buf_index, 2); + + for (; size > 0; size -= 8) { + i830_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_DATA, data, 8); + data += 8; + } + + i830_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_TXRATE, &tx_rate, 1); +} + +static uint8_t i830_sdvo_calc_hbuf_csum(uint8_t *data, uint8_t size) +{ + uint8_t csum = 0; + int i; + + for (i = 0; i < size; i++) + csum += data[i]; + + return 0x100 - csum; +} + +#define DIP_TYPE_AVI 0x82 +#define DIP_VERSION_AVI 0x2 +#define DIP_LEN_AVI 13 + +struct dip_infoframe { + uint8_t type; + uint8_t version; + uint8_t len; + uint8_t checksum; + union { + struct { + /* Packet Byte #1 */ + uint8_t S:2; + uint8_t B:2; + uint8_t A:1; + uint8_t Y:2; + uint8_t rsvd1:1; + /* Packet Byte #2 */ + uint8_t R:4; + uint8_t M:2; + uint8_t C:2; + /* Packet Byte #3 */ + uint8_t SC:2; + uint8_t Q:2; + uint8_t EC:3; + uint8_t ITC:1; + /* Packet Byte #4 */ + uint8_t VIC:7; + uint8_t rsvd2:1; + /* Packet Byte #5 */ + uint8_t PR:4; + uint8_t rsvd3:4; + /* Packet Byte #6~13 */ + uint16_t top_bar_end; + uint16_t bottom_bar_start; + uint16_t left_bar_end; + uint16_t right_bar_start; + } avi; + struct { + /* Packet Byte #1 */ + uint8_t CC:3; + uint8_t rsvd1:1; + uint8_t CT:4; + /* Packet Byte #2 */ + uint8_t SS:2; + uint8_t SF:3; + uint8_t rsvd2:3; + /* Packet Byte #3 */ + uint8_t CXT:5; + uint8_t rsvd3:3; + /* Packet Byte #4 */ + uint8_t CA; + /* Packet Byte #5 */ + uint8_t rsvd4:3; + uint8_t LSV:4; + uint8_t DM_INH:1; + } audio; + uint8_t payload[28]; + } __attribute__ ((packed)) u; +} __attribute__((packed)); + +static void i830_sdvo_set_avi_infoframe(xf86OutputPtr output, + DisplayModePtr mode) +{ + struct dip_infoframe avi_if = { + .type = DIP_TYPE_AVI, + .version = DIP_VERSION_AVI, + .len = DIP_LEN_AVI, + }; + + avi_if.u.avi.PR = i830_sdvo_get_pixel_multiplier(mode) - 1; + avi_if.checksum = i830_sdvo_calc_hbuf_csum((uint8_t *)&avi_if, + 4 + avi_if.len); + i830_sdvo_set_hdmi_buf(output, 1, (uint8_t *)&avi_if, 4 + avi_if.len, + SDVO_HBUF_TX_VSYNC); +} + +static Bool i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { @@ -827,6 +1027,9 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, &in_out, sizeof(in_out)); status = i830_sdvo_read_response(output, NULL, 0); + if (dev_priv->encode.hdmi_rev) + i830_sdvo_set_avi_infoframe(output, mode); + i830_sdvo_get_dtd_from_mode(&input_dtd, mode); /* If it's a TV, we already set the output timing in mode_fixup. @@ -1203,6 +1406,15 @@ i830_sdvo_dump_device(xf86OutputPtr output) i830_sdvo_dump_cmd(output, SDVO_CMD_GET_TV_FORMAT); i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT); i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS); + + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_SUPP_ENCODE); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_ENCODE); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_PIXEL_REPLI); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_COLORIMETRY_CAP); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_COLORIMETRY); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER); + i830_sdvo_dump_cmd(output, SDVO_CMD_GET_AUDIO_STAT); + i830_sdvo_dump_hdmi_buf(output); } void @@ -1503,7 +1715,7 @@ i830_sdvo_select_ddc_bus(struct i830_sdvo_priv *dev_priv) dev_priv->ddc_bus = 1 << num_bits; } -void +Bool i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) { xf86OutputPtr output; @@ -1518,19 +1730,21 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,NULL); if (!output) - return; + return FALSE; intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) + sizeof (struct i830_sdvo_priv), 1); if (!intel_output) { xf86OutputDestroy (output); - return; + return FALSE; } output->driver_private = intel_output; + dev_priv = (struct i830_sdvo_priv *) (intel_output + 1); + intel_output->dev_priv = dev_priv; + output->interlaceAllowed = FALSE; output->doubleScanAllowed = FALSE; - dev_priv = (struct i830_sdvo_priv *) (intel_output + 1); intel_output->type = I830_OUTPUT_SDVO; intel_output->pipe_mask = ((1 << 0) | (1 << 1)); intel_output->clone_mask = (1 << I830_OUTPUT_SDVO); @@ -1546,7 +1760,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) if (i2cbus == NULL) { xf86OutputDestroy (output); - return; + return FALSE; } if (output_device == SDVOB) { @@ -1568,11 +1782,10 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) "Failed to initialize %s I2C device\n", SDVO_NAME(dev_priv)); xf86OutputDestroy (output); - return; + return FALSE; } intel_output->pI2CBus = i2cbus; - intel_output->dev_priv = dev_priv; /* Read the regs to test if we can talk to the device */ for (i = 0; i < 0x40; i++) { @@ -1581,7 +1794,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) "No SDVO device found on SDVO%c\n", output_device == SDVOB ? 'B' : 'C'); xf86OutputDestroy (output); - return; + return FALSE; } } @@ -1594,7 +1807,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) if (ddcbus == NULL) { xf86OutputDestroy (output); - return; + return FALSE; } if (output_device == SDVOB) ddcbus->BusName = "SDVOB DDC Bus"; @@ -1611,7 +1824,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) if (!xf86I2CBusInit(ddcbus)) { xf86OutputDestroy (output); - return; + return FALSE; } intel_output->pI2CBus = i2cbus; @@ -1620,17 +1833,22 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) i830_sdvo_get_capabilities(output, &dev_priv->caps); - if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) - { - dev_priv->controlled_output = SDVO_OUTPUT_TMDS0; - output->subpixel_order = SubPixelHorizontalRGB; - name_prefix="TMDS"; - } - else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) + if (dev_priv->caps.output_flags & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { - dev_priv->controlled_output = SDVO_OUTPUT_TMDS1; + if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) + dev_priv->controlled_output = SDVO_OUTPUT_TMDS0; + else + dev_priv->controlled_output = SDVO_OUTPUT_TMDS1; output->subpixel_order = SubPixelHorizontalRGB; name_prefix="TMDS"; + + i830_sdvo_get_supp_encode(output, &dev_priv->encode); + if (dev_priv->encode.hdmi_rev != 0) { + /* enable hdmi encoding mode if supported */ + i830_sdvo_set_encode(output, SDVO_ENCODE_HDMI); + i830_sdvo_set_colorimetry(output, SDVO_COLORIMETRY_RGB256); + name_prefix = "HDMI"; + } } else if (dev_priv->caps.output_flags & SDVO_OUTPUT_SVID0) { @@ -1670,7 +1888,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) if (!xf86OutputRename (output, name)) { xf86OutputDestroy (output); - return; + return FALSE; } i830_sdvo_select_ddc_bus(dev_priv); @@ -1718,4 +1936,5 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) REPORT_OUTPUT_FLAG(SDVO_OUTPUT_SCART1, "SCART1"); REPORT_OUTPUT_FLAG(SDVO_OUTPUT_LVDS1, "LVDS1"); + return TRUE; } diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h index 1368e43b..798a88df 100644 --- a/src/i830_sdvo.h +++ b/src/i830_sdvo.h @@ -25,7 +25,7 @@ * */ -void +Bool i830_sdvo_init(ScrnInfoPtr pScrn, int output_device); int diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h index dc2522a3..747f2cdd 100644 --- a/src/i830_sdvo_regs.h +++ b/src/i830_sdvo_regs.h @@ -511,3 +511,39 @@ struct i830_sdvo_enhancements_arg { # define SDVO_CONTROL_BUS_DDC2 (1 << 2) # define SDVO_CONTROL_BUS_DDC3 (1 << 3) +/* HDMI op codes */ +#define SDVO_CMD_GET_SUPP_ENCODE 0x9d +#define SDVO_CMD_GET_ENCODE 0x9e +#define SDVO_CMD_SET_ENCODE 0x9f + #define SDVO_ENCODE_DVI 0x0 + #define SDVO_ENCODE_HDMI 0x1 +#define SDVO_CMD_SET_PIXEL_REPLI 0x8b +#define SDVO_CMD_GET_PIXEL_REPLI 0x8c +#define SDVO_CMD_GET_COLORIMETRY_CAP 0x8d +#define SDVO_CMD_SET_COLORIMETRY 0x8e + #define SDVO_COLORIMETRY_RGB256 0x0 + #define SDVO_COLORIMETRY_RGB220 0x1 + #define SDVO_COLORIMETRY_YCrCb422 0x3 + #define SDVO_COLORIMETRY_YCrCb444 0x4 +#define SDVO_CMD_GET_COLORIMETRY 0x8f +#define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90 +#define SDVO_CMD_SET_AUDIO_STAT 0x91 +#define SDVO_CMD_GET_AUDIO_STAT 0x92 +#define SDVO_CMD_SET_HBUF_INDEX 0x93 +#define SDVO_CMD_GET_HBUF_INDEX 0x94 +#define SDVO_CMD_GET_HBUF_INFO 0x95 +#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 +#define SDVO_CMD_GET_HBUF_AV_SPLIT 0x97 +#define SDVO_CMD_SET_HBUF_DATA 0x98 +#define SDVO_CMD_GET_HBUF_DATA 0x99 +#define SDVO_CMD_SET_HBUF_TXRATE 0x9a +#define SDVO_CMD_GET_HBUF_TXRATE 0x9b + #define SDVO_HBUF_TX_DISABLED (0 << 6) + #define SDVO_HBUF_TX_ONCE (2 << 6) + #define SDVO_HBUF_TX_VSYNC (3 << 6) +#define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c + +struct i830_sdvo_encode{ + uint8_t dvi_rev; + uint8_t hdmi_rev; +} __attribute__ ((packed)); diff --git a/src/i830_tv.c b/src/i830_tv.c index cde929a7..651f77b3 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -1715,6 +1715,10 @@ i830_tv_init(ScrnInfoPtr pScrn) (tv_dac_off & TVDAC_STATE_CHG_EN) != 0) return; + i830_bios_get_tv(pScrn); + if (!pI830->tv_present) /* VBIOS claims no TV connector */ + return; + output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV"); if (!output) diff --git a/src/i830_video.c b/src/i830_video.c index e1095781..486f6708 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -620,7 +620,7 @@ I830InitVideo(ScreenPtr pScreen) } /* Set up overlay video if we can do it at this depth. */ - if (!IS_IGD_GM(pI830) && pScrn->bitsPerPixel != 8 && + if (!OVERLAY_NOEXIST(pI830) && pScrn->bitsPerPixel != 8 && pI830->overlay_regs != NULL) { overlayAdaptor = I830SetupImageVideoOverlay(pScreen); @@ -2210,7 +2210,8 @@ I830PutImage(ScrnInfoPtr pScrn, I830OverlayRegPtr overlay; PixmapPtr pPixmap; INT32 x1, x2, y1, y2; - int srcPitch, srcPitch2 = 0, dstPitch, destId; + int srcPitch = 0, srcPitch2 = 0, dstPitch, destId; + int dstPitch2 = 0; int top, left, npixels, nlines, size; BoxRec dstBox; int pitchAlignMask; @@ -2285,13 +2286,11 @@ I830PutImage(ScrnInfoPtr pScrn, case FOURCC_I420: srcPitch = (width + 0x3) & ~0x3; srcPitch2 = ((width >> 1) + 0x3) & ~0x3; + break; #ifdef INTEL_XVMC - if (pI830->IsXvMCSurface) { - srcPitch = (width + 0x3ff) & ~0x3ff; - srcPitch2 = ((width >> 1) + 0x3ff) & ~0x3ff; - } -#endif + case FOURCC_XVMC: break; +#endif case FOURCC_UYVY: case FOURCC_YUY2: default: @@ -2304,6 +2303,11 @@ I830PutImage(ScrnInfoPtr pScrn, */ if (pPriv->textured) { pitchAlignMask = 3; +#ifdef INTEL_XVMC + /* for i915 xvmc, hw requires at least 1kb aligned surface */ + if ((id == FOURCC_XVMC) && IS_I915(pI830)) + pitchAlignMask = 0x3ff; +#endif } else { if (IS_I965G(pI830)) pitchAlignMask = 255; @@ -2317,9 +2321,6 @@ I830PutImage(ScrnInfoPtr pScrn, switch (destId) { case FOURCC_YV12: case FOURCC_I420: -#ifdef INTEL_XVMC - case FOURCC_XVMC: -#endif if (pPriv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { dstPitch = ((height / 2) + pitchAlignMask) & ~pitchAlignMask; size = dstPitch * width * 3; @@ -2339,7 +2340,14 @@ I830PutImage(ScrnInfoPtr pScrn, size = dstPitch * height; } break; - default: +#ifdef INTEL_XVMC + case FOURCC_XVMC: + dstPitch = ((width / 2) + pitchAlignMask ) & ~pitchAlignMask; + dstPitch2 = (width + pitchAlignMask ) & ~pitchAlignMask; + size = 0; + break; +#endif + default: dstPitch = 0; size = 0; break; @@ -2384,24 +2392,35 @@ I830PutImage(ScrnInfoPtr pScrn, (pPriv->doubleBuffer ? size * 2 : size); /* fixup pointers */ - pPriv->YBuf0offset = pPriv->buf->offset; - if (pPriv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { - pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width); - pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2); - if(pPriv->doubleBuffer) { - pPriv->YBuf1offset = pPriv->YBuf0offset + size; - pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * width); - pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * width / 2); - } +#ifdef INTEL_XVMC + if (id == FOURCC_XVMC && IS_I915(pI830)) { + pPriv->YBuf0offset = (uint32_t)buf; + pPriv->VBuf0offset = pPriv->YBuf0offset + (dstPitch2 * height); + pPriv->UBuf0offset = pPriv->VBuf0offset + (dstPitch * height / 2); + destId = FOURCC_YV12; } else { - pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); - pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2); - if(pPriv->doubleBuffer) { - pPriv->YBuf1offset = pPriv->YBuf0offset + size; - pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); - pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2); +#endif + pPriv->YBuf0offset = pPriv->buf->offset; + if (pPriv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width); + pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2); + if(pPriv->doubleBuffer) { + pPriv->YBuf1offset = pPriv->YBuf0offset + size; + pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * width); + pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * width / 2); + } + } else { + pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); + pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2); + if(pPriv->doubleBuffer) { + pPriv->YBuf1offset = pPriv->YBuf0offset + size; + pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); + pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2); + } } +#ifdef INTEL_XVMC } +#endif /* Pick the idle buffer */ if (!pPriv->textured && *pI830->overlayOn && pPriv->doubleBuffer) @@ -2473,7 +2492,7 @@ I830PutImage(ScrnInfoPtr pScrn, src_w, src_h, drw_w, drw_h, pPixmap); } else { I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height, - dstPitch, x1, y1, x2, y2, + dstPitch, dstPitch2, x1, y1, x2, y2, src_w, src_h, drw_w, drw_h, pPixmap); } if (pPriv->textured) { diff --git a/src/i830_video.h b/src/i830_video.h index 52e6b4f8..91f767f9 100644 --- a/src/i830_video.h +++ b/src/i830_video.h @@ -78,7 +78,7 @@ typedef struct { void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, RegionPtr dstRegion, short width, - short height, int video_pitch, + short height, int video_pitch, int video_pitch2, int x1, int y1, int x2, int y2, short src_w, short src_h, short drw_w, short drw_h, diff --git a/src/i915_hwmc.c b/src/i915_hwmc.c index 50e11068..659638e1 100644 --- a/src/i915_hwmc.c +++ b/src/i915_hwmc.c @@ -111,7 +111,7 @@ static XF86MCImageIDList yv12_subpicture_list = static XF86MCSurfaceInfoRec i915_YV12_mpg2_surface = { - FOURCC_YV12, + SURFACE_TYPE_MPEG2_MPML, XVMC_CHROMA_FORMAT_420, 0, 720, @@ -127,7 +127,7 @@ static XF86MCSurfaceInfoRec i915_YV12_mpg2_surface = static XF86MCSurfaceInfoRec i915_YV12_mpg1_surface = { - FOURCC_YV12, + SURFACE_TYPE_MPEG1_MPML, XVMC_CHROMA_FORMAT_420, 0, 720, @@ -319,8 +319,8 @@ static Bool i915_allocate_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *c I830Ptr pI830 = I830PTR(pScrn); int flags = ALIGN_BOTH_ENDS; - if (IS_I915G(pI830) || IS_I915GM(pI830) || - IS_I945G(pI830) || IS_I945GM(pI830)) + /* on 915G/GM, load indirect can only use physical address...sigh */ + if (IS_I915G(pI830) || IS_I915GM(pI830)) flags |= NEED_PHYSICAL_ADDR; if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Static Indirect State", @@ -353,14 +353,14 @@ static Bool i915_allocate_xvmc_buffers(ScrnInfoPtr pScrn, I915XvMCContextPriv *c return FALSE; } - if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Correction Data Buffer", + if (!i830_allocate_xvmc_buffer(pScrn, "[XvMC]Correction Data Buffer", &(ctxpriv->mcCorrdata), 512 * 1024, ALIGN_BOTH_ENDS)) { return FALSE; } - if (0) - i830_describe_allocations(pScrn, 1, ""); + if (1) + i830_describe_allocations(pScrn, 1, "i915_mc: "); return TRUE; } @@ -500,29 +500,32 @@ static int i915_xvmc_create_context (ScrnInfoPtr pScrn, XvMCContextPtr pContext, contextRec->sis.handle = ctxpriv->sis_handle; contextRec->sis.offset = ctxpriv->mcStaticIndirectState->offset; contextRec->sis.size = ctxpriv->mcStaticIndirectState->size; - contextRec->sis.bus_addr = ctxpriv->mcStaticIndirectState->bus_addr; contextRec->ssb.handle = ctxpriv->ssb_handle; contextRec->ssb.offset = ctxpriv->mcSamplerState->offset; contextRec->ssb.size = ctxpriv->mcSamplerState->size; - contextRec->ssb.bus_addr = ctxpriv->mcSamplerState->bus_addr; contextRec->msb.handle = ctxpriv->msb_handle; contextRec->msb.offset = ctxpriv->mcMapState->offset; contextRec->msb.size = ctxpriv->mcMapState->size; - contextRec->msb.bus_addr = ctxpriv->mcMapState->bus_addr; contextRec->psp.handle = ctxpriv->psp_handle; contextRec->psp.offset = ctxpriv->mcPixelShaderProgram->offset; contextRec->psp.size = ctxpriv->mcPixelShaderProgram->size; - contextRec->psp.bus_addr = ctxpriv->mcPixelShaderProgram->bus_addr; contextRec->psc.handle = ctxpriv->psc_handle; contextRec->psc.offset = ctxpriv->mcPixelShaderConstants->offset; contextRec->psc.size = ctxpriv->mcPixelShaderConstants->size; - contextRec->psc.bus_addr = ctxpriv->mcPixelShaderConstants->bus_addr; contextRec->corrdata.handle = ctxpriv->corrdata_handle; contextRec->corrdata.offset = ctxpriv->mcCorrdata->offset; contextRec->corrdata.size = ctxpriv->mcCorrdata->size; contextRec->sarea_priv_offset = sizeof(XF86DRISAREARec); contextRec->deviceID = pI830DRI->deviceID; + if (IS_I915G(pI830) || IS_I915GM(pI830)) { + contextRec->sis.bus_addr = ctxpriv->mcStaticIndirectState->bus_addr; + contextRec->ssb.bus_addr = ctxpriv->mcSamplerState->bus_addr; + contextRec->msb.bus_addr = ctxpriv->mcMapState->bus_addr; + contextRec->psp.bus_addr = ctxpriv->mcPixelShaderProgram->bus_addr; + contextRec->psc.bus_addr = ctxpriv->mcPixelShaderConstants->bus_addr; + } + pXvMC->ncontexts++; pXvMC->contexts[i] = pContext->context_id; pXvMC->ctxprivs[i] = ctxpriv; @@ -787,7 +790,6 @@ static int i915_xvmc_put_image(ScrnInfoPtr pScrn, short height, Bool sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) { - I830Ptr pI830 = I830PTR(pScrn); I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; struct intel_xvmc_command *xvmc_cmd = (struct intel_xvmc_command *)buf; int ret; @@ -803,10 +805,8 @@ static int i915_xvmc_put_image(ScrnInfoPtr pScrn, return 1; } - buf = pI830->FbBase + - pXvMC->sfprivs[xvmc_cmd->srfNo]->surface->offset; - id = xvmc_cmd->real_id; - pI830->IsXvMCSurface = 1; + /* use char *buf to hold our surface offset...hacky! */ + buf = (unsigned char *)pXvMC->sfprivs[xvmc_cmd->srfNo]->surface->offset; break; default: return 0; @@ -816,7 +816,6 @@ static int i915_xvmc_put_image(ScrnInfoPtr pScrn, ret = pXvMC->savePutImage(pScrn, src_x, src_y, drw_x, drw_y, src_w, src_h, drw_w, drw_h, id, buf, width, height, sync, clipBoxes, data, pDraw); - pI830->IsXvMCSurface = 0; return ret; } diff --git a/src/i915_hwmc.h b/src/i915_hwmc.h index 7d90afcc..8f6557da 100644 --- a/src/i915_hwmc.h +++ b/src/i915_hwmc.h @@ -29,6 +29,7 @@ #include "i830_hwmc.h" +/* i915 hw requires surface to be at least 1KB aligned */ #define STRIDE(w) (((w) + 0x3ff) & ~0x3ff) #define SIZE_Y420(w, h) (h * STRIDE(w)) #define SIZE_UV420(w, h) ((h >> 1) * STRIDE(w >> 1)) diff --git a/src/i915_video.c b/src/i915_video.c index e27854ee..e2954a76 100644 --- a/src/i915_video.c +++ b/src/i915_video.c @@ -42,7 +42,7 @@ void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, RegionPtr dstRegion, - short width, short height, int video_pitch, + short width, short height, int video_pitch, int video_pitch2, int x1, int y1, int x2, int y2, short src_w, short src_h, short drw_w, short drw_h, PixmapPtr pPixmap) @@ -271,7 +271,13 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, ms3 |= (height - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); - OUT_BATCH(((video_pitch * 2 / 4) - 1) << MS4_PITCH_SHIFT); + /* check to see if Y has special pitch than normal double u/v pitch, + * e.g i915 XvMC hw requires at least 1K alignment, so Y pitch might + * be same as U/V's.*/ + if (video_pitch2) + OUT_BATCH(((video_pitch2 / 4) - 1) << MS4_PITCH_SHIFT); + else + OUT_BATCH(((video_pitch * 2 / 4) - 1) << MS4_PITCH_SHIFT); OUT_BATCH(pPriv->UBuf0offset); ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS; diff --git a/src/i965_render.c b/src/i965_render.c index 4a8f9b86..1cbfe242 100644 --- a/src/i965_render.c +++ b/src/i965_render.c @@ -59,6 +59,9 @@ do { \ } while(0) #endif +#define MAX_VERTEX_PER_COMPOSITE 24 +#define MAX_VERTEX_BUFFERS 256 + struct blendinfo { Bool dst_alpha; Bool src_alpha; @@ -500,7 +503,7 @@ typedef struct _gen4_state { struct brw_cc_viewport cc_viewport; PAD64 (brw_cc_viewport, 0); - float vb[(2 + 3 + 3) * 3]; /* (dst, src, mask) 3 vertices, 4 bytes */ + float vb[MAX_VERTEX_PER_COMPOSITE * MAX_VERTEX_BUFFERS]; } gen4_state_t; /** Private data for gen4 render accel implementation. */ @@ -510,6 +513,8 @@ struct gen4_render_state { int binding_table_index; int surface_state_index; + int vb_offset; + int vertex_size; }; /** @@ -968,6 +973,7 @@ i965_prepare_composite(int op, PicturePtr pSrcPicture, i830WaitSync(pScrn); render_state->binding_table_index = 0; render_state->surface_state_index = 0; + render_state->vb_offset = 0; } binding_table = card_state->binding_table + @@ -1035,7 +1041,7 @@ i965_prepare_composite(int op, PicturePtr pSrcPicture, BEGIN_BATCH(12); /* Match Mesa driver setup */ - if (IS_IGD_GM(pI830)) + if (IS_GM45(pI830) || IS_G4X(pI830)) OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_3D); else OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); @@ -1195,6 +1201,8 @@ i965_prepare_composite(int op, PicturePtr pSrcPicture, int selem = is_affine ? 2 : 3; uint32_t w_component; uint32_t src_format; + + render_state->vertex_size = 4 * (2 + nelem * selem); if (is_affine) { @@ -1206,17 +1214,9 @@ i965_prepare_composite(int op, PicturePtr pSrcPicture, src_format = BRW_SURFACEFORMAT_R32G32B32_FLOAT; w_component = BRW_VFCOMPONENT_STORE_SRC; } - BEGIN_BATCH(pMask?12:10); - /* Set up the pointer to our (single) vertex buffer */ - OUT_BATCH(BRW_3DSTATE_VERTEX_BUFFERS | 3); - OUT_BATCH((0 << VB0_BUFFER_INDEX_SHIFT) | - VB0_VERTEXDATA | - ((4 * (2 + nelem * selem)) << VB0_BUFFER_PITCH_SHIFT)); - OUT_BATCH(state_base_offset + offsetof(gen4_state_t, vb)); - OUT_BATCH(3); - OUT_BATCH(0); // ignore for VERTEXDATA, but still there - + BEGIN_BATCH(pMask?7:5); /* Set up our vertex elements, sourced from the single vertex buffer. + * that will be set up later. */ OUT_BATCH(BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * (1 + nelem)) - 1)); @@ -1271,6 +1271,7 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); gen4_state_t *card_state = pI830->gen4_render_state->card_state; + struct gen4_render_state *render_state = pI830->gen4_render_state; Bool has_mask; Bool is_affine_src, is_affine_mask, is_affine; float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3]; @@ -1351,12 +1352,12 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, } } - /* Wait for any existing composite rectangles to land before we overwrite - * the VB with the next one. - */ - i830WaitSync(pScrn); + if (render_state->vb_offset + MAX_VERTEX_PER_COMPOSITE >= ARRAY_SIZE(card_state->vb)) { + i830WaitSync(pScrn); + render_state->vb_offset = 0; + } - i = 0; + i = render_state->vb_offset; /* rect (x2,y2) */ vb[i++] = (float)(dstX + w); vb[i++] = (float)(dstY + h); @@ -1400,20 +1401,32 @@ i965_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, } assert (i * 4 <= sizeof(card_state->vb)); - { - BEGIN_BATCH(6); - OUT_BATCH(BRW_3DPRIMITIVE | - BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | - (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | - (0 << 9) | /* CTG - indirect vertex count */ - 4); - OUT_BATCH(3); /* vertex count per instance */ - OUT_BATCH(0); /* start vertex offset */ - OUT_BATCH(1); /* single instance */ - OUT_BATCH(0); /* start instance location */ - OUT_BATCH(0); /* index buffer offset, ignored */ - ADVANCE_BATCH(); - } + BEGIN_BATCH(12); + OUT_BATCH(MI_FLUSH); + /* Set up the pointer to our (single) vertex buffer */ + OUT_BATCH(BRW_3DSTATE_VERTEX_BUFFERS | 3); + OUT_BATCH((0 << VB0_BUFFER_INDEX_SHIFT) | + VB0_VERTEXDATA | + (render_state->vertex_size << VB0_BUFFER_PITCH_SHIFT)); + OUT_BATCH(render_state->card_state_offset + offsetof(gen4_state_t, vb) + + render_state->vb_offset * 4); + OUT_BATCH(3); + OUT_BATCH(0); // ignore for VERTEXDATA, but still there + + OUT_BATCH(BRW_3DPRIMITIVE | + BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | + (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | + (0 << 9) | /* CTG - indirect vertex count */ + 4); + OUT_BATCH(3); /* vertex count per instance */ + OUT_BATCH(0); /* start vertex offset */ + OUT_BATCH(1); /* single instance */ + OUT_BATCH(0); /* start instance location */ + OUT_BATCH(0); /* index buffer offset, ignored */ + ADVANCE_BATCH(); + + render_state->vb_offset = i; + #ifdef I830DEBUG ErrorF("sync after 3dprimitive\n"); I830Sync(pScrn); diff --git a/src/i965_video.c b/src/i965_video.c index 485c89a0..4c79259b 100644 --- a/src/i965_video.c +++ b/src/i965_video.c @@ -584,7 +584,7 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, { BEGIN_BATCH(12); /* Match Mesa driver setup */ - if (IS_IGD_GM(pI830)) + if (IS_GM45(pI830) || IS_G4X(pI830)) OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_3D); else OUT_BATCH(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); diff --git a/src/reg_dumper/.gitignore b/src/reg_dumper/.gitignore index f72a165e..b0f9b6f2 100644 --- a/src/reg_dumper/.gitignore +++ b/src/reg_dumper/.gitignore @@ -1,3 +1,4 @@ +intel_hotplug intel_idle intel_reg_dumper intel_stepping diff --git a/src/reg_dumper/Makefile.am b/src/reg_dumper/Makefile.am index 1c8db204..11275814 100644 --- a/src/reg_dumper/Makefile.am +++ b/src/reg_dumper/Makefile.am @@ -1,4 +1,4 @@ -noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping intel_statuspage +noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping intel_statuspage intel_hotplug intel_reg_dumper_SOURCES = \ main.c \ @@ -12,6 +12,12 @@ intel_idle_SOURCES = \ xprintf.c \ ../i830_debug.c +intel_hotplug_SOURCES = \ + hotplug.c \ + reg_dumper.h \ + xprintf.c \ + ../i830_debug.c + intel_stepping_SOURCES = \ stepping.c @@ -20,6 +26,7 @@ intel_statuspage_SOURCES = \ reg_dumper.h \ util.c +intel_hotplug_LDADD = $(PCIACCESS_LIBS) intel_reg_dumper_LDADD = $(PCIACCESS_LIBS) intel_idle_LDADD = $(PCIACCESS_LIBS) intel_stepping_LDADD = $(PCIACCESS_LIBS) diff --git a/src/reg_dumper/hotplug.c b/src/reg_dumper/hotplug.c new file mode 100644 index 00000000..68fe5842 --- /dev/null +++ b/src/reg_dumper/hotplug.c @@ -0,0 +1,151 @@ +/* + * Copyright Ā© 2007 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 <eric@anholt.net> + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <pciaccess.h> +#include <err.h> +#include <unistd.h> + +#include "reg_dumper.h" +#include "../i810_reg.h" + +struct idle_flags { + uint32_t instdone_flag; + char *name; + unsigned int count; +}; + +int main(int argc, char **argv) +{ + struct pci_device *dev; + I830Rec i830; + I830Ptr pI830 = &i830; + ScrnInfoRec scrn; + int err, mmio_bar; + void *mmio; + int i; + + err = pci_system_init(); + if (err != 0) { + fprintf(stderr, "Couldn't initialize PCI system: %s\n", strerror(err)); + exit(1); + } + + /* Grab the graphics card */ + dev = pci_device_find_by_slot(0, 0, 2, 0); + if (dev == NULL) + errx(1, "Couldn't find graphics card"); + + err = pci_device_probe(dev); + if (err != 0) { + fprintf(stderr, "Couldn't probe graphics card: %s\n", strerror(err)); + exit(1); + } + + if (dev->vendor_id != 0x8086) + errx(1, "Graphics card is non-intel"); + + i830.PciInfo = &i830.pci_info_rec; + i830.PciInfo->chipType = dev->device_id; + + i830.pci_dev = dev; + + mmio_bar = IS_I9XX((&i830)) ? 0 : 1; + + err = pci_device_map_range (dev, + dev->regions[mmio_bar].base_addr, + dev->regions[mmio_bar].size, + PCI_DEV_MAP_FLAG_WRITABLE, + &mmio); + + if (err != 0) { + fprintf(stderr, "Couldn't map MMIO region: %s\n", strerror(err)); + exit(1); + } + i830.mmio = mmio; + + scrn.scrnIndex = 0; + scrn.pI830 = &i830; + + OUTREG(SDVOB, (0x0 << 10)); + OUTREG(SDVOC, (0x0 << 10)); + + OUTREG(PORT_HOTPLUG_EN, + (1 << 29) | + (1 << 28) | + (1 << 27) | + SDVOB_HOTPLUG_INT_EN | + SDVOC_HOTPLUG_INT_EN | + (1 << 24) | + CRT_HOTPLUG_INT_EN | + TV_HOTPLUG_INT_EN | + CRT_HOTPLUG_INT_EN); + + for (i = 0;; i++) { + OUTREG(PORT_HOTPLUG_STAT, + (1 << 20) | + (1 << 19) | + (1 << 18) | + (1 << 17) | + CRT_HOTPLUG_INT_STATUS | + TV_HOTPLUG_INT_STATUS | + SDVOC_HOTPLUG_INT_STATUS | + SDVOB_HOTPLUG_INT_STATUS); + INREG(PORT_HOTPLUG_STAT); + + usleep(500 * 1000); + + printf("%5d: 0x%08x\n", i, INREG(PORT_HOTPLUG_STAT)); + sleep(1); + } + + return 0; +} + +void xf86DrvMsg(int scrnIndex, int severity, const char *format, ...) +{ + va_list va; + + switch (severity) { + case X_INFO: + printf("(II): "); + break; + case X_WARNING: + printf("(WW): "); + break; + case X_ERROR: + printf("(EE): "); + break; + } + + va_start(va, format); + vprintf(format, va); + va_end(va); +} diff --git a/src/xvmc/I810XvMC.c b/src/xvmc/I810XvMC.c index 03be2514..ce5395ac 100644 --- a/src/xvmc/I810XvMC.c +++ b/src/xvmc/I810XvMC.c @@ -130,7 +130,6 @@ Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context) { i810XvMCContext *pI810XvMC; - char busIdString[10]; int priv_count; uint *priv_data; uint magic; @@ -217,7 +216,6 @@ Status XvMCCreateContext(Display *display, XvPortID port, /* Open DRI Device */ if((pI810XvMC->fd = drmOpen("i810",NULL)) < 0) { printf("DRM Device for i810 could not be opened.\n"); - free(busIdString); free(pI810XvMC); return BadAccess; } /* !pI810XvMC->fd */ diff --git a/src/xvmc/i915_structs.h b/src/xvmc/i915_structs.h index a25d7349..b5185cb7 100644 --- a/src/xvmc/i915_structs.h +++ b/src/xvmc/i915_structs.h @@ -28,6 +28,8 @@ #ifndef _I915_STRUCTS_H #define _I915_STRUCTS_H +#include <stdint.h> + /* MI_INSTRUCTION */ #define CMD_MI 0x00 @@ -352,7 +354,7 @@ struct i915_3dstate_dest_buffer_variables_mpeg unsigned rcontrol : 1; unsigned decode_mode : 2; } dw1; - + struct { unsigned pad0 : 1; unsigned picture_coding_type : 2; @@ -372,6 +374,15 @@ struct i915_3dstate_dest_buffer_variables_mpeg } dw2; }; +struct i915_mc_static_indirect_state_buffer { + struct i915_3dstate_buffer_info dest_y; + struct i915_3dstate_buffer_info dest_u; + struct i915_3dstate_buffer_info dest_v; + struct i915_3dstate_dest_buffer_variables dest_buf; + struct i915_3dstate_dest_buffer_variables_mpeg dest_buf_mpeg; + struct i915_3dstate_buffer_info corr; +}; + #define MAP_MAP0 0x0001 #define MAP_MAP1 0x0002 #define MAP_MAP2 0x0004 @@ -432,7 +443,18 @@ struct i915_3dstate_map_state unsigned map_mask : 16; unsigned pad0 : 16; } dw1; -// struct texture_map *tms; +}; + +struct i915_mc_map_state { + struct i915_3dstate_map_state y_map; + struct texture_map y_forward; + struct texture_map y_backward; + struct i915_3dstate_map_state u_map; + struct texture_map u_forward; + struct texture_map u_backward; + struct i915_3dstate_map_state v_map; + struct texture_map v_forward; + struct texture_map v_backward; }; #define SAMPLER_SAMPLER0 0x0001 @@ -532,6 +554,9 @@ struct i915_3dstate_sampler_state unsigned sampler_masker : 16; unsigned pad0 : 16; } dw1; + /* we always use two samplers for mc */ + struct texture_sampler sampler0; + struct texture_sampler sampler1; }; struct arithmetic_inst @@ -641,17 +666,48 @@ union shader_inst struct declaration_inst d; }; +struct i915_3dstate_pixel_shader_header { + unsigned length : 9; + unsigned pad0 : 6; + unsigned retain : 1; + unsigned opcode : 13; + unsigned type : 3; +}; + struct i915_3dstate_pixel_shader_program { - struct { - unsigned length : 9; - unsigned pad0 : 6; - unsigned retain : 1; - unsigned opcode : 13; - unsigned type : 3; - } dw0; - - // union shader_inst *insts; + struct i915_3dstate_pixel_shader_header shader0; + /* mov oC, c0.0000 */ + uint32_t inst0[3]; + + struct i915_3dstate_pixel_shader_header shader1; + /* dcl t0.xy */ + /* dcl t1.xy */ + /* dcl_2D s0 */ + /* texld r0, t0, s0 */ + /* mov oC, r0 */ + uint32_t inst1[3*5]; + + struct i915_3dstate_pixel_shader_header shader2; + /* dcl t2.xy */ + /* dcl t3.xy */ + /* dcl_2D s1 */ + /* texld r0, t2, s1 */ + /* mov oC, r0 */ + uint32_t inst2[3*5]; + + struct i915_3dstate_pixel_shader_header shader3; + /* dcl t0.xy */ + /* dcl t1.xy */ + /* dcl t2.xy */ + /* dcl t3.xy */ + /* dcl_2D s0 */ + /* dcl_2D s1 */ + /* texld r0, t0, s0 */ + /* texld r0, t2, s1 */ + /* add r0, r0, r1*/ + /* mov oC, r0 */ + uint32_t inst3[3*10]; }; #define REG_CR0 0x00000001 @@ -707,7 +763,8 @@ struct i915_3dstate_pixel_shader_constants struct { unsigned reg_mask; } dw1; - // struct shader_constant *consts; + /* we only need one constant */ + struct shader_constant value; }; #define BLOCK_SIS 0x01 diff --git a/src/xvmc/i915_xvmc.c b/src/xvmc/i915_xvmc.c index 519de5a3..c32073a1 100644 --- a/src/xvmc/i915_xvmc.c +++ b/src/xvmc/i915_xvmc.c @@ -39,9 +39,9 @@ SIZE_Y420(surface->width, surface->height)) typedef union { - short s[4]; - uint u[2]; -} su_t; + int16_t component[2]; + int32_t v; +} vector_t; #if 0 static int findOverlap(unsigned int width, unsigned int height, @@ -81,577 +81,6 @@ static int findOverlap(unsigned int width, unsigned int height, } #endif -static void i915_flush(int map, int render) -{ - struct i915_mi_flush mi_flush; - - memset(&mi_flush, 0, sizeof(mi_flush)); - mi_flush.dw0.type = CMD_MI; - mi_flush.dw0.opcode = OPC_MI_FLUSH; - mi_flush.dw0.map_cache_invalidate = map; - mi_flush.dw0.render_cache_flush_inhibit = render; - - intelBatchbufferData(&mi_flush, sizeof(mi_flush), 0); -} - -/* for MC picture rendering */ -static void i915_mc_static_indirect_state_buffer(XvMCContext *context, - XvMCSurface *surface, - unsigned int picture_structure, - unsigned int flags, - unsigned int picture_coding_type) -{ - struct i915_3dstate_buffer_info *buffer_info; - struct i915_3dstate_dest_buffer_variables *dest_buffer_variables; - struct i915_3dstate_dest_buffer_variables_mpeg *dest_buffer_variables_mpeg; - i915XvMCSurface *pI915Surface = (i915XvMCSurface *)surface->privData; - i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; - unsigned int w = surface->width; - - /* 3DSTATE_BUFFER_INFO */ - /* DEST Y */ - buffer_info = (struct i915_3dstate_buffer_info *)pI915XvMC->sis.map; - memset(buffer_info, 0, sizeof(*buffer_info)); - buffer_info->dw0.type = CMD_3D; - buffer_info->dw0.opcode = OPC_3DSTATE_BUFFER_INFO; - buffer_info->dw0.length = 1; - buffer_info->dw1.aux_id = 0; - buffer_info->dw1.buffer_id = BUFFERID_COLOR_BACK; - buffer_info->dw1.fence_regs = 0; /* disabled */ /* FIXME: tiled y for performance */ - buffer_info->dw1.tiled_surface = 0; /* linear */ - buffer_info->dw1.walk = TILEWALK_XMAJOR; - buffer_info->dw1.pitch = (pI915Surface->yStride >> 2); /* in DWords */ - buffer_info->dw2.base_address = (YOFFSET(pI915Surface) >> 2); /* starting DWORD address */ - - /* DEST U */ - ++buffer_info; - memset(buffer_info, 0, sizeof(*buffer_info)); - buffer_info->dw0.type = CMD_3D; - buffer_info->dw0.opcode = OPC_3DSTATE_BUFFER_INFO; - buffer_info->dw0.length = 1; - buffer_info->dw1.aux_id = 0; - buffer_info->dw1.buffer_id = BUFFERID_COLOR_AUX; - buffer_info->dw1.fence_regs = 0; - buffer_info->dw1.tiled_surface = 0; - buffer_info->dw1.walk = TILEWALK_XMAJOR; - buffer_info->dw1.pitch = (pI915Surface->uvStride >> 2); /* in DWords */ - buffer_info->dw2.base_address = (UOFFSET(pI915Surface) >> 2); /* starting DWORD address */ - - /* DEST V */ - ++buffer_info; - memset(buffer_info, 0, sizeof(*buffer_info)); - buffer_info->dw0.type = CMD_3D; - buffer_info->dw0.opcode = OPC_3DSTATE_BUFFER_INFO; - buffer_info->dw0.length = 1; - buffer_info->dw1.aux_id = 1; - buffer_info->dw1.buffer_id = BUFFERID_COLOR_AUX; - buffer_info->dw1.fence_regs = 0; - buffer_info->dw1.tiled_surface = 0; - buffer_info->dw1.walk = TILEWALK_XMAJOR; - buffer_info->dw1.pitch = (pI915Surface->uvStride >> 2); /* in Dwords */ - buffer_info->dw2.base_address = (VOFFSET(pI915Surface) >> 2); /* starting DWORD address */ - - /* 3DSTATE_DEST_BUFFER_VARIABLES */ - dest_buffer_variables = (struct i915_3dstate_dest_buffer_variables *)(++buffer_info); - memset(dest_buffer_variables, 0, sizeof(*dest_buffer_variables)); - dest_buffer_variables->dw0.type = CMD_3D; - dest_buffer_variables->dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES; - dest_buffer_variables->dw0.length = 0; - dest_buffer_variables->dw1.dest_v_bias = 8; /* 0.5 */ - dest_buffer_variables->dw1.dest_h_bias = 8; /* 0.5 */ - dest_buffer_variables->dw1.color_fmt = COLORBUFFER_8BIT; - dest_buffer_variables->dw1.v_ls = 0; - dest_buffer_variables->dw1.v_ls_offset = 0; - - if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { - ; - } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) { - dest_buffer_variables->dw1.v_ls = 1; - } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_BOTTOM_FIELD) { - dest_buffer_variables->dw1.v_ls = 1; - dest_buffer_variables->dw1.v_ls_offset = 1; - } - - /* 3DSTATE_DEST_BUFFER_VARIABLES_MPEG */ - dest_buffer_variables_mpeg = (struct i915_3dstate_dest_buffer_variables_mpeg *)(++dest_buffer_variables); - memset(dest_buffer_variables_mpeg, 0, sizeof(*dest_buffer_variables_mpeg)); - dest_buffer_variables_mpeg->dw0.type = CMD_3D; - dest_buffer_variables_mpeg->dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG; - dest_buffer_variables_mpeg->dw0.length = 1; - dest_buffer_variables_mpeg->dw1.decode_mode = MPEG_DECODE_MC; - dest_buffer_variables_mpeg->dw1.rcontrol = 0; /* for MPEG-1/MPEG-2 */ - dest_buffer_variables_mpeg->dw1.bidir_avrg_control = 0; /* for MPEG-1/MPEG-2/MPEG-4 */ - dest_buffer_variables_mpeg->dw1.abort_on_error = 1; - dest_buffer_variables_mpeg->dw1.intra8 = 0; /* 16-bit formatted correction data */ - dest_buffer_variables_mpeg->dw1.tff = 1; - - if (picture_structure & XVMC_FRAME_PICTURE) { - ; - } else if (picture_structure & XVMC_TOP_FIELD) { - if (flags & XVMC_SECOND_FIELD) - dest_buffer_variables_mpeg->dw1.tff = 0; - else - dest_buffer_variables_mpeg->dw1.tff = 1; - } else if (picture_structure & XVMC_BOTTOM_FIELD) { - if (flags & XVMC_SECOND_FIELD) - dest_buffer_variables_mpeg->dw1.tff = 1; - else - dest_buffer_variables_mpeg->dw1.tff = 0; - } - - dest_buffer_variables_mpeg->dw1.v_subsample_factor = MC_SUB_1V; - dest_buffer_variables_mpeg->dw1.h_subsample_factor = MC_SUB_1H; - dest_buffer_variables_mpeg->dw1.picture_width = (w >> 4); /* in macroblocks */ - dest_buffer_variables_mpeg->dw2.picture_coding_type = picture_coding_type; - - /* 3DSATE_BUFFER_INFO */ - /* CORRECTION DATA */ - buffer_info = (struct i915_3dstate_buffer_info *)(++dest_buffer_variables_mpeg); - memset(buffer_info, 0, sizeof(*buffer_info)); - buffer_info->dw0.type = CMD_3D; - buffer_info->dw0.opcode = OPC_3DSTATE_BUFFER_INFO; - buffer_info->dw0.length = 1; - buffer_info->dw1.aux_id = 0; - buffer_info->dw1.buffer_id = BUFFERID_MC_INTRA_CORR; - buffer_info->dw1.aux_id = 0; - buffer_info->dw1.fence_regs = 0; - buffer_info->dw1.tiled_surface = 0; - buffer_info->dw1.walk = 0; - buffer_info->dw1.pitch = 0; - buffer_info->dw2.base_address = (pI915XvMC->corrdata.offset >> 2); /* starting DWORD address */ -} - -static void i915_mc_map_state_buffer(XvMCContext *context, - i915XvMCSurface *privTarget, - i915XvMCSurface *privPast, - i915XvMCSurface *privFuture) -{ - struct i915_3dstate_map_state *map_state; - struct texture_map *tm; - i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; - unsigned int w = context->width, h = context->height; - - /* 3DSATE_MAP_STATE: Y */ - map_state = (struct i915_3dstate_map_state *)pI915XvMC->msb.map; - memset(map_state, 0, sizeof(*map_state)); - map_state->dw0.type = CMD_3D; - map_state->dw0.opcode = OPC_3DSTATE_MAP_STATE; - map_state->dw0.retain = 1; - map_state->dw0.length = 6; - map_state->dw1.map_mask = MAP_MAP0 | MAP_MAP1; - - /* texture map: Forward (Past) */ - tm = (struct texture_map *)(++map_state); - memset(tm, 0, sizeof(*tm)); - tm->tm0.v_ls_offset = 0; - tm->tm0.v_ls = 0; - tm->tm0.base_address = (YOFFSET(privPast) >> 2); - tm->tm1.tile_walk = TILEWALK_XMAJOR; /* FIXME: tiled y for performace */ - tm->tm1.tiled_surface = 0; - tm->tm1.utilize_fence_regs = 0; - tm->tm1.texel_fmt = 0; /* 8bit */ - tm->tm1.surface_fmt = 1; /* 8bit */ - tm->tm1.width = w - 1; - tm->tm1.height = h - 1; - tm->tm2.depth = 0; - tm->tm2.max_lod = 0; - tm->tm2.cube_face = 0; - tm->tm2.pitch = (privPast->yStride >> 2) - 1; /* in DWords - 1 */ - - /* texture map: Backward (Future) */ - ++tm; - memset(tm, 0, sizeof(*tm)); - tm->tm0.v_ls_offset = 0; - tm->tm0.v_ls = 0; - tm->tm0.base_address = (YOFFSET(privFuture) >> 2); - tm->tm1.tile_walk = TILEWALK_XMAJOR; - tm->tm1.tiled_surface = 0; - tm->tm1.utilize_fence_regs = 0; - tm->tm1.texel_fmt = 0; /* 8bit */ - tm->tm1.surface_fmt = 1; /* 8bit */ - tm->tm1.width = w - 1; - tm->tm1.height = h - 1; - tm->tm2.depth = 0; - tm->tm2.max_lod = 0; - tm->tm2.cube_face = 0; - tm->tm2.pitch = (privFuture->yStride >> 2) - 1; - - /* 3DSATE_MAP_STATE: U */ - map_state = (struct i915_3dstate_map_state *)(++tm); - memset(map_state, 0, sizeof(*map_state)); - map_state->dw0.type = CMD_3D; - map_state->dw0.opcode = OPC_3DSTATE_MAP_STATE; - map_state->dw0.retain = 1; - map_state->dw0.length = 6; - map_state->dw1.map_mask = MAP_MAP0 | MAP_MAP1; - - /* texture map: Forward */ - tm = (struct texture_map *)(++map_state); - memset(tm, 0, sizeof(*tm)); - tm->tm0.v_ls_offset = 0; - tm->tm0.v_ls = 0; - tm->tm0.base_address = (UOFFSET(privPast) >> 2); - tm->tm1.tile_walk = TILEWALK_XMAJOR; - tm->tm1.tiled_surface = 0; - tm->tm1.utilize_fence_regs = 0; - tm->tm1.texel_fmt = 0; /* 8bit */ - tm->tm1.surface_fmt = 1; /* 8bit */ - tm->tm1.width = (w >> 1) - 1; - tm->tm1.height = (h >> 1) - 1; - tm->tm2.depth = 0; - tm->tm2.max_lod = 0; - tm->tm2.cube_face = 0; - tm->tm2.pitch = (privPast->uvStride >> 2) - 1; /* in DWords - 1 */ - - /* texture map: Backward */ - ++tm; - memset(tm, 0, sizeof(*tm)); - tm->tm0.v_ls_offset = 0; - tm->tm0.v_ls = 0; - tm->tm0.base_address = (UOFFSET(privFuture) >> 2); - tm->tm1.tile_walk = TILEWALK_XMAJOR; - tm->tm1.tiled_surface = 0; - tm->tm1.utilize_fence_regs = 0; - tm->tm1.texel_fmt = 0; - tm->tm1.surface_fmt = 1; - tm->tm1.width = (w >> 1) - 1; - tm->tm1.height = (h >> 1) - 1; - tm->tm2.depth = 0; - tm->tm2.max_lod = 0; - tm->tm2.cube_face = 0; - tm->tm2.pitch = (privFuture->uvStride >> 2) - 1; - - /* 3DSATE_MAP_STATE: V */ - map_state = (struct i915_3dstate_map_state *)(++tm); - memset(map_state, 0, sizeof(*map_state)); - map_state->dw0.type = CMD_3D; - map_state->dw0.opcode = OPC_3DSTATE_MAP_STATE; - map_state->dw0.retain = 1; - map_state->dw0.length = 6; - map_state->dw1.map_mask = MAP_MAP0 | MAP_MAP1; - - /* texture map: Forward */ - tm = (struct texture_map *)(++map_state); - memset(tm, 0, sizeof(*tm)); - tm->tm0.v_ls_offset = 0; - tm->tm0.v_ls = 0; - tm->tm0.base_address = (VOFFSET(privPast) >> 2); - tm->tm1.tile_walk = TILEWALK_XMAJOR; - tm->tm1.tiled_surface = 0; - tm->tm1.utilize_fence_regs = 0; - tm->tm1.texel_fmt = 0; - tm->tm1.surface_fmt = 1; - tm->tm1.width = (w >> 1) - 1; - tm->tm1.height = (h >> 1) - 1; - tm->tm2.depth = 0; - tm->tm2.max_lod = 0; - tm->tm2.cube_face = 0; - tm->tm2.pitch = (privPast->uvStride >> 2) - 1; /* in DWords - 1 */ - - /* texture map: Backward */ - ++tm; - memset(tm, 0, sizeof(*tm)); - tm->tm0.v_ls_offset = 0; - tm->tm0.v_ls = 0; - tm->tm0.base_address = (VOFFSET(privFuture) >> 2); - tm->tm1.tile_walk = TILEWALK_XMAJOR; - tm->tm1.tiled_surface = 0; - tm->tm1.utilize_fence_regs = 0; - tm->tm1.texel_fmt = 0; - tm->tm1.surface_fmt = 1; - tm->tm1.width = (w >> 1) - 1; - tm->tm1.height = (h >> 1) - 1; - tm->tm2.depth = 0; - tm->tm2.max_lod = 0; - tm->tm2.cube_face = 0; - tm->tm2.pitch = (privFuture->uvStride >> 2) - 1; -} - -static void i915_mc_load_sis_msb_buffers(XvMCContext *context) -{ - struct i915_3dstate_load_indirect *load_indirect; - sis_state *sis = NULL; - msb_state *msb = NULL; - i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; - void *base = NULL; - unsigned int size; - int mem_select = 1; - - /* 3DSTATE_LOAD_INDIRECT */ - size = sizeof(*load_indirect) + sizeof(*sis) + sizeof(*msb); - base = calloc(1, size); - load_indirect = (struct i915_3dstate_load_indirect *)base; - load_indirect->dw0.type = CMD_3D; - load_indirect->dw0.opcode = OPC_3DSTATE_LOAD_INDIRECT; - load_indirect->dw0.block_mask = BLOCK_SIS | BLOCK_MSB; - load_indirect->dw0.length = (size >> 2) - 2; - - if (pI915XvMC->deviceID == PCI_CHIP_I915_G || - pI915XvMC->deviceID == PCI_CHIP_I915_GM || - pI915XvMC->deviceID == PCI_CHIP_I945_G || - pI915XvMC->deviceID == PCI_CHIP_I945_GM) - mem_select = 0; - - load_indirect->dw0.mem_select = mem_select; - - /* SIS */ - sis = (sis_state *)(++load_indirect); - sis->dw0.valid = 1; - sis->dw0.force = 1; - sis->dw1.length = 16; // 4 * 3 + 2 + 3 - 1 - - if (mem_select) - sis->dw0.buffer_address = (pI915XvMC->sis.offset >> 2); - else - sis->dw0.buffer_address = (pI915XvMC->sis.bus_addr >> 2); - - /* MSB */ - msb = (msb_state *)(++sis); - msb->dw0.valid = 1; - msb->dw0.force = 1; - msb->dw1.length = 23; // 3 * 8 - 1 - - if (mem_select) - msb->dw0.buffer_address = (pI915XvMC->msb.offset >> 2); - else - msb->dw0.buffer_address = (pI915XvMC->msb.bus_addr >> 2); - - intelBatchbufferData(base, size, 0); - free(base); -} - -static void i915_mc_mpeg_set_origin(XvMCContext *context, XvMCMacroBlock *mb) -{ - struct i915_3dmpeg_set_origin set_origin; - - /* 3DMPEG_SET_ORIGIN */ - memset(&set_origin, 0, sizeof(set_origin)); - set_origin.dw0.type = CMD_3D; - set_origin.dw0.opcode = OPC_3DMPEG_SET_ORIGIN; - set_origin.dw0.length = 0; - set_origin.dw1.h_origin = mb->x; - set_origin.dw1.v_origin = mb->y; - - intelBatchbufferData(&set_origin, sizeof(set_origin), 0); -} - -static void i915_mc_mpeg_macroblock_ipicture(XvMCContext *context, XvMCMacroBlock *mb) -{ - struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture; - - /* 3DMPEG_MACROBLOCK_IPICTURE */ - memset(¯oblock_ipicture, 0, sizeof(macroblock_ipicture)); - macroblock_ipicture.dw0.type = CMD_3D; - macroblock_ipicture.dw0.opcode = OPC_3DMPEG_MACROBLOCK_IPICTURE; - macroblock_ipicture.dw0.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD); - - intelBatchbufferData(¯oblock_ipicture, sizeof(macroblock_ipicture), 0); -} - -#if 0 -static void i915_mc_mpeg_macroblock_0mv(XvMCContext *context, XvMCMacroBlock *mb) -{ - struct i915_3dmpeg_macroblock_0mv macroblock_0mv; - - /* 3DMPEG_MACROBLOCK(0mv) */ - memset(¯oblock_0mv, 0, sizeof(macroblock_0mv)); - macroblock_0mv.header.dw0.type = CMD_3D; - macroblock_0mv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; - macroblock_0mv.header.dw0.length = 0; - macroblock_0mv.header.dw1.mb_intra = 1; /* should be 1 */ - macroblock_0mv.header.dw1.forward = 0; /* should be 0 */ - macroblock_0mv.header.dw1.backward = 0; /* should be 0 */ - macroblock_0mv.header.dw1.h263_4mv = 0; /* should be 0 */ - macroblock_0mv.header.dw1.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD); - -/* - if (!mb->coded_block_pattern) - macroblock_0mv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; -*/ - - macroblock_0mv.header.dw1.motion_type = 0; // (mb->motion_type & 0x3); - macroblock_0mv.header.dw1.vertical_field_select = 0; // mb->motion_vertical_field_select & 0xf; - macroblock_0mv.header.dw1.coded_block_pattern = mb->coded_block_pattern; - macroblock_0mv.header.dw1.skipped_macroblocks = 0; - - intelBatchbufferData(¯oblock_0mv, sizeof(macroblock_0mv), 0); -} -#endif - -static void i915_mc_mpeg_macroblock_1fbmv(XvMCContext *context, XvMCMacroBlock *mb) -{ - struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv; - - /* Motion Vectors */ - su_t fmv; - su_t bmv; - - /* 3DMPEG_MACROBLOCK(1fbmv) */ - memset(¯oblock_1fbmv, 0, sizeof(macroblock_1fbmv)); - macroblock_1fbmv.header.dw0.type = CMD_3D; - macroblock_1fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; - macroblock_1fbmv.header.dw0.length = 2; - macroblock_1fbmv.header.dw1.mb_intra = 0; /* should be 0 */ - macroblock_1fbmv.header.dw1.forward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); - macroblock_1fbmv.header.dw1.backward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); - macroblock_1fbmv.header.dw1.h263_4mv = 0; /* should be 0 */ - macroblock_1fbmv.header.dw1.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD); - - if (!(mb->coded_block_pattern & 0x3f)) - macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; - - macroblock_1fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); - macroblock_1fbmv.header.dw1.vertical_field_select = (mb->motion_vertical_field_select & 0x0f); - macroblock_1fbmv.header.dw1.coded_block_pattern = mb->coded_block_pattern; - macroblock_1fbmv.header.dw1.skipped_macroblocks = 0; - - fmv.s[0] = mb->PMV[0][0][0]; - fmv.s[1] = mb->PMV[0][0][1]; - bmv.s[0] = mb->PMV[0][1][0]; - bmv.s[1] = mb->PMV[0][1][1]; - - macroblock_1fbmv.dw2 = fmv.u[0]; - macroblock_1fbmv.dw3 = bmv.u[0]; - - intelBatchbufferData(¯oblock_1fbmv, sizeof(macroblock_1fbmv), 0); -} - -static void i915_mc_mpeg_macroblock_2fbmv(XvMCContext *context, XvMCMacroBlock *mb, unsigned int ps) -{ - struct i915_3dmpeg_macroblock_2fbmv macroblock_2fbmv; - - /* Motion Vectors */ - su_t fmv; - su_t bmv; - - /* 3DMPEG_MACROBLOCK(2fbmv) */ - memset(¯oblock_2fbmv, 0, sizeof(macroblock_2fbmv)); - macroblock_2fbmv.header.dw0.type = CMD_3D; - macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; - macroblock_2fbmv.header.dw0.length = 4; - macroblock_2fbmv.header.dw1.mb_intra = 0; /* should be 0 */ - macroblock_2fbmv.header.dw1.forward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); - macroblock_2fbmv.header.dw1.backward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); - macroblock_2fbmv.header.dw1.h263_4mv = 0; /* should be 0 */ - macroblock_2fbmv.header.dw1.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD); - - if (!(mb->coded_block_pattern & 0x3f)) - macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; - - macroblock_2fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); - macroblock_2fbmv.header.dw1.vertical_field_select = (mb->motion_vertical_field_select & 0x0f); - macroblock_2fbmv.header.dw1.coded_block_pattern = mb->coded_block_pattern; - macroblock_2fbmv.header.dw1.skipped_macroblocks = 0; - - fmv.s[0] = mb->PMV[0][0][0]; - fmv.s[1] = mb->PMV[0][0][1]; - fmv.s[2] = mb->PMV[1][0][0]; - fmv.s[3] = mb->PMV[1][0][1]; - bmv.s[0] = mb->PMV[0][1][0]; - bmv.s[1] = mb->PMV[0][1][1]; - bmv.s[2] = mb->PMV[1][1][0]; - bmv.s[3] = mb->PMV[1][1][1]; - - if ((ps & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { - if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) { - fmv.s[0] = mb->PMV[0][0][0]; - fmv.s[1] = mb->PMV[0][0][1] >> 1; - fmv.s[2] = mb->PMV[1][0][0]; - fmv.s[3] = mb->PMV[1][0][1] >> 1; - bmv.s[0] = mb->PMV[0][1][0]; - bmv.s[1] = mb->PMV[0][1][1] >> 1; - bmv.s[2] = mb->PMV[1][1][0]; - bmv.s[3] = mb->PMV[1][1][1] >> 1; - } else if ((mb->motion_type & 3) == XVMC_PREDICTION_DUAL_PRIME) { - fmv.s[0] = mb->PMV[0][0][0]; - fmv.s[1] = mb->PMV[0][0][1] >> 1; - fmv.s[2] = mb->PMV[0][0][0]; - fmv.s[3] = mb->PMV[0][0][1] >> 1; // MPEG2 MV[0][1] isn't used - bmv.s[0] = mb->PMV[1][0][0]; - bmv.s[1] = mb->PMV[1][0][1] >> 1; - bmv.s[2] = mb->PMV[1][1][0]; - bmv.s[3] = mb->PMV[1][1][1] >> 1; - } - } - - macroblock_2fbmv.dw2 = fmv.u[0]; - macroblock_2fbmv.dw3 = bmv.u[0]; - macroblock_2fbmv.dw4 = fmv.u[1]; - macroblock_2fbmv.dw5 = bmv.u[1]; - - intelBatchbufferData(¯oblock_2fbmv, sizeof(macroblock_2fbmv), 0); -} - -/* for MC context initialization */ -static void i915_mc_sampler_state_buffer(XvMCContext *context) -{ - struct i915_3dstate_sampler_state *sampler_state; - struct texture_sampler *ts; - i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; - - /* 3DSATE_SAMPLER_STATE */ - sampler_state = (struct i915_3dstate_sampler_state *)pI915XvMC->ssb.map; - memset(sampler_state, 0, sizeof(*sampler_state)); - sampler_state->dw0.type = CMD_3D; - sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE; - sampler_state->dw0.length = 6; - sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1; - - /* Sampler 0 */ - ts = (struct texture_sampler *)(++sampler_state); - memset(ts, 0, sizeof(*ts)); - ts->ts0.reverse_gamma = 0; - ts->ts0.planar2packet = 0; - ts->ts0.color_conversion = 0; - ts->ts0.chromakey_index = 0; - ts->ts0.base_level = 0; - ts->ts0.mip_filter = MIPFILTER_NONE; /* NONE */ - ts->ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */ - ts->ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */ - ts->ts0.lod_bias = 0; /* 0.0 */ - ts->ts0.shadow_enable = 0; - ts->ts0.max_anisotropy = ANISORATIO_2; - ts->ts0.shadow_function = PREFILTEROP_ALWAYS; - ts->ts1.min_lod = 0; /* 0.0 Maximum Mip Level */ - ts->ts1.kill_pixel = 0; - ts->ts1.keyed_texture_filter = 0; - ts->ts1.chromakey_enable = 0; - ts->ts1.tcx_control = TEXCOORDMODE_CLAMP; - ts->ts1.tcy_control = TEXCOORDMODE_CLAMP; - ts->ts1.tcz_control = TEXCOORDMODE_CLAMP; - ts->ts1.normalized_coor = 0; - ts->ts1.map_index = 0; - ts->ts1.east_deinterlacer = 0; - ts->ts2.default_color = 0; - - /* Sampler 1 */ - ++ts; - memset(ts, 0, sizeof(*ts)); - ts->ts0.reverse_gamma = 0; - ts->ts0.planar2packet = 0; - ts->ts0.color_conversion = 0; - ts->ts0.chromakey_index = 0; - ts->ts0.base_level = 0; - ts->ts0.mip_filter = MIPFILTER_NONE; /* NONE */ - ts->ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */ - ts->ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */ - ts->ts0.lod_bias = 0; /* 0.0 */ - ts->ts0.shadow_enable = 0; - ts->ts0.max_anisotropy = ANISORATIO_2; - ts->ts0.shadow_function = PREFILTEROP_ALWAYS; - ts->ts1.min_lod = 0; /* 0.0 Maximum Mip Level */ - ts->ts1.kill_pixel = 0; - ts->ts1.keyed_texture_filter = 0; - ts->ts1.chromakey_enable = 0; - ts->ts1.tcx_control = TEXCOORDMODE_CLAMP; - ts->ts1.tcy_control = TEXCOORDMODE_CLAMP; - ts->ts1.tcz_control = TEXCOORDMODE_CLAMP; - ts->ts1.normalized_coor = 0; - ts->ts1.map_index = 1; - ts->ts1.east_deinterlacer = 0; - ts->ts2.default_color = 0; -} - static void i915_inst_arith(unsigned int *inst, unsigned int op, unsigned int dest, @@ -695,191 +124,245 @@ static void i915_inst_texld(unsigned int *inst, *inst = T2_MBZ; } -static void i915_mc_pixel_shader_program_buffer(XvMCContext *context) +static void i915_emit_batch(void *data, int size, int flag) +{ + intelBatchbufferData(data, size, flag); +} + +/* one time context initialization buffer */ +static uint32_t *one_time_load_state_imm1; +static uint32_t *one_time_load_indirect; +static int one_time_load_state_imm1_size, one_time_load_indirect_size; + +/* load indirect buffer for mc rendering */ +static uint32_t *mc_render_load_indirect; +static int mc_render_load_indirect_size; + +static void i915_mc_one_time_context_init(XvMCContext *context) { - struct i915_3dstate_pixel_shader_program *pixel_shader_program; - i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; - unsigned int *inst; unsigned int dest, src0, src1, src2; + i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; + int i; + struct i915_3dstate_sampler_state *sampler_state; + struct i915_3dstate_pixel_shader_program *pixel_shader_program; + struct i915_3dstate_pixel_shader_constants *pixel_shader_constants; - /* Shader 0 */ + /* sampler static state */ + sampler_state = (struct i915_3dstate_sampler_state *)pI915XvMC->ssb.map; + /* pixel shader static state */ pixel_shader_program = (struct i915_3dstate_pixel_shader_program *)pI915XvMC->psp.map; + /* pixel shader contant static state */ + pixel_shader_constants = (struct i915_3dstate_pixel_shader_constants *)pI915XvMC->psc.map; + + memset(sampler_state, 0, sizeof(*sampler_state)); + sampler_state->dw0.type = CMD_3D; + sampler_state->dw0.opcode = OPC_3DSTATE_SAMPLER_STATE; + sampler_state->dw0.length = 6; + sampler_state->dw1.sampler_masker = SAMPLER_SAMPLER0 | SAMPLER_SAMPLER1; + + sampler_state->sampler0.ts0.reverse_gamma = 0; + sampler_state->sampler0.ts0.planar2packet = 0; + sampler_state->sampler0.ts0.color_conversion = 0; + sampler_state->sampler0.ts0.chromakey_index = 0; + sampler_state->sampler0.ts0.base_level = 0; + sampler_state->sampler0.ts0.mip_filter = MIPFILTER_NONE; /* NONE */ + sampler_state->sampler0.ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */ + sampler_state->sampler0.ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */ + sampler_state->sampler0.ts0.lod_bias = 0; /* 0.0 */ + sampler_state->sampler0.ts0.shadow_enable = 0; + sampler_state->sampler0.ts0.max_anisotropy = ANISORATIO_2; + sampler_state->sampler0.ts0.shadow_function = PREFILTEROP_ALWAYS; + sampler_state->sampler0.ts1.min_lod = 0; /* 0.0 Maximum Mip Level */ + sampler_state->sampler0.ts1.kill_pixel = 0; + sampler_state->sampler0.ts1.keyed_texture_filter = 0; + sampler_state->sampler0.ts1.chromakey_enable = 0; + sampler_state->sampler0.ts1.tcx_control = TEXCOORDMODE_CLAMP; + sampler_state->sampler0.ts1.tcy_control = TEXCOORDMODE_CLAMP; + sampler_state->sampler0.ts1.tcz_control = TEXCOORDMODE_CLAMP; + sampler_state->sampler0.ts1.normalized_coor = 0; + sampler_state->sampler0.ts1.map_index = 0; + sampler_state->sampler0.ts1.east_deinterlacer = 0; + sampler_state->sampler0.ts2.default_color = 0; + + sampler_state->sampler1.ts0.reverse_gamma = 0; + sampler_state->sampler1.ts0.planar2packet = 0; + sampler_state->sampler1.ts0.color_conversion = 0; + sampler_state->sampler1.ts0.chromakey_index = 0; + sampler_state->sampler1.ts0.base_level = 0; + sampler_state->sampler1.ts0.mip_filter = MIPFILTER_NONE; /* NONE */ + sampler_state->sampler1.ts0.mag_filter = MAPFILTER_LINEAR; /* LINEAR */ + sampler_state->sampler1.ts0.min_filter = MAPFILTER_LINEAR; /* LINEAR */ + sampler_state->sampler1.ts0.lod_bias = 0; /* 0.0 */ + sampler_state->sampler1.ts0.shadow_enable = 0; + sampler_state->sampler1.ts0.max_anisotropy = ANISORATIO_2; + sampler_state->sampler1.ts0.shadow_function = PREFILTEROP_ALWAYS; + sampler_state->sampler1.ts1.min_lod = 0; /* 0.0 Maximum Mip Level */ + sampler_state->sampler1.ts1.kill_pixel = 0; + sampler_state->sampler1.ts1.keyed_texture_filter = 0; + sampler_state->sampler1.ts1.chromakey_enable = 0; + sampler_state->sampler1.ts1.tcx_control = TEXCOORDMODE_CLAMP; + sampler_state->sampler1.ts1.tcy_control = TEXCOORDMODE_CLAMP; + sampler_state->sampler1.ts1.tcz_control = TEXCOORDMODE_CLAMP; + sampler_state->sampler1.ts1.normalized_coor = 0; + sampler_state->sampler1.ts1.map_index = 1; + sampler_state->sampler1.ts1.east_deinterlacer = 0; + sampler_state->sampler1.ts2.default_color = 0; + memset(pixel_shader_program, 0, sizeof(*pixel_shader_program)); - pixel_shader_program->dw0.type = CMD_3D; - pixel_shader_program->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; - pixel_shader_program->dw0.retain = 1; - pixel_shader_program->dw0.length = 2; - /* mov oC, c0.0000 */ - inst = (unsigned int*)(++pixel_shader_program); + pixel_shader_program->shader0.type = CMD_3D; + pixel_shader_program->shader0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; + pixel_shader_program->shader0.retain = 1; + pixel_shader_program->shader0.length = 2; /* 1 inst */ + i = 0; + dest = UREG(REG_TYPE_OC, 0); src0 = UREG(REG_TYPE_CONST, 0); src1 = 0; src2 = 0; - i915_inst_arith(inst, A0_MOV, dest, A0_DEST_CHANNEL_ALL, - A0_DEST_SATURATE, src0, src1, src2); - inst += 3; - - /* Shader 1 */ - pixel_shader_program = (struct i915_3dstate_pixel_shader_program *)inst; - memset(pixel_shader_program, 0, sizeof(*pixel_shader_program)); - pixel_shader_program->dw0.type = CMD_3D; - pixel_shader_program->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; - pixel_shader_program->dw0.retain = 1; - pixel_shader_program->dw0.length = 14; + i915_inst_arith(&pixel_shader_program->inst0[i], A0_MOV, + dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, src2); + + pixel_shader_program->shader1.type = CMD_3D; + pixel_shader_program->shader1.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; + pixel_shader_program->shader1.retain = 1; + pixel_shader_program->shader1.length = 14; /* 5 inst */ + i = 0; /* dcl t0.xy */ - inst = (unsigned int*)(++pixel_shader_program); - i915_inst_decl(inst, REG_TYPE_T, T_TEX0, D0_CHANNEL_XY); + i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX0, D0_CHANNEL_XY); + i+=3; /* dcl t1.xy */ - inst += 3; - i915_inst_decl(inst, REG_TYPE_T, T_TEX1, D0_CHANNEL_XY); + i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_T, T_TEX1, D0_CHANNEL_XY); /* dcl_2D s0 */ - inst += 3; - i915_inst_decl(inst, REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D); + i += 3; + i915_inst_decl(&pixel_shader_program->inst1[i], REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D); /* texld r0, t0, s0 */ - inst += 3; + i += 3; dest = UREG(REG_TYPE_R, 0); src0 = UREG(REG_TYPE_T, 0); /* COORD */ src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */ - i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + i915_inst_texld(&pixel_shader_program->inst1[i], T0_TEXLD, dest, src0, src1); /* mov oC, r0 */ - inst += 3; + i += 3; dest = UREG(REG_TYPE_OC, 0); src0 = UREG(REG_TYPE_R, 0); src1 = src2 = 0; - i915_inst_arith(inst, A0_MOV, dest, A0_DEST_CHANNEL_ALL, + i915_inst_arith(&pixel_shader_program->inst1[i], A0_MOV, dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, src2); - inst += 3; - /* Shader 2 */ - pixel_shader_program = (struct i915_3dstate_pixel_shader_program *)inst; - memset(pixel_shader_program, 0, sizeof(*pixel_shader_program)); - pixel_shader_program->dw0.type = CMD_3D; - pixel_shader_program->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; - pixel_shader_program->dw0.retain = 1; - pixel_shader_program->dw0.length = 14; + + pixel_shader_program->shader2.type = CMD_3D; + pixel_shader_program->shader2.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; + pixel_shader_program->shader2.retain = 1; + pixel_shader_program->shader2.length = 14; /* 5 inst */ + i = 0; /* dcl t2.xy */ - inst = (unsigned int*)(++pixel_shader_program); - i915_inst_decl(inst, REG_TYPE_T, T_TEX2, D0_CHANNEL_XY); + i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX2, D0_CHANNEL_XY); /* dcl t3.xy */ - inst += 3; - i915_inst_decl(inst, REG_TYPE_T, T_TEX3, D0_CHANNEL_XY); + i += 3; + i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_T, T_TEX3, D0_CHANNEL_XY); /* dcl_2D s1 */ - inst += 3; - i915_inst_decl(inst, REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D); + i += 3; + i915_inst_decl(&pixel_shader_program->inst2[i], REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D); /* texld r0, t2, s1 */ - inst += 3; + i += 3; dest = UREG(REG_TYPE_R, 0); src0 = UREG(REG_TYPE_T, 2); /* COORD */ src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */ - i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + i915_inst_texld(&pixel_shader_program->inst2[i], T0_TEXLD, dest, src0, src1); /* mov oC, r0 */ - inst += 3; + i += 3; dest = UREG(REG_TYPE_OC, 0); src0 = UREG(REG_TYPE_R, 0); src1 = src2 = 0; - i915_inst_arith(inst, A0_MOV, dest, A0_DEST_CHANNEL_ALL, + i915_inst_arith(&pixel_shader_program->inst2[i], A0_MOV, dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, src2); - inst += 3; /* Shader 3 */ - pixel_shader_program = (struct i915_3dstate_pixel_shader_program *)inst; - memset(pixel_shader_program, 0, sizeof(*pixel_shader_program)); - pixel_shader_program->dw0.type = CMD_3D; - pixel_shader_program->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; - pixel_shader_program->dw0.retain = 1; - pixel_shader_program->dw0.length = 29; + pixel_shader_program->shader3.type = CMD_3D; + pixel_shader_program->shader3.opcode = OPC_3DSTATE_PIXEL_SHADER_PROGRAM; + pixel_shader_program->shader3.retain = 1; + pixel_shader_program->shader3.length = 29; /* 10 inst */ + i = 0; /* dcl t0.xy */ - inst = (unsigned int*)(++pixel_shader_program); - i915_inst_decl(inst, REG_TYPE_T, T_TEX0, D0_CHANNEL_XY); + i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX0, D0_CHANNEL_XY); /* dcl t1.xy */ - inst += 3; - i915_inst_decl(inst, REG_TYPE_T, T_TEX1, D0_CHANNEL_XY); + i += 3; + i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX1, D0_CHANNEL_XY); /* dcl t2.xy */ - inst += 3; - i915_inst_decl(inst, REG_TYPE_T, T_TEX2, D0_CHANNEL_XY); + i += 3; + i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX2, D0_CHANNEL_XY); /* dcl t3.xy */ - inst += 3; - i915_inst_decl(inst, REG_TYPE_T, T_TEX3, D0_CHANNEL_XY); + i += 3; + i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_T, T_TEX3, D0_CHANNEL_XY); /* dcl_2D s0 */ - inst += 3; - i915_inst_decl(inst, REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D); + i += 3; + i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 0, D0_SAMPLE_TYPE_2D); /* dcl_2D s1 */ - inst += 3; - i915_inst_decl(inst, REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D); + i += 3; + i915_inst_decl(&pixel_shader_program->inst3[i], REG_TYPE_S, 1, D0_SAMPLE_TYPE_2D); /* texld r0, t0, s0 */ - inst += 3; + i += 3; dest = UREG(REG_TYPE_R, 0); src0 = UREG(REG_TYPE_T, 0); /* COORD */ src1 = UREG(REG_TYPE_S, 0); /* SAMPLER */ - i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0, src1); /* texld r1, t2, s1 */ - inst += 3; + i += 3; dest = UREG(REG_TYPE_R, 1); src0 = UREG(REG_TYPE_T, 2); /* COORD */ src1 = UREG(REG_TYPE_S, 1); /* SAMPLER */ - i915_inst_texld(inst, T0_TEXLD, dest, src0, src1); + i915_inst_texld(&pixel_shader_program->inst3[i], T0_TEXLD, dest, src0, src1); /* add r0, r0, r1 */ - inst += 3; + i += 3; dest = UREG(REG_TYPE_R, 0); src0 = UREG(REG_TYPE_R, 0); src1 = UREG(REG_TYPE_R, 1); src2 = 0; - i915_inst_arith(inst, A0_ADD, dest, A0_DEST_CHANNEL_ALL, + i915_inst_arith(&pixel_shader_program->inst3[i], A0_ADD, dest, A0_DEST_CHANNEL_ALL, 0 /* A0_DEST_SATURATE */, src0, src1, src2); /* mul oC, r0, c0 */ - inst += 3; + i += 3; dest = UREG(REG_TYPE_OC, 0); src0 = UREG(REG_TYPE_R, 0); src1 = UREG(REG_TYPE_CONST, 0); src2 = 0; - i915_inst_arith(inst, A0_MUL, dest, A0_DEST_CHANNEL_ALL, + i915_inst_arith(&pixel_shader_program->inst3[i], A0_MUL, dest, A0_DEST_CHANNEL_ALL, A0_DEST_SATURATE, src0, src1, src2); - inst += 3; -} - -static void i915_mc_pixel_shader_constants_buffer(XvMCContext *context) -{ - struct i915_3dstate_pixel_shader_constants *pixel_shader_constants; - i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; - float *value; - pixel_shader_constants = (struct i915_3dstate_pixel_shader_constants *)pI915XvMC->psc.map; memset(pixel_shader_constants, 0, sizeof(*pixel_shader_constants)); pixel_shader_constants->dw0.type = CMD_3D; pixel_shader_constants->dw0.opcode = OPC_3DSTATE_PIXEL_SHADER_CONSTANTS; pixel_shader_constants->dw0.length = 4; pixel_shader_constants->dw1.reg_mask = REG_CR0; - value = (float *)(++pixel_shader_constants); - *(value++) = 0.5; - *(value++) = 0.5; - *(value++) = 0.5; - *(value++) = 0.5; + pixel_shader_constants->value.x = 0.5; + pixel_shader_constants->value.y = 0.5; + pixel_shader_constants->value.z = 0.5; + pixel_shader_constants->value.w = 0.5; + } -static void i915_mc_one_time_state_initialization(XvMCContext *context) +static void i915_mc_one_time_state_init(XvMCContext *context) { - struct i915_3dstate_load_state_immediate_1 *load_state_immediate_1 = NULL; struct s3_dword *s3 = NULL; struct s6_dword *s6 = NULL; - struct i915_3dstate_load_indirect *load_indirect = NULL; dis_state *dis = NULL; ssb_state *ssb = NULL; psp_state *psp = NULL; psc_state *psc = NULL; i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; - unsigned int size; - void *base = NULL; - int mem_select = 1; + struct i915_3dstate_load_state_immediate_1 *load_state_immediate_1; + struct i915_3dstate_load_indirect *load_indirect; + int mem_select; /* 3DSTATE_LOAD_STATE_IMMEDIATE_1 */ - size = sizeof(*load_state_immediate_1) + sizeof(*s3) + sizeof(*s6); - base = calloc(1, size); - load_state_immediate_1 = (struct i915_3dstate_load_state_immediate_1 *)base; + one_time_load_state_imm1_size = sizeof(*load_state_immediate_1) + sizeof(*s3) + sizeof(*s6); + one_time_load_state_imm1 = calloc(1, one_time_load_state_imm1_size); + load_state_immediate_1 = (struct i915_3dstate_load_state_immediate_1 *)one_time_load_state_imm1; load_state_immediate_1->dw0.type = CMD_3D; load_state_immediate_1->dw0.opcode = OPC_3DSTATE_LOAD_STATE_IMMEDIATE_1; load_state_immediate_1->dw0.load_s3 = 1; load_state_immediate_1->dw0.load_s6 = 1; - load_state_immediate_1->dw0.length = (size >> 2) - 2; + load_state_immediate_1->dw0.length = (one_time_load_state_imm1_size >> 2) - 2; s3 = (struct s3_dword *)(++load_state_immediate_1); s3->set0_pcd = 1; @@ -905,33 +388,31 @@ static void i915_mc_one_time_state_initialization(XvMCContext *context) s6->color_buffer_write = 1; s6->triangle_pv = 0; - intelBatchbufferData(base, size, 0); - free(base); - /* 3DSTATE_LOAD_INDIRECT */ - size = sizeof(*load_indirect) + sizeof(*dis) + sizeof(*ssb) + sizeof(*psp) + sizeof(*psc); - base = calloc(1, size); - load_indirect = (struct i915_3dstate_load_indirect *)base; + one_time_load_indirect_size = sizeof(*load_indirect) + sizeof(*dis) + sizeof(*ssb) + sizeof(*psp) + sizeof(*psc); + one_time_load_indirect = calloc(1, one_time_load_indirect_size); + load_indirect = (struct i915_3dstate_load_indirect *)one_time_load_indirect; load_indirect->dw0.type = CMD_3D; load_indirect->dw0.opcode = OPC_3DSTATE_LOAD_INDIRECT; load_indirect->dw0.block_mask = BLOCK_DIS | BLOCK_SSB | BLOCK_PSP | BLOCK_PSC; - load_indirect->dw0.length = (size >> 2) - 2; + load_indirect->dw0.length = (one_time_load_indirect_size >> 2) - 2; if (pI915XvMC->deviceID == PCI_CHIP_I915_G || - pI915XvMC->deviceID == PCI_CHIP_I915_GM || - pI915XvMC->deviceID == PCI_CHIP_I945_G || - pI915XvMC->deviceID == PCI_CHIP_I945_GM) - mem_select = 0; + pI915XvMC->deviceID == PCI_CHIP_I915_GM) + mem_select = 0; /* use physical address */ + else + mem_select = 1; /* use gfx address */ load_indirect->dw0.mem_select = mem_select; - /* DIS */ + + /* Dynamic indirect state buffer */ dis = (dis_state *)(++load_indirect); dis->dw0.valid = 0; dis->dw0.reset = 0; dis->dw0.buffer_address = 0; - /* SSB */ + /* Sample state buffer */ ssb = (ssb_state *)(++dis); ssb->dw0.valid = 1; ssb->dw0.force = 1; @@ -940,20 +421,20 @@ static void i915_mc_one_time_state_initialization(XvMCContext *context) if (mem_select) ssb->dw0.buffer_address = (pI915XvMC->ssb.offset >> 2); else - ssb->dw0.buffer_address = (pI915XvMC->ssb.bus_addr >> 2); + ssb->dw0.buffer_address = (pI915XvMC->ssb.bus_addr >> 2); - /* PSP */ + /* Pixel shader program buffer */ psp = (psp_state *)(++ssb); psp->dw0.valid = 1; psp->dw0.force = 1; psp->dw1.length = 66; /* 4 + 16 + 16 + 31 - 1 */ if (mem_select) - psp->dw0.buffer_address = (pI915XvMC->psp.offset >> 2); + psp->dw0.buffer_address = (pI915XvMC->psp.offset >> 2); else - psp->dw0.buffer_address = (pI915XvMC->psp.bus_addr >> 2); + psp->dw0.buffer_address = (pI915XvMC->psp.bus_addr >> 2); - /* PSC */ + /* Pixel shader constant buffer */ psc = (psc_state *)(++psp); psc->dw0.valid = 1; psc->dw0.force = 1; @@ -963,9 +444,483 @@ static void i915_mc_one_time_state_initialization(XvMCContext *context) psc->dw0.buffer_address = (pI915XvMC->psc.offset >> 2); else psc->dw0.buffer_address = (pI915XvMC->psc.bus_addr >> 2); +} - intelBatchbufferData(base, size, 0); - free(base); +static void i915_mc_one_time_state_emit(void) +{ + i915_emit_batch(one_time_load_state_imm1, one_time_load_state_imm1_size, 0); + i915_emit_batch(one_time_load_indirect, one_time_load_indirect_size, 0); +} + +static void i915_mc_static_indirect_state_init(XvMCContext *context) +{ + i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; + struct i915_mc_static_indirect_state_buffer *buffer_info = + (struct i915_mc_static_indirect_state_buffer *)pI915XvMC->sis.map; + + memset(buffer_info, 0, sizeof(*buffer_info)); + /* dest Y */ + buffer_info->dest_y.dw0.type = CMD_3D; + buffer_info->dest_y.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; + buffer_info->dest_y.dw0.length = 1; + buffer_info->dest_y.dw1.aux_id = 0; + buffer_info->dest_y.dw1.buffer_id = BUFFERID_COLOR_BACK; + buffer_info->dest_y.dw1.fence_regs = 0; /* disabled */ /* FIXME: tiled y for performance */ + buffer_info->dest_y.dw1.tiled_surface = 0; /* linear */ + buffer_info->dest_y.dw1.walk = TILEWALK_XMAJOR; + + /* dest U */ + buffer_info->dest_u.dw0.type = CMD_3D; + buffer_info->dest_u.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; + buffer_info->dest_u.dw0.length = 1; + buffer_info->dest_u.dw1.aux_id = 0; + buffer_info->dest_u.dw1.buffer_id = BUFFERID_COLOR_AUX; + buffer_info->dest_u.dw1.fence_regs = 0; + buffer_info->dest_u.dw1.tiled_surface = 0; + buffer_info->dest_u.dw1.walk = TILEWALK_XMAJOR; + + /* dest V */ + buffer_info->dest_v.dw0.type = CMD_3D; + buffer_info->dest_v.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; + buffer_info->dest_v.dw0.length = 1; + buffer_info->dest_v.dw1.aux_id = 1; + buffer_info->dest_v.dw1.buffer_id = BUFFERID_COLOR_AUX; + buffer_info->dest_v.dw1.fence_regs = 0; + buffer_info->dest_v.dw1.tiled_surface = 0; + buffer_info->dest_v.dw1.walk = TILEWALK_XMAJOR; + + buffer_info->dest_buf.dw0.type = CMD_3D; + buffer_info->dest_buf.dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES; + buffer_info->dest_buf.dw0.length = 0; + buffer_info->dest_buf.dw1.dest_v_bias = 8; /* 0.5 */ + buffer_info->dest_buf.dw1.dest_h_bias = 8; /* 0.5 */ + buffer_info->dest_buf.dw1.color_fmt = COLORBUFFER_8BIT; + buffer_info->dest_buf.dw1.v_ls = 0; /* fill later */ + buffer_info->dest_buf.dw1.v_ls_offset = 0; /* fill later */ + + buffer_info->dest_buf_mpeg.dw0.type = CMD_3D; + buffer_info->dest_buf_mpeg.dw0.opcode = OPC_3DSTATE_DEST_BUFFER_VARIABLES_MPEG; + buffer_info->dest_buf_mpeg.dw0.length = 1; + buffer_info->dest_buf_mpeg.dw1.decode_mode = MPEG_DECODE_MC; + buffer_info->dest_buf_mpeg.dw1.rcontrol = 0; /* for MPEG-1/MPEG-2 */ + buffer_info->dest_buf_mpeg.dw1.bidir_avrg_control = 0; /* for MPEG-1/MPEG-2/MPEG-4 */ + buffer_info->dest_buf_mpeg.dw1.abort_on_error = 1; + buffer_info->dest_buf_mpeg.dw1.intra8 = 0; /* 16-bit formatted correction data */ + buffer_info->dest_buf_mpeg.dw1.tff = 1; /* fill later */ + + buffer_info->dest_buf_mpeg.dw1.v_subsample_factor = MC_SUB_1V; + buffer_info->dest_buf_mpeg.dw1.h_subsample_factor = MC_SUB_1H; + + buffer_info->corr.dw0.type = CMD_3D; + buffer_info->corr.dw0.opcode = OPC_3DSTATE_BUFFER_INFO; + buffer_info->corr.dw0.length = 1; + buffer_info->corr.dw1.aux_id = 0; + buffer_info->corr.dw1.buffer_id = BUFFERID_MC_INTRA_CORR; + buffer_info->corr.dw1.aux_id = 0; + buffer_info->corr.dw1.fence_regs = 0; + buffer_info->corr.dw1.tiled_surface = 0; + buffer_info->corr.dw1.walk = 0; + buffer_info->corr.dw1.pitch = 0; + buffer_info->corr.dw2.base_address = (pI915XvMC->corrdata.offset >> 2); /* starting DWORD address */ +} + +static void i915_mc_static_indirect_state_set(XvMCContext *context, XvMCSurface *dest, + unsigned int picture_structure, unsigned int flags, unsigned int picture_coding_type) +{ + i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; + i915XvMCSurface *pI915Surface = (i915XvMCSurface *)dest->privData; + struct i915_mc_static_indirect_state_buffer *buffer_info = + (struct i915_mc_static_indirect_state_buffer *)pI915XvMC->sis.map; + unsigned int w = dest->width; + + buffer_info->dest_y.dw1.pitch = (pI915Surface->yStride >> 2); /* in DWords */ + buffer_info->dest_y.dw2.base_address = (YOFFSET(pI915Surface) >> 2); /* starting DWORD address */ + buffer_info->dest_u.dw1.pitch = (pI915Surface->uvStride >> 2); /* in DWords */ + buffer_info->dest_u.dw2.base_address = (UOFFSET(pI915Surface) >> 2); /* starting DWORD address */ + buffer_info->dest_v.dw1.pitch = (pI915Surface->uvStride >> 2); /* in Dwords */ + buffer_info->dest_v.dw2.base_address = (VOFFSET(pI915Surface) >> 2); /* starting DWORD address */ + + if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { + ; + } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_TOP_FIELD) { + buffer_info->dest_buf.dw1.v_ls = 1; + } else if ((picture_structure & XVMC_FRAME_PICTURE) == XVMC_BOTTOM_FIELD) { + buffer_info->dest_buf.dw1.v_ls = 1; + buffer_info->dest_buf.dw1.v_ls_offset = 1; + } + + if (picture_structure & XVMC_FRAME_PICTURE) { + ; + } else if (picture_structure & XVMC_TOP_FIELD) { + if (flags & XVMC_SECOND_FIELD) + buffer_info->dest_buf_mpeg.dw1.tff = 0; + else + buffer_info->dest_buf_mpeg.dw1.tff = 1; + } else if (picture_structure & XVMC_BOTTOM_FIELD) { + if (flags & XVMC_SECOND_FIELD) + buffer_info->dest_buf_mpeg.dw1.tff = 1; + else + buffer_info->dest_buf_mpeg.dw1.tff = 0; + } + + buffer_info->dest_buf_mpeg.dw1.picture_width = (dest->width >> 4); /* in macroblocks */ + buffer_info->dest_buf_mpeg.dw2.picture_coding_type = picture_coding_type; +} + +static void i915_mc_map_state_init(XvMCContext *context) +{ + i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; + unsigned int w = context->width; + unsigned int h = context->height; + struct i915_mc_map_state *map_state; + + map_state = (struct i915_mc_map_state *)pI915XvMC->msb.map; + + memset(map_state, 0, sizeof(*map_state)); + + /* 3DSATE_MAP_STATE: Y */ + map_state->y_map.dw0.type = CMD_3D; + map_state->y_map.dw0.opcode = OPC_3DSTATE_MAP_STATE; + map_state->y_map.dw0.retain = 1; + map_state->y_map.dw0.length = 6; + map_state->y_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1; + + /* Y Forward (Past) */ + map_state->y_forward.tm0.v_ls_offset = 0; + map_state->y_forward.tm0.v_ls = 0; + map_state->y_forward.tm1.tile_walk = TILEWALK_XMAJOR; + map_state->y_forward.tm1.tiled_surface = 0; + map_state->y_forward.tm1.utilize_fence_regs = 0; + map_state->y_forward.tm1.texel_fmt = 0; /* 8bit */ + map_state->y_forward.tm1.surface_fmt = 1; /* 8bit */ + map_state->y_forward.tm1.width = w - 1; + map_state->y_forward.tm1.height = h - 1; + map_state->y_forward.tm2.depth = 0; + map_state->y_forward.tm2.max_lod = 0; + map_state->y_forward.tm2.cube_face = 0; + + /* Y Backward (Future) */ + map_state->y_backward.tm0.v_ls_offset = 0; + map_state->y_backward.tm0.v_ls = 0; + map_state->y_backward.tm1.tile_walk = TILEWALK_XMAJOR; + map_state->y_backward.tm1.tiled_surface = 0; + map_state->y_backward.tm1.utilize_fence_regs = 0; + map_state->y_backward.tm1.texel_fmt = 0; /* 8bit */ + map_state->y_backward.tm1.surface_fmt = 1; /* 8bit */ + map_state->y_backward.tm1.width = w - 1; + map_state->y_backward.tm1.height = h - 1; + map_state->y_backward.tm2.depth = 0; + map_state->y_backward.tm2.max_lod = 0; + map_state->y_backward.tm2.cube_face = 0; + + /* 3DSATE_MAP_STATE: U */ + map_state->u_map.dw0.type = CMD_3D; + map_state->u_map.dw0.opcode = OPC_3DSTATE_MAP_STATE; + map_state->u_map.dw0.retain = 1; + map_state->u_map.dw0.length = 6; + map_state->u_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1; + + /* U Forward */ + map_state->u_forward.tm0.v_ls_offset = 0; + map_state->u_forward.tm0.v_ls = 0; + map_state->u_forward.tm1.tile_walk = TILEWALK_XMAJOR; + map_state->u_forward.tm1.tiled_surface = 0; + map_state->u_forward.tm1.utilize_fence_regs = 0; + map_state->u_forward.tm1.texel_fmt = 0; /* 8bit */ + map_state->u_forward.tm1.surface_fmt = 1; /* 8bit */ + map_state->u_forward.tm1.width = (w >> 1) - 1; + map_state->u_forward.tm1.height = (h >> 1) - 1; + map_state->u_forward.tm2.depth = 0; + map_state->u_forward.tm2.max_lod = 0; + map_state->u_forward.tm2.cube_face = 0; + + /* U Backward */ + map_state->u_backward.tm0.v_ls_offset = 0; + map_state->u_backward.tm0.v_ls = 0; + map_state->u_backward.tm1.tile_walk = TILEWALK_XMAJOR; + map_state->u_backward.tm1.tiled_surface = 0; + map_state->u_backward.tm1.utilize_fence_regs = 0; + map_state->u_backward.tm1.texel_fmt = 0; + map_state->u_backward.tm1.surface_fmt = 1; + map_state->u_backward.tm1.width = (w >> 1) - 1; + map_state->u_backward.tm1.height = (h >> 1) - 1; + map_state->u_backward.tm2.depth = 0; + map_state->u_backward.tm2.max_lod = 0; + map_state->u_backward.tm2.cube_face = 0; + + /* 3DSATE_MAP_STATE: V */ + map_state->v_map.dw0.type = CMD_3D; + map_state->v_map.dw0.opcode = OPC_3DSTATE_MAP_STATE; + map_state->v_map.dw0.retain = 1; + map_state->v_map.dw0.length = 6; + map_state->v_map.dw1.map_mask = MAP_MAP0 | MAP_MAP1; + + /* V Forward */ + map_state->v_forward.tm0.v_ls_offset = 0; + map_state->v_forward.tm0.v_ls = 0; + map_state->v_forward.tm1.tile_walk = TILEWALK_XMAJOR; + map_state->v_forward.tm1.tiled_surface = 0; + map_state->v_forward.tm1.utilize_fence_regs = 0; + map_state->v_forward.tm1.texel_fmt = 0; + map_state->v_forward.tm1.surface_fmt = 1; + map_state->v_forward.tm1.width = (w >> 1) - 1; + map_state->v_forward.tm1.height = (h >> 1) - 1; + map_state->v_forward.tm2.depth = 0; + map_state->v_forward.tm2.max_lod = 0; + map_state->v_forward.tm2.cube_face = 0; + + /* V Backward */ + map_state->v_backward.tm0.v_ls_offset = 0; + map_state->v_backward.tm0.v_ls = 0; + map_state->v_backward.tm1.tile_walk = TILEWALK_XMAJOR; + map_state->v_backward.tm1.tiled_surface = 0; + map_state->v_backward.tm1.utilize_fence_regs = 0; + map_state->v_backward.tm1.texel_fmt = 0; + map_state->v_backward.tm1.surface_fmt = 1; + map_state->v_backward.tm1.width = (w >> 1) - 1; + map_state->v_backward.tm1.height = (h >> 1) - 1; + map_state->v_backward.tm2.depth = 0; + map_state->v_backward.tm2.max_lod = 0; + map_state->v_backward.tm2.cube_face = 0; +} + +static void i915_mc_map_state_set(XvMCContext *context, + i915XvMCSurface *privPast, + i915XvMCSurface *privFuture) +{ + i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; + struct i915_mc_map_state *map_state; + + map_state = (struct i915_mc_map_state *)pI915XvMC->msb.map; + + map_state->y_forward.tm0.base_address = (YOFFSET(privPast) >> 2); + map_state->y_forward.tm2.pitch = (privPast->yStride >> 2) - 1; /* in DWords - 1 */ + map_state->y_backward.tm0.base_address = (YOFFSET(privFuture) >> 2); + map_state->y_backward.tm2.pitch = (privFuture->yStride >> 2) - 1; + map_state->u_forward.tm0.base_address = (UOFFSET(privPast) >> 2); + map_state->u_forward.tm2.pitch = (privPast->uvStride >> 2) - 1; /* in DWords - 1 */ + map_state->u_backward.tm0.base_address = (UOFFSET(privFuture) >> 2); + map_state->u_backward.tm2.pitch = (privFuture->uvStride >> 2) - 1; + map_state->v_forward.tm0.base_address = (VOFFSET(privPast) >> 2); + map_state->v_forward.tm2.pitch = (privPast->uvStride >> 2) - 1; /* in DWords - 1 */ + map_state->v_backward.tm0.base_address = (VOFFSET(privFuture) >> 2); + map_state->v_backward.tm2.pitch = (privFuture->uvStride >> 2) - 1; +} + +static void i915_flush(int map, int render) +{ + struct i915_mi_flush mi_flush; + + memset(&mi_flush, 0, sizeof(mi_flush)); + mi_flush.dw0.type = CMD_MI; + mi_flush.dw0.opcode = OPC_MI_FLUSH; + mi_flush.dw0.map_cache_invalidate = map; + mi_flush.dw0.render_cache_flush_inhibit = render; + + intelBatchbufferData(&mi_flush, sizeof(mi_flush), 0); +} + +static void i915_mc_load_indirect_render_init(XvMCContext *context) +{ + i915XvMCContext *pI915XvMC = (i915XvMCContext *)context->privData; + sis_state *sis; + msb_state *msb; + struct i915_3dstate_load_indirect *load_indirect; + int mem_select; + + mc_render_load_indirect_size = sizeof(*load_indirect) + sizeof(*sis) + + sizeof(*msb); + mc_render_load_indirect = calloc(1, mc_render_load_indirect_size); + + load_indirect = (struct i915_3dstate_load_indirect *)mc_render_load_indirect; + load_indirect->dw0.type = CMD_3D; + load_indirect->dw0.opcode = OPC_3DSTATE_LOAD_INDIRECT; + load_indirect->dw0.block_mask = BLOCK_SIS | BLOCK_MSB; + load_indirect->dw0.length = (mc_render_load_indirect_size >> 2) - 2; + + if (pI915XvMC->deviceID == PCI_CHIP_I915_G || + pI915XvMC->deviceID == PCI_CHIP_I915_GM) + mem_select = 0; + else + mem_select = 1; + + load_indirect->dw0.mem_select = mem_select; + + /* Static Indirect state buffer (dest buffer info) */ + sis = (sis_state *)(++load_indirect); + sis->dw0.valid = 1; + sis->dw0.force = 1; + sis->dw1.length = 16; /* 4 * 3 + 2 + 3 - 1 */ + + if (mem_select) + sis->dw0.buffer_address = (pI915XvMC->sis.offset >> 2); + else + sis->dw0.buffer_address = (pI915XvMC->sis.bus_addr >> 2); + + /* Map state buffer (reference buffer info) */ + msb = (msb_state *)(++sis); + msb->dw0.valid = 1; + msb->dw0.force = 1; + msb->dw1.length = 23; /* 3 * 8 - 1 */ + + if (mem_select) + msb->dw0.buffer_address = (pI915XvMC->msb.offset >> 2); + else + msb->dw0.buffer_address = (pI915XvMC->msb.bus_addr >> 2); +} + +static void i915_mc_load_indirect_render_emit(void) +{ + i915_emit_batch(mc_render_load_indirect, mc_render_load_indirect_size, 0); +} + +static void i915_mc_mpeg_set_origin(XvMCContext *context, XvMCMacroBlock *mb) +{ + struct i915_3dmpeg_set_origin set_origin; + + /* 3DMPEG_SET_ORIGIN */ + memset(&set_origin, 0, sizeof(set_origin)); + set_origin.dw0.type = CMD_3D; + set_origin.dw0.opcode = OPC_3DMPEG_SET_ORIGIN; + set_origin.dw0.length = 0; + set_origin.dw1.h_origin = mb->x; + set_origin.dw1.v_origin = mb->y; + + intelBatchbufferData(&set_origin, sizeof(set_origin), 0); +} + +static void i915_mc_mpeg_macroblock_ipicture(XvMCContext *context, XvMCMacroBlock *mb) +{ + struct i915_3dmpeg_macroblock_ipicture macroblock_ipicture; + + /* 3DMPEG_MACROBLOCK_IPICTURE */ + memset(¯oblock_ipicture, 0, sizeof(macroblock_ipicture)); + macroblock_ipicture.dw0.type = CMD_3D; + macroblock_ipicture.dw0.opcode = OPC_3DMPEG_MACROBLOCK_IPICTURE; + macroblock_ipicture.dw0.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD); + + intelBatchbufferData(¯oblock_ipicture, sizeof(macroblock_ipicture), 0); +} + +#if 0 +static void i915_mc_mpeg_macroblock_0mv(XvMCContext *context, XvMCMacroBlock *mb) +{ + struct i915_3dmpeg_macroblock_0mv macroblock_0mv; + + /* 3DMPEG_MACROBLOCK(0mv) */ + memset(¯oblock_0mv, 0, sizeof(macroblock_0mv)); + macroblock_0mv.header.dw0.type = CMD_3D; + macroblock_0mv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; + macroblock_0mv.header.dw0.length = 0; + macroblock_0mv.header.dw1.mb_intra = 1; /* should be 1 */ + macroblock_0mv.header.dw1.forward = 0; /* should be 0 */ + macroblock_0mv.header.dw1.backward = 0; /* should be 0 */ + macroblock_0mv.header.dw1.h263_4mv = 0; /* should be 0 */ + macroblock_0mv.header.dw1.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD); + +/* + if (!mb->coded_block_pattern) + macroblock_0mv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; +*/ + + macroblock_0mv.header.dw1.motion_type = 0; // (mb->motion_type & 0x3); + macroblock_0mv.header.dw1.vertical_field_select = 0; // mb->motion_vertical_field_select & 0xf; + macroblock_0mv.header.dw1.coded_block_pattern = mb->coded_block_pattern; + macroblock_0mv.header.dw1.skipped_macroblocks = 0; + + intelBatchbufferData(¯oblock_0mv, sizeof(macroblock_0mv), 0); +} +#endif + +static void i915_mc_mpeg_macroblock_1fbmv(XvMCContext *context, XvMCMacroBlock *mb) +{ + struct i915_3dmpeg_macroblock_1fbmv macroblock_1fbmv; + vector_t mv0[2]; + + /* 3DMPEG_MACROBLOCK(1fbmv) */ + memset(¯oblock_1fbmv, 0, sizeof(macroblock_1fbmv)); + macroblock_1fbmv.header.dw0.type = CMD_3D; + macroblock_1fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; + macroblock_1fbmv.header.dw0.length = 2; + macroblock_1fbmv.header.dw1.mb_intra = 0; /* should be 0 */ + macroblock_1fbmv.header.dw1.forward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); + macroblock_1fbmv.header.dw1.backward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); + macroblock_1fbmv.header.dw1.h263_4mv = 0; /* should be 0 */ + macroblock_1fbmv.header.dw1.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD); + + if (!(mb->coded_block_pattern & 0x3f)) + macroblock_1fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; + + macroblock_1fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); + macroblock_1fbmv.header.dw1.vertical_field_select = (mb->motion_vertical_field_select & 0x0f); + macroblock_1fbmv.header.dw1.coded_block_pattern = mb->coded_block_pattern; + macroblock_1fbmv.header.dw1.skipped_macroblocks = 0; + + mv0[0].component[0] = mb->PMV[0][0][0]; + mv0[0].component[1] = mb->PMV[0][0][1]; + mv0[1].component[0] = mb->PMV[0][1][0]; + mv0[1].component[1] = mb->PMV[0][1][1]; + + macroblock_1fbmv.dw2 = mv0[0].v; + macroblock_1fbmv.dw3 = mv0[1].v; + + intelBatchbufferData(¯oblock_1fbmv, sizeof(macroblock_1fbmv), 0); +} + +static void i915_mc_mpeg_macroblock_2fbmv(XvMCContext *context, XvMCMacroBlock *mb, unsigned int ps) +{ + struct i915_3dmpeg_macroblock_2fbmv macroblock_2fbmv; + vector_t mv0[2]; + vector_t mv1[2]; + + /* 3DMPEG_MACROBLOCK(2fbmv) */ + memset(¯oblock_2fbmv, 0, sizeof(macroblock_2fbmv)); + macroblock_2fbmv.header.dw0.type = CMD_3D; + macroblock_2fbmv.header.dw0.opcode = OPC_3DMPEG_MACROBLOCK; + macroblock_2fbmv.header.dw0.length = 4; + macroblock_2fbmv.header.dw1.mb_intra = 0; /* should be 0 */ + macroblock_2fbmv.header.dw1.forward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_FORWARD) ? 1 : 0); + macroblock_2fbmv.header.dw1.backward = ((mb->macroblock_type & XVMC_MB_TYPE_MOTION_BACKWARD) ? 1 : 0); + macroblock_2fbmv.header.dw1.h263_4mv = 0; /* should be 0 */ + macroblock_2fbmv.header.dw1.dct_type = (mb->dct_type == XVMC_DCT_TYPE_FIELD); + + if (!(mb->coded_block_pattern & 0x3f)) + macroblock_2fbmv.header.dw1.dct_type = XVMC_DCT_TYPE_FRAME; + + macroblock_2fbmv.header.dw1.motion_type = (mb->motion_type & 0x03); + macroblock_2fbmv.header.dw1.vertical_field_select = (mb->motion_vertical_field_select & 0x0f); + macroblock_2fbmv.header.dw1.coded_block_pattern = mb->coded_block_pattern; + macroblock_2fbmv.header.dw1.skipped_macroblocks = 0; + + mv0[0].component[0] = mb->PMV[0][0][0]; + mv0[0].component[1] = mb->PMV[0][0][1]; + mv0[1].component[0] = mb->PMV[0][1][0]; + mv0[1].component[1] = mb->PMV[0][1][1]; + mv1[0].component[0] = mb->PMV[1][0][0]; + mv1[0].component[1] = mb->PMV[1][0][1]; + mv1[1].component[0] = mb->PMV[1][1][0]; + mv1[1].component[1] = mb->PMV[1][1][1]; + + if ((ps & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { + if ((mb->motion_type & 3) == XVMC_PREDICTION_FIELD) { + mv0[0].component[1] = mb->PMV[0][0][1] >> 1; + mv0[1].component[1] = mb->PMV[0][1][1] >> 1; + mv1[0].component[1] = mb->PMV[1][0][1] >> 1; + mv1[1].component[1] = mb->PMV[1][1][1] >> 1; + } else if ((mb->motion_type & 3) == XVMC_PREDICTION_DUAL_PRIME) { + mv0[0].component[1] = mb->PMV[0][0][1] >> 1; + mv0[1].component[1] = mb->PMV[0][1][1] >> 1; // MPEG2 MV[0][1] isn't used + mv1[0].component[1] = mb->PMV[1][0][1] >> 1; + mv1[1].component[1] = mb->PMV[1][1][1] >> 1; + } + } + + macroblock_2fbmv.dw2 = mv0[0].v; + macroblock_2fbmv.dw3 = mv0[1].v; + macroblock_2fbmv.dw4 = mv1[0].v; + macroblock_2fbmv.dw5 = mv1[1].v; + + intelBatchbufferData(¯oblock_2fbmv, sizeof(macroblock_2fbmv), 0); } #if 0 @@ -1646,9 +1601,7 @@ static Status i915_xvmc_mc_create_context(Display *display, XvMCContext *context pI915XvMC->psc.size = tmpComm->psc.size; if (pI915XvMC->deviceID == PCI_CHIP_I915_G || - pI915XvMC->deviceID == PCI_CHIP_I915_GM || - pI915XvMC->deviceID == PCI_CHIP_I945_G || - pI915XvMC->deviceID == PCI_CHIP_I945_GM) { + pI915XvMC->deviceID == PCI_CHIP_I915_GM) { pI915XvMC->sis.bus_addr = tmpComm->sis.bus_addr; pI915XvMC->ssb.bus_addr = tmpComm->ssb.bus_addr; pI915XvMC->msb.bus_addr = tmpComm->msb.bus_addr; @@ -1683,6 +1636,16 @@ static Status i915_xvmc_mc_create_context(Display *display, XvMCContext *context pI915XvMC->last_flip = 0; pI915XvMC->port = context->port; pI915XvMC->ref = 1; + + /* pre-init state buffers */ + i915_mc_one_time_context_init(context); + i915_mc_one_time_state_init(context); + + i915_mc_static_indirect_state_init(context); + + i915_mc_map_state_init(context); + + i915_mc_load_indirect_render_init(context); return Success; } @@ -1695,6 +1658,10 @@ static int i915_xvmc_mc_destroy_context(Display *display, XvMCContext *context) /* Pass Control to the X server to destroy the drm_context_t */ i915_release_resource(display,context); + + free(one_time_load_state_imm1); + free(one_time_load_indirect); + free(mc_render_load_indirect); return Success; } @@ -1850,9 +1817,8 @@ static int i915_xvmc_mc_render_surface(Display *display, XvMCContext *context, if (!(privTarget = target_surface->privData)) return XvMCBadSurface; - /* Test For YV12 Surface */ - if (context->surface_type_id != FOURCC_YV12) { - XVMC_ERR("HWMC only possible on YV12 Surfaces."); + if (context->surface_type_id >= SURFACE_TYPE_MAX) { + XVMC_ERR("Unsupprted surface_type_id %d.", context->surface_type_id); return BadValue; } @@ -1938,16 +1904,15 @@ static int i915_xvmc_mc_render_surface(Display *display, XvMCContext *context, // i915_mc_invalidate_subcontext_buffers(context, BLOCK_SIS | BLOCK_DIS | BLOCK_SSB // | BLOCK_MSB | BLOCK_PSP | BLOCK_PSC); - i915_mc_sampler_state_buffer(context); - i915_mc_pixel_shader_program_buffer(context); - i915_mc_pixel_shader_constants_buffer(context); - i915_mc_one_time_state_initialization(context); + i915_mc_one_time_state_emit(); + + i915_mc_static_indirect_state_set(context, target_surface, picture_structure, + flags, picture_coding_type); + /* setup reference surfaces */ + i915_mc_map_state_set(context, privPast, privFuture); + + i915_mc_load_indirect_render_emit(); - i915_mc_static_indirect_state_buffer(context, target_surface, - picture_structure, flags, - picture_coding_type); - i915_mc_map_state_buffer(context, privTarget, privPast, privFuture); - i915_mc_load_sis_msb_buffers(context); i915_mc_mpeg_set_origin(context, ¯oblock_array->macro_blocks[first_macroblock]); for (i = first_macroblock; i < (num_macroblocks + first_macroblock); i++) { diff --git a/src/xvmc/intel_xvmc.c b/src/xvmc/intel_xvmc.c index ae357aa5..8fabb35e 100644 --- a/src/xvmc/intel_xvmc.c +++ b/src/xvmc/intel_xvmc.c @@ -98,9 +98,17 @@ unsigned int mb_bytes_420[] = { 768 /* 111111 */ }; +int DEBUG; + static int error_base; static int event_base; +static void intel_xvmc_debug_init(void) +{ + if (getenv("INTEL_XVMC_DEBUG")) + DEBUG = 1; +} + /* locking */ static void intel_xvmc_try_heavy_lock(drm_context_t ctx) { @@ -282,6 +290,8 @@ Status XvMCCreateContext(Display *display, XvPortID port, return BadValue; } + intel_xvmc_debug_init(); + /* Open DRI Device */ if((fd = drmOpen("i915", NULL)) < 0) { XVMC_ERR("DRM Device could not be opened."); @@ -588,7 +598,7 @@ Status XvMCCreateBlocks(Display *display, XvMCContext *context, */ Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *block) { - if (!display || block) + if (!display || !block) return BadValue; if (block->blocks) diff --git a/src/xvmc/intel_xvmc.h b/src/xvmc/intel_xvmc.h index 31196238..c4dfd770 100644 --- a/src/xvmc/intel_xvmc.h +++ b/src/xvmc/intel_xvmc.h @@ -38,6 +38,7 @@ #include <string.h> #include <assert.h> #include <signal.h> +#include <stdint.h> #include <xf86drm.h> #include "i830_common.h" @@ -56,7 +57,7 @@ #include "intel_batchbuffer.h" -#define DEBUG 0 +extern int DEBUG; #define XVMC_ERR(s, arg...) \ do { \ diff --git a/src/xvmc/intel_xvmc_dump.c b/src/xvmc/intel_xvmc_dump.c index 12fc52a5..419bd0d8 100644 --- a/src/xvmc/intel_xvmc_dump.c +++ b/src/xvmc/intel_xvmc_dump.c @@ -116,18 +116,25 @@ void intel_xvmc_dump_render(XvMCContext *context, unsigned int picture_structure fprintf(fp, "intra "); fprintf(fp, ") "); fprintf(fp, "mc type "); - if (mb->motion_type & XVMC_PREDICTION_FIELD) - fprintf(fp, "(field) "); - else if (mb->motion_type & XVMC_PREDICTION_FRAME) - fprintf(fp, "(frame) "); - else if (mb->motion_type & XVMC_PREDICTION_DUAL_PRIME) - fprintf(fp, "(dual-prime) "); - else if (mb->motion_type & XVMC_PREDICTION_16x8) - fprintf(fp, "(16x8) "); - else if (mb->motion_type & XVMC_PREDICTION_4MV) - fprintf(fp, "(4MV) "); - else - fprintf(fp, "(none) "); + if (picture_structure == XVMC_FRAME_PICTURE) { + if (mb->motion_type & XVMC_PREDICTION_FIELD) + fprintf(fp, "(field) "); + else if (mb->motion_type & XVMC_PREDICTION_FRAME) + fprintf(fp, "(frame) "); + else if (mb->motion_type & XVMC_PREDICTION_DUAL_PRIME) + fprintf(fp, "(dual-prime) "); + else + fprintf(fp, "(unknown %d) ", mb->motion_type); + } else { /* field */ + if (mb->motion_type & XVMC_PREDICTION_FIELD) + fprintf(fp, "(field) "); + else if (mb->motion_type & XVMC_PREDICTION_DUAL_PRIME) + fprintf(fp, "(dual-prime) "); + else if (mb->motion_type & XVMC_PREDICTION_16x8) + fprintf(fp, "(16x8) "); + else + fprintf(fp, "(unknown %d) ", mb->motion_type); + } if (mb->dct_type == XVMC_DCT_TYPE_FRAME) fprintf(fp, "dct type (frame) "); |