From a397fbca1b8c53c9762ffa49bdf5372d93c0d60a Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Thu, 12 Feb 2009 18:18:14 +0000 Subject: linux-moblin: Update patches --- .../psb-driver.patch | 26303 +++++++++---------- 1 file changed, 12510 insertions(+), 13793 deletions(-) diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.28+2.6.29-rc2/psb-driver.patch b/meta-moblin/packages/linux/linux-moblin-2.6.28+2.6.29-rc2/psb-driver.patch index c515bc60ce..ca449c6cf5 100644 --- a/meta-moblin/packages/linux/linux-moblin-2.6.28+2.6.29-rc2/psb-driver.patch +++ b/meta-moblin/packages/linux/linux-moblin-2.6.28+2.6.29-rc2/psb-driver.patch @@ -337,7 +337,7 @@ Index: linux-2.6.28/include/drm/drm.h Index: linux-2.6.28/include/drm/drmP.h =================================================================== --- linux-2.6.28.orig/include/drm/drmP.h 2009-02-12 09:14:40.000000000 +0000 -+++ linux-2.6.28/include/drm/drmP.h 2009-02-12 09:14:41.000000000 +0000 ++++ linux-2.6.28/include/drm/drmP.h 2009-02-12 15:59:51.000000000 +0000 @@ -57,6 +57,7 @@ #include #include @@ -638,16 +638,6 @@ Index: linux-2.6.28/include/drm/drmP.h /* AGP/GART support (drm_agpsupport.h) */ extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); -@@ -1303,9 +1340,6 @@ - extern int drm_sysfs_device_add(struct drm_minor *minor); - extern void drm_sysfs_hotplug_event(struct drm_device *dev); - extern void drm_sysfs_device_remove(struct drm_minor *minor); --extern char *drm_get_connector_status_name(enum drm_connector_status status); --extern int drm_sysfs_connector_add(struct drm_connector *connector); --extern void drm_sysfs_connector_remove(struct drm_connector *connector); - - /* - * Basic memory manager support (drm_mm.c) Index: linux-2.6.28/include/drm/drm_pciids.h =================================================================== --- linux-2.6.28.orig/include/drm/drm_pciids.h 2009-02-12 09:14:31.000000000 +0000 @@ -665,8 +655,8 @@ Index: linux-2.6.28/include/drm/drm_pciids.h Index: linux-2.6.28/drivers/gpu/drm/Makefile =================================================================== --- linux-2.6.28.orig/drivers/gpu/drm/Makefile 2009-02-12 09:14:37.000000000 +0000 -+++ linux-2.6.28/drivers/gpu/drm/Makefile 2009-02-12 09:14:41.000000000 +0000 -@@ -10,8 +10,11 @@ ++++ linux-2.6.28/drivers/gpu/drm/Makefile 2009-02-12 16:00:51.000000000 +0000 +@@ -10,6 +10,8 @@ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ @@ -674,11 +664,8 @@ Index: linux-2.6.28/drivers/gpu/drm/Makefile + drm_bo_lock.o drm_bo_move.o drm_regman.o \ drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o -+ drm-$(CONFIG_COMPAT) += drm_ioc32.o - - obj-$(CONFIG_DRM) += drm.o -@@ -22,6 +25,7 @@ +@@ -22,6 +24,7 @@ obj-$(CONFIG_DRM_I810) += i810/ obj-$(CONFIG_DRM_I830) += i830/ obj-$(CONFIG_DRM_I915) += i915/ @@ -7239,2730 +7226,1929 @@ Index: linux-2.6.28/drivers/gpu/drm/psb/Makefile + psb_schedule.o psb_xhw.o + +obj-$(CONFIG_DRM_PSB) += psb.o -Index: linux-2.6.28/drivers/gpu/drm/psb/i915_reg.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.28/drivers/gpu/drm/psb/i915_reg.h 2009-02-12 09:14:41.000000000 +0000 -@@ -0,0 +1,67 @@ -+#include "../i915/i915_reg.h" -+ -+ -+/*#define IS_I830(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82830_CGC) -+#define IS_845G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82845G_IG) -+#define IS_I85X(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG) -+#define IS_I855(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG) -+#define IS_I865G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82865_IG) -+ -+#define IS_I915G(dev) (dev->pci_device == PCI_DEVICE_ID_INTEL_82915G_IG) -+#define IS_I915GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82915GM_IG) -+#define IS_I945G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945G_IG) -+#define IS_I945GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945GM_IG) -+ -+#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \ -+ (dev)->pci_device == 0x2982 || \ -+ (dev)->pci_device == 0x2992 || \ -+ (dev)->pci_device == 0x29A2 || \ -+ (dev)->pci_device == 0x2A02 || \ -+ (dev)->pci_device == 0x2A12) -+ -+#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02) -+ -+#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ -+ (dev)->pci_device == 0x29B2 || \ -+ (dev)->pci_device == 0x29D2) -+ -+#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \ -+ IS_I945GM(dev) || IS_I965G(dev) || IS_POULSBO(dev)) -+ -+#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ -+ IS_I945GM(dev) || IS_I965GM(dev) || IS_POULSBO(dev)) -+ -+#define IS_POULSBO(dev) (((dev)->pci_device == 0x8108) || \ -+ ((dev)->pci_device == 0x8109))*/ -+ -+#define FPA0 0x06040 -+#define FPA1 0x06044 -+#define FPB0 0x06048 -+#define FPB1 0x0604c -+#define FP_N_DIV_MASK 0x003f0000 -+#define FP_N_DIV_SHIFT 16 -+#define FP_M1_DIV_MASK 0x00003f00 -+#define FP_M1_DIV_SHIFT 8 -+#define FP_M2_DIV_MASK 0x0000003f -+#define FP_M2_DIV_SHIFT 0 -+ -+#define DPLL_B_MD 0x06020 -+ -+#define ADPA 0x61100 -+#define ADPA_DAC_ENABLE (1<<31) -+#define ADPA_DAC_DISABLE 0 -+#define ADPA_PIPE_SELECT_MASK (1<<30) -+#define ADPA_PIPE_A_SELECT 0 -+#define ADPA_PIPE_B_SELECT (1<<30) -+#define ADPA_USE_VGA_HVPOLARITY (1<<15) -+#define ADPA_SETS_HVPOLARITY 0 -+#define ADPA_VSYNC_CNTL_DISABLE (1<<11) -+#define ADPA_VSYNC_CNTL_ENABLE 0 -+#define ADPA_HSYNC_CNTL_DISABLE (1<<10) -+#define ADPA_HSYNC_CNTL_ENABLE 0 -+#define ADPA_VSYNC_ACTIVE_HIGH (1<<4) -+#define ADPA_VSYNC_ACTIVE_LOW 0 -+#define ADPA_HSYNC_ACTIVE_HIGH (1<<3) -+#define ADPA_HSYNC_ACTIVE_LOW 0 -+ -+ -Index: linux-2.6.28/drivers/gpu/drm/psb/intel_display.c +Index: linux-2.6.28/drivers/gpu/drm/psb/psb_buffer.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.28/drivers/gpu/drm/psb/intel_display.c 2009-02-12 09:14:41.000000000 +0000 -@@ -0,0 +1,1813 @@ -+/* -+ * Copyright © 2006-2007 Intel Corporation ++++ linux-2.6.28/drivers/gpu/drm/psb/psb_buffer.c 2009-02-12 09:14:41.000000000 +0000 +@@ -0,0 +1,437 @@ ++/************************************************************************** ++ * Copyright (c) 2007, Intel Corporation. ++ * All Rights Reserved. + * -+ * 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: ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. + * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. + * -+ * 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. ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * -+ * Authors: -+ * Eric Anholt ++ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to ++ * develop this driver. ++ * ++ **************************************************************************/ ++/* ++ * Authors: Thomas Hellstrom + */ -+ -+#include +#include "drmP.h" -+#include "../i915/intel_drv.h" -+#include "i915_drm.h" -+#include "../i915/i915_drv.h" -+ -+#include "drm_crtc_helper.h" ++#include "psb_drv.h" ++#include "psb_schedule.h" + -+bool intel_pipe_has_type (struct drm_crtc *crtc, int type); -+ -+typedef struct { -+ /* given values */ -+ int n; -+ int m1, m2; -+ int p1, p2; -+ /* derived values */ -+ int dot; -+ int vco; -+ int m; -+ int p; -+} intel_clock_t; -+ -+typedef struct { -+ int min, max; -+} intel_range_t; -+ -+typedef struct { -+ int dot_limit; -+ int p2_slow, p2_fast; -+} intel_p2_t; -+ -+#define INTEL_P2_NUM 2 -+ -+typedef struct { -+ intel_range_t dot, vco, n, m, m1, m2, p, p1; -+ intel_p2_t p2; -+} intel_limit_t; -+ -+#define I8XX_DOT_MIN 25000 -+#define I8XX_DOT_MAX 350000 -+#define I8XX_VCO_MIN 930000 -+#define I8XX_VCO_MAX 1400000 -+#define I8XX_N_MIN 3 -+#define I8XX_N_MAX 16 -+#define I8XX_M_MIN 96 -+#define I8XX_M_MAX 140 -+#define I8XX_M1_MIN 18 -+#define I8XX_M1_MAX 26 -+#define I8XX_M2_MIN 6 -+#define I8XX_M2_MAX 16 -+#define I8XX_P_MIN 4 -+#define I8XX_P_MAX 128 -+#define I8XX_P1_MIN 2 -+#define I8XX_P1_MAX 33 -+#define I8XX_P1_LVDS_MIN 1 -+#define I8XX_P1_LVDS_MAX 6 -+#define I8XX_P2_SLOW 4 -+#define I8XX_P2_FAST 2 -+#define I8XX_P2_LVDS_SLOW 14 -+#define I8XX_P2_LVDS_FAST 14 /* No fast option */ -+#define I8XX_P2_SLOW_LIMIT 165000 -+ -+#define I9XX_DOT_MIN 20000 -+#define I9XX_DOT_MAX 400000 -+#define I9XX_VCO_MIN 1400000 -+#define I9XX_VCO_MAX 2800000 -+#define I9XX_N_MIN 3 -+#define I9XX_N_MAX 8 -+#define I9XX_M_MIN 70 -+#define I9XX_M_MAX 120 -+#define I9XX_M1_MIN 10 -+#define I9XX_M1_MAX 20 -+#define I9XX_M2_MIN 5 -+#define I9XX_M2_MAX 9 -+#define I9XX_P_SDVO_DAC_MIN 5 -+#define I9XX_P_SDVO_DAC_MAX 80 -+#define I9XX_P_LVDS_MIN 7 -+#define I9XX_P_LVDS_MAX 98 -+#define I9XX_P1_MIN 1 -+#define I9XX_P1_MAX 8 -+#define I9XX_P2_SDVO_DAC_SLOW 10 -+#define I9XX_P2_SDVO_DAC_FAST 5 -+#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 -+#define I9XX_P2_LVDS_SLOW 14 -+#define I9XX_P2_LVDS_FAST 7 -+#define I9XX_P2_LVDS_SLOW_LIMIT 112000 -+ -+#define INTEL_LIMIT_I8XX_DVO_DAC 0 -+#define INTEL_LIMIT_I8XX_LVDS 1 -+#define INTEL_LIMIT_I9XX_SDVO_DAC 2 -+#define INTEL_LIMIT_I9XX_LVDS 3 -+ -+static const intel_limit_t intel_limits[] = { -+ { /* INTEL_LIMIT_I8XX_DVO_DAC */ -+ .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, -+ .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, -+ .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, -+ .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, -+ .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, -+ .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, -+ .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, -+ .p1 = { .min = I8XX_P1_MIN, .max = I8XX_P1_MAX }, -+ .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, -+ .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, -+ }, -+ { /* INTEL_LIMIT_I8XX_LVDS */ -+ .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, -+ .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, -+ .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, -+ .m = { .min = I8XX_M_MIN, .max = I8XX_M_MAX }, -+ .m1 = { .min = I8XX_M1_MIN, .max = I8XX_M1_MAX }, -+ .m2 = { .min = I8XX_M2_MIN, .max = I8XX_M2_MAX }, -+ .p = { .min = I8XX_P_MIN, .max = I8XX_P_MAX }, -+ .p1 = { .min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX }, -+ .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, -+ .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, -+ }, -+ { /* INTEL_LIMIT_I9XX_SDVO_DAC */ -+ .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, -+ .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, -+ .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, -+ .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, -+ .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, -+ .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, -+ .p = { .min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX }, -+ .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, -+ .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, -+ .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, -+ }, -+ { /* INTEL_LIMIT_I9XX_LVDS */ -+ .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, -+ .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, -+ .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, -+ .m = { .min = I9XX_M_MIN, .max = I9XX_M_MAX }, -+ .m1 = { .min = I9XX_M1_MIN, .max = I9XX_M1_MAX }, -+ .m2 = { .min = I9XX_M2_MIN, .max = I9XX_M2_MAX }, -+ .p = { .min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX }, -+ .p1 = { .min = I9XX_P1_MIN, .max = I9XX_P1_MAX }, -+ /* The single-channel range is 25-112Mhz, and dual-channel -+ * is 80-224Mhz. Prefer single channel as much as possible. -+ */ -+ .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, -+ .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, -+ }, ++struct drm_psb_ttm_backend { ++ struct drm_ttm_backend base; ++ struct page **pages; ++ unsigned int desired_tile_stride; ++ unsigned int hw_tile_stride; ++ int mem_type; ++ unsigned long offset; ++ unsigned long num_pages; +}; + -+static const intel_limit_t *intel_limit(struct drm_crtc *crtc) ++int psb_fence_types(struct drm_buffer_object *bo, uint32_t * class, ++ uint32_t * type) +{ -+ struct drm_device *dev = crtc->dev; -+ const intel_limit_t *limit; -+ -+ if (IS_I9XX(dev)) { -+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) -+ limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; -+ else -+ limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; -+ } else { -+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) -+ limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; -+ else -+ limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; ++ switch (*class) { ++ case PSB_ENGINE_TA: ++ *type = DRM_FENCE_TYPE_EXE | ++ _PSB_FENCE_TYPE_TA_DONE | _PSB_FENCE_TYPE_RASTER_DONE; ++ if (bo->mem.mask & PSB_BO_FLAG_TA) ++ *type &= ~_PSB_FENCE_TYPE_RASTER_DONE; ++ if (bo->mem.mask & PSB_BO_FLAG_SCENE) ++ *type |= _PSB_FENCE_TYPE_SCENE_DONE; ++ if (bo->mem.mask & PSB_BO_FLAG_FEEDBACK) ++ *type |= _PSB_FENCE_TYPE_FEEDBACK; ++ break; ++ default: ++ *type = DRM_FENCE_TYPE_EXE; + } -+ return limit; ++ return 0; +} + -+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ -+ -+static void i8xx_clock(int refclk, intel_clock_t *clock) ++static inline size_t drm_size_align(size_t size) +{ -+ clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); -+ clock->p = clock->p1 * clock->p2; -+ clock->vco = refclk * clock->m / (clock->n + 2); -+ clock->dot = clock->vco / clock->p; ++ size_t tmpSize = 4; ++ if (size > PAGE_SIZE) ++ return PAGE_ALIGN(size); ++ while (tmpSize < size) ++ tmpSize <<= 1; ++ ++ return (size_t) tmpSize; +} + -+/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ ++/* ++ * Poulsbo GPU virtual space looks like this ++ * (We currently use only one MMU context). ++ * ++ * gatt_start = Start of GATT aperture in bus space. ++ * stolen_end = End of GATT populated by stolen memory in bus space. ++ * gatt_end = End of GATT ++ * twod_end = MIN(gatt_start + 256_MEM, gatt_end) ++ * ++ * 0x00000000 -> 0x10000000 Temporary mapping space for tiling- and copy operations. ++ * This space is not managed and is protected by the ++ * temp_mem mutex. ++ * ++ * 0x10000000 -> 0x20000000 DRM_PSB_MEM_KERNEL For kernel buffers. ++ * ++ * 0x20000000 -> gatt_start DRM_PSB_MEM_MMU For generic MMU-only use. ++ * ++ * gatt_start -> stolen_end DRM_BO_MEM_VRAM Pre-populated GATT pages. ++ * ++ * stolen_end -> twod_end DRM_BO_MEM_TT GATT memory usable by 2D engine. ++ * ++ * twod_end -> gatt_end DRM_BO_MEM_APER GATT memory not usable by 2D engine. ++ * ++ * gatt_end -> 0xffffffff Currently unused. ++ */ + -+static void i9xx_clock(int refclk, intel_clock_t *clock) ++int psb_init_mem_type(struct drm_device *dev, uint32_t type, ++ struct drm_mem_type_manager *man) +{ -+ clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); -+ clock->p = clock->p1 * clock->p2; -+ clock->vco = refclk * clock->m / (clock->n + 2); -+ clock->dot = clock->vco / clock->p; -+} ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; ++ struct psb_gtt *pg = dev_priv->pg; + -+static void intel_clock(struct drm_device *dev, int refclk, -+ intel_clock_t *clock) -+{ -+ if (IS_I9XX(dev)) -+ i9xx_clock (refclk, clock); -+ else -+ i8xx_clock (refclk, clock); ++ switch (type) { ++ case DRM_BO_MEM_LOCAL: ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_CACHED; ++ man->drm_bus_maptype = 0; ++ break; ++ case DRM_PSB_MEM_KERNEL: ++ man->io_offset = 0x00000000; ++ man->io_size = 0x00000000; ++ man->io_addr = NULL; ++ man->drm_bus_maptype = _DRM_TTM; ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_MEMTYPE_CMA; ++ man->gpu_offset = PSB_MEM_KERNEL_START; ++ break; ++ case DRM_PSB_MEM_MMU: ++ man->io_offset = 0x00000000; ++ man->io_size = 0x00000000; ++ man->io_addr = NULL; ++ man->drm_bus_maptype = _DRM_TTM; ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_MEMTYPE_CMA; ++ man->gpu_offset = PSB_MEM_MMU_START; ++ break; ++ case DRM_PSB_MEM_PDS: ++ man->io_offset = 0x00000000; ++ man->io_size = 0x00000000; ++ man->io_addr = NULL; ++ man->drm_bus_maptype = _DRM_TTM; ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_MEMTYPE_CMA; ++ man->gpu_offset = PSB_MEM_PDS_START; ++ break; ++ case DRM_PSB_MEM_RASTGEOM: ++ man->io_offset = 0x00000000; ++ man->io_size = 0x00000000; ++ man->io_addr = NULL; ++ man->drm_bus_maptype = _DRM_TTM; ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_MEMTYPE_CMA; ++ man->gpu_offset = PSB_MEM_RASTGEOM_START; ++ break; ++ case DRM_BO_MEM_VRAM: ++ man->io_addr = NULL; ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_FIXED | _DRM_FLAG_NEEDS_IOREMAP; ++#ifdef PSB_WORKING_HOST_MMU_ACCESS ++ man->drm_bus_maptype = _DRM_AGP; ++ man->io_offset = pg->gatt_start; ++ man->io_size = pg->gatt_pages << PAGE_SHIFT; ++#else ++ man->drm_bus_maptype = _DRM_TTM; /* Forces uncached */ ++ man->io_offset = pg->stolen_base; ++ man->io_size = pg->stolen_size; ++#endif ++ man->gpu_offset = pg->gatt_start; ++ break; ++ case DRM_BO_MEM_TT: /* Mappable GATT memory */ ++ man->io_offset = pg->gatt_start; ++ man->io_size = pg->gatt_pages << PAGE_SHIFT; ++ man->io_addr = NULL; ++#ifdef PSB_WORKING_HOST_MMU_ACCESS ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP; ++ man->drm_bus_maptype = _DRM_AGP; ++#else ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_MEMTYPE_CMA; ++ man->drm_bus_maptype = _DRM_TTM; ++#endif ++ man->gpu_offset = pg->gatt_start; ++ break; ++ case DRM_PSB_MEM_APER: /*MMU memory. Mappable. Not usable for 2D. */ ++ man->io_offset = pg->gatt_start; ++ man->io_size = pg->gatt_pages << PAGE_SHIFT; ++ man->io_addr = NULL; ++#ifdef PSB_WORKING_HOST_MMU_ACCESS ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP; ++ man->drm_bus_maptype = _DRM_AGP; ++#else ++ man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE | ++ _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_MEMTYPE_CMA; ++ man->drm_bus_maptype = _DRM_TTM; ++#endif ++ man->gpu_offset = pg->gatt_start; ++ break; ++ default: ++ DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); ++ return -EINVAL; ++ } ++ return 0; +} + -+/** -+ * Returns whether any output on the specified pipe is of the specified type -+ */ -+bool intel_pipe_has_type (struct drm_crtc *crtc, int type) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct drm_mode_config *mode_config = &dev->mode_config; -+ struct drm_connector *l_entry; -+ -+ list_for_each_entry(l_entry, &mode_config->connector_list, head) { -+ if (l_entry->encoder && -+ l_entry->encoder->crtc == crtc) { -+ struct intel_output *intel_output = to_intel_output(l_entry); -+ if (intel_output->type == type) -+ return true; -+ } -+ } -+ return false; ++uint32_t psb_evict_mask(struct drm_buffer_object * bo) ++{ ++ switch (bo->mem.mem_type) { ++ case DRM_BO_MEM_VRAM: ++ return DRM_BO_FLAG_MEM_TT; ++ default: ++ return DRM_BO_FLAG_MEM_LOCAL; ++ } +} + -+#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } -+/** -+ * Returns whether the given set of divisors are valid for a given refclk with -+ * the given connectors. -+ */ -+ -+static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) -+{ -+ const intel_limit_t *limit = intel_limit (crtc); -+ -+ if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) -+ INTELPllInvalid ("p1 out of range\n"); -+ if (clock->p < limit->p.min || limit->p.max < clock->p) -+ INTELPllInvalid ("p out of range\n"); -+ if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) -+ INTELPllInvalid ("m2 out of range\n"); -+ if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) -+ INTELPllInvalid ("m1 out of range\n"); -+ if (clock->m1 <= clock->m2) -+ INTELPllInvalid ("m1 <= m2\n"); -+ if (clock->m < limit->m.min || limit->m.max < clock->m) -+ INTELPllInvalid ("m out of range\n"); -+ if (clock->n < limit->n.min || limit->n.max < clock->n) -+ INTELPllInvalid ("n out of range\n"); -+ if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) -+ INTELPllInvalid ("vco out of range\n"); -+ /* XXX: We may need to be checking "Dot clock" depending on the multiplier, -+ * connector, etc., rather than just a single range. -+ */ -+ if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) -+ INTELPllInvalid ("dot out of range\n"); -+ -+ return true; ++int psb_invalidate_caches(struct drm_device *dev, uint64_t flags) ++{ ++ return 0; +} + -+/** -+ * Returns a set of divisors for the desired target clock with the given -+ * refclk, or FALSE. The returned values represent the clock equation: -+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. -+ */ -+static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, -+ int refclk, intel_clock_t *best_clock) ++static int psb_move_blit(struct drm_buffer_object *bo, ++ int evict, int no_wait, struct drm_bo_mem_reg *new_mem) +{ -+ struct drm_device *dev = crtc->dev; -+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; -+ intel_clock_t clock; -+ const intel_limit_t *limit = intel_limit(crtc); -+ int err = target; ++ struct drm_bo_mem_reg *old_mem = &bo->mem; ++ int dir = 0; + -+ if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && -+ (I915_READ(LVDS) & LVDS_PORT_EN) != 0) { -+ /* -+ * For LVDS, if the panel is on, just rely on its current -+ * settings for dual-channel. We haven't figured out how to -+ * reliably set up different single/dual channel state, if we -+ * even can. -+ */ -+ if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == -+ LVDS_CLKB_POWER_UP) -+ clock.p2 = limit->p2.p2_fast; -+ else -+ clock.p2 = limit->p2.p2_slow; -+ } else { -+ if (target < limit->p2.dot_limit) -+ clock.p2 = limit->p2.p2_slow; -+ else -+ clock.p2 = limit->p2.p2_fast; ++ if ((old_mem->mem_type == new_mem->mem_type) && ++ (new_mem->mm_node->start < ++ old_mem->mm_node->start + old_mem->mm_node->size)) { ++ dir = 1; + } + -+ memset (best_clock, 0, sizeof (*best_clock)); ++ psb_emit_2d_copy_blit(bo->dev, ++ old_mem->mm_node->start << PAGE_SHIFT, ++ new_mem->mm_node->start << PAGE_SHIFT, ++ new_mem->num_pages, dir); + -+ for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { -+ for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 && -+ clock.m2 <= limit->m2.max; clock.m2++) { -+ for (clock.n = limit->n.min; clock.n <= limit->n.max; -+ clock.n++) { -+ for (clock.p1 = limit->p1.min; -+ clock.p1 <= limit->p1.max; clock.p1++) { -+ int this_err; ++ return drm_bo_move_accel_cleanup(bo, evict, no_wait, 0, ++ DRM_FENCE_TYPE_EXE, 0, new_mem); ++} + -+ intel_clock(dev, refclk, &clock); ++/* ++ * Flip destination ttm into cached-coherent GATT, ++ * then blit and subsequently move out again. ++ */ + -+ if (!intel_PLL_is_valid(crtc, &clock)) -+ continue; ++static int psb_move_flip(struct drm_buffer_object *bo, ++ int evict, int no_wait, struct drm_bo_mem_reg *new_mem) ++{ ++ struct drm_device *dev = bo->dev; ++ struct drm_bo_mem_reg tmp_mem; ++ int ret; + -+ this_err = abs(clock.dot - target); -+ if (this_err < err) { -+ *best_clock = clock; -+ err = this_err; -+ } -+ } -+ } -+ } -+ } ++ tmp_mem = *new_mem; ++ tmp_mem.mm_node = NULL; ++ tmp_mem.mask = DRM_BO_FLAG_MEM_TT | ++ DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING; + -+ return (err != target); -+} ++ ret = drm_bo_mem_space(bo, &tmp_mem, no_wait); ++ if (ret) ++ return ret; ++ ret = drm_bind_ttm(bo->ttm, &tmp_mem); ++ if (ret) ++ goto out_cleanup; ++ ret = psb_move_blit(bo, 1, no_wait, &tmp_mem); ++ if (ret) ++ goto out_cleanup; + -+void -+intel_wait_for_vblank(struct drm_device *dev) -+{ -+ /* Wait for 20ms, i.e. one cycle at 50hz. */ -+ udelay(20000); ++ ret = drm_bo_move_ttm(bo, evict, no_wait, new_mem); ++ out_cleanup: ++ if (tmp_mem.mm_node) { ++ mutex_lock(&dev->struct_mutex); ++ if (tmp_mem.mm_node != bo->pinned_node) ++ drm_mm_put_block(tmp_mem.mm_node); ++ tmp_mem.mm_node = NULL; ++ mutex_unlock(&dev->struct_mutex); ++ } ++ return ret; +} + -+static void -+intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, -+ struct drm_framebuffer *old_fb) ++int psb_move(struct drm_buffer_object *bo, ++ int evict, int no_wait, struct drm_bo_mem_reg *new_mem) +{ -+ struct drm_device *dev = crtc->dev; -+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ unsigned long Start, Offset; -+ int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); -+ int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); -+ int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; -+ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -+ u32 dspcntr, alignment; -+ -+ Start = crtc->fb->offset; -+ Offset = y * crtc->fb->pitch + x; ++ struct drm_bo_mem_reg *old_mem = &bo->mem; + -+ DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); -+ if (IS_I965G(dev)) { -+ I915_WRITE(dspbase, Offset); -+ I915_READ(dspbase); -+ I915_WRITE(dspsurf, Start); -+ I915_READ(dspsurf); ++ if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { ++ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); ++ } else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { ++ if (psb_move_flip(bo, evict, no_wait, new_mem)) ++ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } else { -+ I915_WRITE(dspbase, Start + Offset); -+ I915_READ(dspbase); ++ if (psb_move_blit(bo, evict, no_wait, new_mem)) ++ return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); + } ++ return 0; ++} + -+ -+ if (!dev_priv->sarea_priv) -+ return; -+ -+ switch (pipe) { -+ case 0: -+ dev_priv->sarea_priv->pipeA_x = x; -+ dev_priv->sarea_priv->pipeA_y = y; -+ break; -+ case 1: -+ dev_priv->sarea_priv->pipeB_x = x; -+ dev_priv->sarea_priv->pipeB_y = y; -+ break; -+ default: -+ DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); -+ break; -+ } ++static int drm_psb_tbe_nca(struct drm_ttm_backend *backend) ++{ ++ return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1); +} + ++static int drm_psb_tbe_populate(struct drm_ttm_backend *backend, ++ unsigned long num_pages, struct page **pages) ++{ ++ struct drm_psb_ttm_backend *psb_be = ++ container_of(backend, struct drm_psb_ttm_backend, base); + ++ psb_be->pages = pages; ++ return 0; ++} + -+/** -+ * Sets the power management mode of the pipe and plane. -+ * -+ * This code should probably grow support for turning the cursor off and back -+ * on appropriately at the same time as we're turning the pipe off/on. -+ */ -+static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) ++static int drm_psb_tbe_unbind(struct drm_ttm_backend *backend) +{ -+ struct drm_device *dev = crtc->dev; -+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -+ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -+ int dspbase_reg = (pipe == 0) ? DSPAADDR : DSPBADDR; -+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -+ u32 temp; -+ bool enabled; ++ struct drm_device *dev = backend->dev; ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; ++ struct drm_psb_ttm_backend *psb_be = ++ container_of(backend, struct drm_psb_ttm_backend, base); ++ struct psb_mmu_pd *pd = psb_mmu_get_default_pd(dev_priv->mmu); ++ struct drm_mem_type_manager *man = &dev->bm.man[psb_be->mem_type]; + -+ /* XXX: When our outputs are all unaware of DPMS modes other than off -+ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. -+ */ -+ switch (mode) { -+ case DRM_MODE_DPMS_ON: -+ case DRM_MODE_DPMS_STANDBY: -+ case DRM_MODE_DPMS_SUSPEND: -+ /* Enable the DPLL */ -+ temp = I915_READ(dpll_reg); -+ if ((temp & DPLL_VCO_ENABLE) == 0) { -+ I915_WRITE(dpll_reg, temp); -+ I915_READ(dpll_reg); -+ /* Wait for the clocks to stabilize. */ -+ udelay(150); -+ I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -+ I915_READ(dpll_reg); -+ /* Wait for the clocks to stabilize. */ -+ udelay(150); -+ I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -+ I915_READ(dpll_reg); -+ /* Wait for the clocks to stabilize. */ -+ udelay(150); -+ } ++ PSB_DEBUG_RENDER("MMU unbind.\n"); + -+ /* Enable the pipe */ -+ temp = I915_READ(pipeconf_reg); -+ if ((temp & PIPEACONF_ENABLE) == 0) -+ I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); -+ -+ /* Enable the plane */ -+ temp = I915_READ(dspcntr_reg); -+ if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -+ I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); -+ /* Flush the plane changes */ -+ I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); -+ } ++ if (psb_be->mem_type == DRM_BO_MEM_TT) { ++ uint32_t gatt_p_offset = (psb_be->offset - man->gpu_offset) >> ++ PAGE_SHIFT; + -+ intel_crtc_load_lut(crtc); -+ -+ /* Give the overlay scaler a chance to enable if it's on this pipe */ -+ //intel_crtc_dpms_video(crtc, true); TODO -+ break; -+ case DRM_MODE_DPMS_OFF: -+ /* Give the overlay scaler a chance to disable if it's on this pipe */ -+ //intel_crtc_dpms_video(crtc, FALSE); TODO -+ -+ /* Disable the VGA plane that we never use */ -+ I915_WRITE(VGACNTRL, VGA_DISP_DISABLE); -+ -+ /* Disable display plane */ -+ temp = I915_READ(dspcntr_reg); -+ if ((temp & DISPLAY_PLANE_ENABLE) != 0) { -+ I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); -+ /* Flush the plane changes */ -+ I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); -+ I915_READ(dspbase_reg); -+ } ++ (void)psb_gtt_remove_pages(dev_priv->pg, gatt_p_offset, ++ psb_be->num_pages, ++ psb_be->desired_tile_stride, ++ psb_be->hw_tile_stride); ++ } + -+ if (!IS_I9XX(dev)) { -+ /* Wait for vblank for the disable to take effect */ -+ intel_wait_for_vblank(dev); -+ } ++ psb_mmu_remove_pages(pd, psb_be->offset, ++ psb_be->num_pages, ++ psb_be->desired_tile_stride, ++ psb_be->hw_tile_stride); + -+ /* Next, disable display pipes */ -+ temp = I915_READ(pipeconf_reg); -+ if ((temp & PIPEACONF_ENABLE) != 0) { -+ I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); -+ I915_READ(pipeconf_reg); -+ } ++ return 0; ++} + -+ /* Wait for vblank for the disable to take effect. */ -+ intel_wait_for_vblank(dev); ++static int drm_psb_tbe_bind(struct drm_ttm_backend *backend, ++ struct drm_bo_mem_reg *bo_mem) ++{ ++ struct drm_device *dev = backend->dev; ++ struct drm_psb_private *dev_priv = ++ (struct drm_psb_private *)dev->dev_private; ++ struct drm_psb_ttm_backend *psb_be = ++ container_of(backend, struct drm_psb_ttm_backend, base); ++ struct psb_mmu_pd *pd = psb_mmu_get_default_pd(dev_priv->mmu); ++ struct drm_mem_type_manager *man = &dev->bm.man[bo_mem->mem_type]; ++ int type; ++ int ret = 0; + -+ temp = I915_READ(dpll_reg); -+ if ((temp & DPLL_VCO_ENABLE) != 0) { -+ I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); -+ I915_READ(dpll_reg); -+ } ++ psb_be->mem_type = bo_mem->mem_type; ++ psb_be->num_pages = bo_mem->num_pages; ++ psb_be->desired_tile_stride = bo_mem->desired_tile_stride; ++ psb_be->hw_tile_stride = bo_mem->hw_tile_stride; ++ psb_be->desired_tile_stride = 0; ++ psb_be->hw_tile_stride = 0; ++ psb_be->offset = (bo_mem->mm_node->start << PAGE_SHIFT) + ++ man->gpu_offset; + -+ /* Wait for the clocks to turn off. */ -+ udelay(150); -+ break; -+ } ++ type = (bo_mem->flags & DRM_BO_FLAG_CACHED) ? PSB_MMU_CACHED_MEMORY : 0; + ++ PSB_DEBUG_RENDER("MMU bind.\n"); ++ if (psb_be->mem_type == DRM_BO_MEM_TT) { ++ uint32_t gatt_p_offset = (psb_be->offset - man->gpu_offset) >> ++ PAGE_SHIFT; + -+ if (!dev_priv->sarea_priv) -+ return; ++ ret = psb_gtt_insert_pages(dev_priv->pg, psb_be->pages, ++ gatt_p_offset, ++ psb_be->num_pages, ++ psb_be->desired_tile_stride, ++ psb_be->hw_tile_stride, type); ++ } + -+ enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; ++ ret = psb_mmu_insert_pages(pd, psb_be->pages, ++ psb_be->offset, psb_be->num_pages, ++ psb_be->desired_tile_stride, ++ psb_be->hw_tile_stride, type); ++ if (ret) ++ goto out_err; + -+ switch (pipe) { -+ case 0: -+ dev_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0; -+ dev_priv->sarea_priv->pipeA_h = enabled ? crtc->mode.vdisplay : 0; -+ break; -+ case 1: -+ dev_priv->sarea_priv->pipeB_w = enabled ? crtc->mode.hdisplay : 0; -+ dev_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; -+ break; -+ default: -+ DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); -+ break; -+ } ++ DRM_FLAG_MASKED(backend->flags, (bo_mem->flags & DRM_BO_FLAG_CACHED) ? ++ DRM_BE_FLAG_BOUND_CACHED : 0, DRM_BE_FLAG_BOUND_CACHED); + -+ intel_crtc->dpms_mode = mode; -+} ++ return 0; ++ out_err: ++ drm_psb_tbe_unbind(backend); ++ return ret; + -+static void intel_crtc_prepare (struct drm_crtc *crtc) -+{ -+ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); +} + -+static void intel_crtc_commit (struct drm_crtc *crtc) ++static void drm_psb_tbe_clear(struct drm_ttm_backend *backend) +{ -+ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -+} ++ struct drm_psb_ttm_backend *psb_be = ++ container_of(backend, struct drm_psb_ttm_backend, base); + -+void intel_encoder_prepare (struct drm_encoder *encoder) -+{ -+ struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; -+ /* lvds has its own version of prepare see intel_lvds_prepare */ -+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); ++ psb_be->pages = NULL; ++ return; +} + -+void intel_encoder_commit (struct drm_encoder *encoder) ++static void drm_psb_tbe_destroy(struct drm_ttm_backend *backend) +{ -+ struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; -+ /* lvds has its own version of commit see intel_lvds_commit */ -+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); -+} ++ struct drm_psb_ttm_backend *psb_be = ++ container_of(backend, struct drm_psb_ttm_backend, base); + -+static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, -+ struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ return true; ++ if (backend) ++ drm_free(psb_be, sizeof(*psb_be), DRM_MEM_TTM); +} + ++static struct drm_ttm_backend_func psb_ttm_backend = { ++ .needs_ub_cache_adjust = drm_psb_tbe_nca, ++ .populate = drm_psb_tbe_populate, ++ .clear = drm_psb_tbe_clear, ++ .bind = drm_psb_tbe_bind, ++ .unbind = drm_psb_tbe_unbind, ++ .destroy = drm_psb_tbe_destroy, ++}; + -+/** Returns the core display clock speed for i830 - i945 */ -+static int intel_get_core_clock_speed(struct drm_device *dev) ++struct drm_ttm_backend *drm_psb_tbe_init(struct drm_device *dev) +{ ++ struct drm_psb_ttm_backend *psb_be; + -+ /* Core clock values taken from the published datasheets. -+ * The 830 may go up to 166 Mhz, which we should check. -+ */ -+ if (IS_I945G(dev)) -+ return 400000; -+ else if (IS_I915G(dev)) -+ return 333000; -+ else if (IS_I945GM(dev) || IS_POULSBO(dev) || IS_845G(dev)) -+ return 200000; -+ else if (IS_I915GM(dev)) { -+ u16 gcfgc = 0; -+ -+ pci_read_config_word(dev->pdev, GCFGC, &gcfgc); -+ -+ if (gcfgc & GC_LOW_FREQUENCY_ENABLE) -+ return 133000; -+ else { -+ switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { -+ case GC_DISPLAY_CLOCK_333_MHZ: -+ return 333000; -+ default: -+ case GC_DISPLAY_CLOCK_190_200_MHZ: -+ return 190000; -+ } -+ } -+ } else if (IS_I865G(dev)) -+ return 266000; -+ else if (IS_I855(dev)) { -+ u16 hpllcc = 0; -+ /* Assume that the hardware is in the high speed state. This -+ * should be the default. -+ */ -+ switch (hpllcc & GC_CLOCK_CONTROL_MASK) { -+ case GC_CLOCK_133_200: -+ case GC_CLOCK_100_200: -+ return 200000; -+ case GC_CLOCK_166_250: -+ return 250000; -+ case GC_CLOCK_100_133: -+ return 133000; -+ } -+ } else /* 852, 830 */ -+ return 133000; ++ psb_be = drm_calloc(1, sizeof(*psb_be), DRM_MEM_TTM); ++ if (!psb_be) ++ return NULL; ++ psb_be->pages = NULL; ++ psb_be->base.func = &psb_ttm_backend; ++ psb_be->base.dev = dev; + -+ return 0; /* Silence gcc warning */ ++ return &psb_be->base; +} + -+ -+/** -+ * Return the pipe currently connected to the panel fitter, -+ * or -1 if the panel fitter is not present or not in use -+ */ -+static int intel_panel_fitter_pipe (struct drm_device *dev) ++int psb_tbe_size(struct drm_device *dev, unsigned long num_pages) +{ -+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; -+ u32 pfit_control; -+ -+ /* i830 doesn't have a panel fitter */ -+ if (IS_I830(dev)) -+ return -1; -+ -+ pfit_control = I915_READ(PFIT_CONTROL); ++ /* ++ * Return the size of the structures themselves and the ++ * estimated size of the pagedir and pagetable entries. ++ */ + -+ /* See if the panel fitter is in use */ -+ if ((pfit_control & PFIT_ENABLE) == 0) -+ return -1; -+ -+ /* 965 can place panel fitter on either pipe */ -+ if (IS_I965G(dev)) -+ return (pfit_control >> 29) & 0x3; -+ -+ /* older chips can only use pipe 1 */ -+ return 1; ++ return drm_size_align(sizeof(struct drm_psb_ttm_backend)) + ++ 8*num_pages; +} +Index: linux-2.6.28/drivers/gpu/drm/psb/psb_drm.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.28/drivers/gpu/drm/psb/psb_drm.h 2009-02-12 09:14:41.000000000 +0000 +@@ -0,0 +1,370 @@ ++/************************************************************************** ++ * Copyright (c) 2007, Intel Corporation. ++ * All Rights Reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to ++ * develop this driver. ++ * ++ **************************************************************************/ ++/* ++ */ + -+#define WA_NO_FB_GARBAGE_DISPLAY -+#ifdef WA_NO_FB_GARBAGE_DISPLAY -+static u32 fp_reg_value[2]; -+static u32 dpll_reg_value[2]; -+static u32 dpll_md_reg_value[2]; -+static u32 dspcntr_reg_value[2]; -+static u32 pipeconf_reg_value[2]; -+static u32 htot_reg_value[2]; -+static u32 hblank_reg_value[2]; -+static u32 hsync_reg_value[2]; -+static u32 vtot_reg_value[2]; -+static u32 vblank_reg_value[2]; -+static u32 vsync_reg_value[2]; -+static u32 dspsize_reg_value[2]; -+static u32 dspstride_reg_value[2]; -+static u32 dsppos_reg_value[2]; -+static u32 pipesrc_reg_value[2]; ++#ifndef _PSB_DRM_H_ ++#define _PSB_DRM_H_ + -+static u32 dspbase_value[2]; ++#if defined(__linux__) && !defined(__KERNEL__) ++#include ++#endif + -+static u32 lvds_reg_value[2]; -+static u32 vgacntrl_reg_value[2]; -+static u32 pfit_control_reg_value[2]; ++/* ++ * Intel Poulsbo driver package version. ++ * ++ */ ++/* #define PSB_PACKAGE_VERSION "ED"__DATE__*/ ++#define PSB_PACKAGE_VERSION "2.1.0.32L.0019" + -+#if 0 -+void intel_crtc_mode_restore(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ int fp_reg = (pipe == 0) ? FPA0 : FPB0; -+ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -+ int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; -+ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -+ int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; -+ int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; -+ int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; -+ int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; -+ int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; -+ int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; -+ int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; -+ int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; -+ int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; -+ int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; -+ int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); ++#define DRM_PSB_SAREA_MAJOR 0 ++#define DRM_PSB_SAREA_MINOR 1 ++#define PSB_FIXED_SHIFT 16 + -+ bool ok, is_sdvo = false, is_dvo = false; -+ bool is_crt = false, is_lvds = false, is_tv = false; -+ struct drm_mode_config *mode_config = &dev->mode_config; -+ struct drm_connector *output; ++/* ++ * Public memory types. ++ */ + -+ list_for_each_entry(output, &mode_config->connector_list, head) { -+ struct intel_output *intel_output = to_intel_output(crtc); ++#define DRM_PSB_MEM_MMU DRM_BO_MEM_PRIV1 ++#define DRM_PSB_FLAG_MEM_MMU DRM_BO_FLAG_MEM_PRIV1 ++#define DRM_PSB_MEM_PDS DRM_BO_MEM_PRIV2 ++#define DRM_PSB_FLAG_MEM_PDS DRM_BO_FLAG_MEM_PRIV2 ++#define DRM_PSB_MEM_APER DRM_BO_MEM_PRIV3 ++#define DRM_PSB_FLAG_MEM_APER DRM_BO_FLAG_MEM_PRIV3 ++#define DRM_PSB_MEM_RASTGEOM DRM_BO_MEM_PRIV4 ++#define DRM_PSB_FLAG_MEM_RASTGEOM DRM_BO_FLAG_MEM_PRIV4 ++#define PSB_MEM_RASTGEOM_START 0x30000000 + -+ if (output->crtc != crtc) -+ continue; ++typedef int32_t psb_fixed; ++typedef uint32_t psb_ufixed; + -+ switch (intel_output->type) { -+ case INTEL_OUTPUT_LVDS: -+ is_lvds = TRUE; -+ break; -+ case INTEL_OUTPUT_SDVO: -+ is_sdvo = TRUE; -+ break; -+ case INTEL_OUTPUT_DVO: -+ is_dvo = TRUE; -+ break; -+ case INTEL_OUTPUT_TVOUT: -+ is_tv = TRUE; -+ break; -+ case INTEL_OUTPUT_ANALOG: -+ is_crt = TRUE; -+ break; -+ } -+ if(is_lvds && ((lvds_reg_value[pipe] & LVDS_PORT_EN) == 0)) -+ { -+ printk("%s: is_lvds but not the boot display, so return\n", -+ __FUNCTION__); -+ return; -+ } -+ output->funcs->prepare(output); -+ } ++static inline psb_fixed psb_int_to_fixed(int a) ++{ ++ return a * (1 << PSB_FIXED_SHIFT); ++} + -+ intel_crtc_prepare(crtc); -+ /* Disable the panel fitter if it was on our pipe */ -+ if (intel_panel_fitter_pipe(dev) == pipe) -+ I915_WRITE(PFIT_CONTROL, 0); ++static inline psb_ufixed psb_unsigned_to_ufixed(unsigned int a) ++{ ++ return a << PSB_FIXED_SHIFT; ++} + -+ if (dpll_reg_value[pipe] & DPLL_VCO_ENABLE) { -+ I915_WRITE(fp_reg, fp_reg_value[pipe]); -+ I915_WRITE(dpll_reg, dpll_reg_value[pipe]& ~DPLL_VCO_ENABLE); -+ I915_READ(dpll_reg); -+ udelay(150); -+ } ++/*Status of the command sent to the gfx device.*/ ++typedef enum { ++ DRM_CMD_SUCCESS, ++ DRM_CMD_FAILED, ++ DRM_CMD_HANG ++} drm_cmd_status_t; + -+ /* -+ if(is_lvds) -+ I915_WRITE(LVDS, lvds_reg_value[pipe]); -+ */ -+ if (is_lvds) { -+ I915_WRITE(LVDS, lvds_reg_value[pipe]); -+ I915_READ(LVDS); -+ } ++struct drm_psb_scanout { ++ uint32_t buffer_id; /* DRM buffer object ID */ ++ uint32_t rotation; /* Rotation as in RR_rotation definitions */ ++ uint32_t stride; /* Buffer stride in bytes */ ++ uint32_t depth; /* Buffer depth in bits (NOT) bpp */ ++ uint32_t width; /* Buffer width in pixels */ ++ uint32_t height; /* Buffer height in lines */ ++ psb_fixed transform[3][3]; /* Buffer composite transform */ ++ /* (scaling, rot, reflect) */ ++}; + -+ I915_WRITE(fp_reg, fp_reg_value[pipe]); -+ I915_WRITE(dpll_reg, dpll_reg_value[pipe]); -+ I915_READ(dpll_reg); -+ udelay(150); -+ //I915_WRITE(dpll_md_reg, dpll_md_reg_value[pipe]); -+ I915_WRITE(dpll_reg, dpll_reg_value[pipe]); -+ I915_READ(dpll_reg); -+ udelay(150); -+ I915_WRITE(htot_reg, htot_reg_value[pipe]); -+ I915_WRITE(hblank_reg, hblank_reg_value[pipe]); -+ I915_WRITE(hsync_reg, hsync_reg_value[pipe]); -+ I915_WRITE(vtot_reg, vtot_reg_value[pipe]); -+ I915_WRITE(vblank_reg, vblank_reg_value[pipe]); -+ I915_WRITE(vsync_reg, vsync_reg_value[pipe]); -+ I915_WRITE(dspstride_reg, dspstride_reg_value[pipe]); -+ I915_WRITE(dspsize_reg, dspsize_reg_value[pipe]); -+ I915_WRITE(dsppos_reg, dsppos_reg_value[pipe]); -+ I915_WRITE(pipesrc_reg, pipesrc_reg_value[pipe]); -+ I915_WRITE(pipeconf_reg, pipeconf_reg_value[pipe]); -+ I915_READ(pipeconf_reg); -+ intel_wait_for_vblank(dev); -+ I915_WRITE(dspcntr_reg, dspcntr_reg_value[pipe]); -+ I915_WRITE(dspbase, dspbase_value[pipe]); -+ I915_READ(dspbase); -+ I915_WRITE(VGACNTRL, vgacntrl_reg_value[pipe]); -+ intel_wait_for_vblank(dev); -+ I915_WRITE(PFIT_CONTROL, pfit_control_reg_value[pipe]); ++#define DRM_PSB_SAREA_OWNERS 16 ++#define DRM_PSB_SAREA_OWNER_2D 0 ++#define DRM_PSB_SAREA_OWNER_3D 1 + -+ intel_crtc_commit(crtc); -+ list_for_each_entry(output, &mode_config->connector_list, head) { -+ if (output->crtc != crtc) -+ continue; ++#define DRM_PSB_SAREA_SCANOUTS 3 + -+ output->funcs->commit(output); -+ //output->funcs->dpms(output, DRM_MODE_DPMS_OFF); -+ //printk("turn off the display first\n"); -+ } -+ return; -+} ++struct drm_psb_sarea { ++ /* Track changes of this data structure */ + -+void intel_crtc_mode_save(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ int fp_reg = (pipe == 0) ? FPA0 : FPB0; -+ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -+ int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; -+ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -+ int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; -+ int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; -+ int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; -+ int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; -+ int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; -+ int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; -+ int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; -+ int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; -+ int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; -+ int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; -+ int dspbase = (pipe == 0 ? DSPAADDR : DSPBADDR); -+ bool ok, is_sdvo = false, is_dvo = false; -+ bool is_crt = false, is_lvds = false, is_tv = false; -+ struct drm_mode_config *mode_config = &dev->mode_config; -+ struct drm_connector *output; ++ uint32_t major; ++ uint32_t minor; + -+ list_for_each_entry(output, &mode_config->connector_list, head) { -+ struct intel_output *intel_output = to_intel_output(crtc); ++ /* Last context to touch part of hw */ ++ uint32_t ctx_owners[DRM_PSB_SAREA_OWNERS]; + -+ if (output->crtc != crtc) -+ continue; -+ -+ switch (intel_output->type) { -+ case INTEL_OUTPUT_LVDS: -+ is_lvds = TRUE; -+ break; -+ case INTEL_OUTPUT_SDVO: -+ is_sdvo = TRUE; -+ break; -+ case INTEL_OUTPUT_DVO: -+ is_dvo = TRUE; -+ break; -+ case INTEL_OUTPUT_TVOUT: -+ is_tv = TRUE; -+ break; -+ case INTEL_OUTPUT_ANALOG: -+ is_crt = TRUE; -+ break; -+ } -+ } -+ -+ fp_reg_value[pipe] = I915_READ(fp_reg); -+ dpll_reg_value[pipe] = I915_READ(dpll_reg); -+ dpll_md_reg_value[pipe] = I915_READ(dpll_md_reg); -+ dspcntr_reg_value[pipe] = I915_READ(dspcntr_reg); -+ pipeconf_reg_value[pipe] = I915_READ(pipeconf_reg); -+ htot_reg_value[pipe] = I915_READ(htot_reg); -+ hblank_reg_value[pipe] = I915_READ(hblank_reg); -+ hsync_reg_value[pipe] = I915_READ(hsync_reg); -+ vtot_reg_value[pipe] = I915_READ(vtot_reg); -+ vblank_reg_value[pipe] = I915_READ(vblank_reg); -+ vsync_reg_value[pipe] = I915_READ(vsync_reg); -+ dspsize_reg_value[pipe] = I915_READ(dspsize_reg); -+ dspstride_reg_value[pipe] = I915_READ(dspstride_reg); -+ dsppos_reg_value[pipe] = I915_READ(dsppos_reg); -+ pipesrc_reg_value[pipe] = I915_READ(pipesrc_reg); -+ dspbase_value[pipe] = I915_READ(dspbase); -+ if(is_lvds) -+ lvds_reg_value[pipe] = I915_READ(LVDS); -+ vgacntrl_reg_value[pipe] = I915_READ(VGACNTRL); -+ pfit_control_reg_value[pipe] = I915_READ(PFIT_CONTROL); -+} -+#endif -+#endif -+static void intel_crtc_mode_set(struct drm_crtc *crtc, -+ struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode, -+ int x, int y, -+ struct drm_framebuffer *old_fb) -+{ -+ struct drm_device *dev = crtc->dev; -+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int pipe = intel_crtc->pipe; -+ int fp_reg = (pipe == 0) ? FPA0 : FPB0; -+ int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -+ int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; -+ int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -+ int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; -+ int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; -+ int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; -+ int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; -+ int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; -+ int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; -+ int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; -+ int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; -+ int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; -+ int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; -+ int refclk; -+ intel_clock_t clock; -+ u32 dpll = 0, fp = 0, dspcntr, pipeconf; -+ bool ok, is_sdvo = false, is_dvo = false; -+ bool is_crt = false, is_lvds = false, is_tv = false; -+ struct drm_mode_config *mode_config = &dev->mode_config; -+ struct drm_connector *connector; -+ -+ if (!crtc->fb) { -+ DRM_ERROR("Can't set mode without attached fb\n"); -+ return; -+ } ++ /* Definition of front- and rotated buffers */ ++ uint32_t num_scanouts; ++ struct drm_psb_scanout scanouts[DRM_PSB_SAREA_SCANOUTS]; + -+ list_for_each_entry(connector, &mode_config->connector_list, head) { -+ struct intel_output *intel_output = to_intel_output(connector); ++ int pipeA_x; ++ int pipeA_y; ++ int pipeA_w; ++ int pipeA_h; ++ int pipeB_x; ++ int pipeB_y; ++ int pipeB_w; ++ int pipeB_h; ++ uint32_t msvdx_state; ++ uint32_t msvdx_context; ++}; + -+ if (!connector->encoder || connector->encoder->crtc != crtc) -+ continue; ++#define PSB_RELOC_MAGIC 0x67676767 ++#define PSB_RELOC_SHIFT_MASK 0x0000FFFF ++#define PSB_RELOC_SHIFT_SHIFT 0 ++#define PSB_RELOC_ALSHIFT_MASK 0xFFFF0000 ++#define PSB_RELOC_ALSHIFT_SHIFT 16 + -+ switch (intel_output->type) { -+ case INTEL_OUTPUT_LVDS: -+ is_lvds = true; -+ break; -+ case INTEL_OUTPUT_SDVO: -+ case INTEL_OUTPUT_HDMI: -+ is_sdvo = true; -+ break; -+ case INTEL_OUTPUT_DVO: -+ is_dvo = true; -+ break; -+ case INTEL_OUTPUT_TVOUT: -+ is_tv = true; -+ break; -+ case INTEL_OUTPUT_ANALOG: -+ is_crt = true; -+ break; -+ } -+ } ++#define PSB_RELOC_OP_OFFSET 0 /* Offset of the indicated ++ * buffer ++ */ ++#define PSB_RELOC_OP_2D_OFFSET 1 /* Offset of the indicated ++ * buffer, relative to 2D ++ * base address ++ */ ++#define PSB_RELOC_OP_PDS_OFFSET 2 /* Offset of the indicated buffer, ++ * relative to PDS base address ++ */ ++#define PSB_RELOC_OP_STRIDE 3 /* Stride of the indicated ++ * buffer (for tiling) ++ */ ++#define PSB_RELOC_OP_USE_OFFSET 4 /* Offset of USE buffer ++ * relative to base reg ++ */ ++#define PSB_RELOC_OP_USE_REG 5 /* Base reg of USE buffer */ + -+ if (IS_I9XX(dev)) { -+ refclk = 96000; -+ } else { -+ refclk = 48000; -+ } ++struct drm_psb_reloc { ++ uint32_t reloc_op; ++ uint32_t where; /* offset in destination buffer */ ++ uint32_t buffer; /* Buffer reloc applies to */ ++ uint32_t mask; /* Destination format: */ ++ uint32_t shift; /* Destination format: */ ++ uint32_t pre_add; /* Destination format: */ ++ uint32_t background; /* Destination add */ ++ uint32_t dst_buffer; /* Destination buffer. Index into buffer_list */ ++ uint32_t arg0; /* Reloc-op dependant */ ++ uint32_t arg1; ++}; + -+ ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); -+ if (!ok) { -+ DRM_ERROR("Couldn't find PLL settings for mode!\n"); -+ return; -+ } ++#define PSB_BO_FLAG_TA (1ULL << 48) ++#define PSB_BO_FLAG_SCENE (1ULL << 49) ++#define PSB_BO_FLAG_FEEDBACK (1ULL << 50) ++#define PSB_BO_FLAG_USSE (1ULL << 51) + -+ fp = clock.n << 16 | clock.m1 << 8 | clock.m2; ++#define PSB_ENGINE_2D 0 ++#define PSB_ENGINE_VIDEO 1 ++#define PSB_ENGINE_RASTERIZER 2 ++#define PSB_ENGINE_TA 3 ++#define PSB_ENGINE_HPRAST 4 + -+ dpll = DPLL_VGA_MODE_DIS; -+ if (IS_I9XX(dev)) { -+ if (is_lvds) { -+ dpll |= DPLLB_MODE_LVDS; -+ if (IS_POULSBO(dev)) -+ dpll |= DPLL_DVO_HIGH_SPEED; -+ } else -+ dpll |= DPLLB_MODE_DAC_SERIAL; -+ if (is_sdvo) { -+ dpll |= DPLL_DVO_HIGH_SPEED; -+ if (IS_I945G(dev) || IS_I945GM(dev) || IS_POULSBO(dev)) { -+ int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; -+ dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; -+ } -+ } ++/* ++ * For this fence class we have a couple of ++ * fence types. ++ */ + -+ /* compute bitmask from p1 value */ -+ dpll |= (1 << (clock.p1 - 1)) << 16; -+ switch (clock.p2) { -+ case 5: -+ dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; -+ break; -+ case 7: -+ dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; -+ break; -+ case 10: -+ dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; -+ break; -+ case 14: -+ dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; -+ break; -+ } -+ if (IS_I965G(dev)) -+ dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); -+ } else { -+ if (is_lvds) { -+ dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; -+ } else { -+ if (clock.p1 == 2) -+ dpll |= PLL_P1_DIVIDE_BY_TWO; -+ else -+ dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; -+ if (clock.p2 == 4) -+ dpll |= PLL_P2_DIVIDE_BY_4; -+ } -+ } ++#define _PSB_FENCE_EXE_SHIFT 0 ++#define _PSB_FENCE_TA_DONE_SHIFT 1 ++#define _PSB_FENCE_RASTER_DONE_SHIFT 2 ++#define _PSB_FENCE_SCENE_DONE_SHIFT 3 ++#define _PSB_FENCE_FEEDBACK_SHIFT 4 + -+ if (is_tv) { -+ /* XXX: just matching BIOS for now */ -+/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ -+ dpll |= 3; -+ } -+ else -+ dpll |= PLL_REF_INPUT_DREFCLK; ++#define _PSB_ENGINE_TA_FENCE_TYPES 5 ++#define _PSB_FENCE_TYPE_TA_DONE (1 << _PSB_FENCE_TA_DONE_SHIFT) ++#define _PSB_FENCE_TYPE_RASTER_DONE (1 << _PSB_FENCE_RASTER_DONE_SHIFT) ++#define _PSB_FENCE_TYPE_SCENE_DONE (1 << _PSB_FENCE_SCENE_DONE_SHIFT) ++#define _PSB_FENCE_TYPE_FEEDBACK (1 << _PSB_FENCE_FEEDBACK_SHIFT) + -+ /* setup pipeconf */ -+ pipeconf = I915_READ(pipeconf_reg); ++#define PSB_ENGINE_HPRAST 4 ++#define PSB_NUM_ENGINES 5 + -+ /* Set up the display plane register */ -+ dspcntr = DISPPLANE_GAMMA_ENABLE; ++#define PSB_TA_FLAG_FIRSTPASS (1 << 0) ++#define PSB_TA_FLAG_LASTPASS (1 << 1) + -+ switch (crtc->fb->bits_per_pixel) { -+ case 8: -+ dspcntr |= DISPPLANE_8BPP; -+ break; -+ case 16: -+ if (crtc->fb->depth == 15) -+ dspcntr |= DISPPLANE_15_16BPP; -+ else -+ dspcntr |= DISPPLANE_16BPP; -+ break; -+ case 32: -+ dspcntr |= DISPPLANE_32BPP_NO_ALPHA; -+ break; -+ default: -+ DRM_ERROR("Unknown color depth\n"); -+ return; -+ } ++#define PSB_FEEDBACK_OP_VISTEST (1 << 0) + ++struct drm_psb_scene { ++ int handle_valid; ++ uint32_t handle; ++ uint32_t w; ++ uint32_t h; ++ uint32_t num_buffers; ++}; + -+ if (pipe == 0) -+ dspcntr |= DISPPLANE_SEL_PIPE_A; -+ else -+ dspcntr |= DISPPLANE_SEL_PIPE_B; ++struct drm_psb_hw_info ++{ ++ uint32_t rev_id; ++ uint32_t caps; ++}; + -+ if (pipe == 0 && !IS_I965G(dev)) { -+ /* Enable pixel doubling when the dot clock is > 90% of the (display) -+ * core speed. -+ * -+ * XXX: No double-wide on 915GM pipe B. Is that the only reason for the -+ * pipe == 0 check? -+ */ -+ if (mode->clock > intel_get_core_clock_speed(dev) * 9 / 10) -+ pipeconf |= PIPEACONF_DOUBLE_WIDE; -+ else -+ pipeconf &= ~PIPEACONF_DOUBLE_WIDE; -+ } ++typedef struct drm_psb_cmdbuf_arg { ++ uint64_t buffer_list; /* List of buffers to validate */ ++ uint64_t clip_rects; /* See i915 counterpart */ ++ uint64_t scene_arg; ++ uint64_t fence_arg; + -+ dspcntr |= DISPLAY_PLANE_ENABLE; -+ pipeconf |= PIPEACONF_ENABLE; -+ dpll |= DPLL_VCO_ENABLE; ++ uint32_t ta_flags; + ++ uint32_t ta_handle; /* TA reg-value pairs */ ++ uint32_t ta_offset; ++ uint32_t ta_size; + -+ /* Disable the panel fitter if it was on our pipe */ -+ if (intel_panel_fitter_pipe(dev) == pipe) -+ I915_WRITE(PFIT_CONTROL, 0); ++ uint32_t oom_handle; ++ uint32_t oom_offset; ++ uint32_t oom_size; + -+ DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); -+ drm_mode_debug_printmodeline(mode); ++ uint32_t cmdbuf_handle; /* 2D Command buffer object or, */ ++ uint32_t cmdbuf_offset; /* rasterizer reg-value pairs */ ++ uint32_t cmdbuf_size; + ++ uint32_t reloc_handle; /* Reloc buffer object */ ++ uint32_t reloc_offset; ++ uint32_t num_relocs; + -+ if (dpll & DPLL_VCO_ENABLE) { -+ I915_WRITE(fp_reg, fp); -+ I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); -+ I915_READ(dpll_reg); -+ udelay(150); -+ } ++ int32_t damage; /* Damage front buffer with cliprects */ ++ /* Not implemented yet */ ++ uint32_t fence_flags; ++ uint32_t engine; + -+ /* The LVDS pin pair needs to be on before the DPLLs are enabled. -+ * This is an exception to the general rule that mode_set doesn't turn -+ * things on. ++ /* ++ * Feedback; + */ -+ if (is_lvds) { -+ u32 lvds = I915_READ(LVDS); -+ -+ lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; -+ /* Set the B0-B3 data pairs corresponding to whether we're going to -+ * set the DPLLs for dual-channel mode or not. -+ */ -+ if (clock.p2 == 7) -+ lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; -+ else -+ lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); -+ -+ /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) -+ * appropriately here, but we need to look more thoroughly into how -+ * panels behave in the two modes. -+ */ + -+ I915_WRITE(LVDS, lvds); -+ I915_READ(LVDS); -+ } -+ -+ I915_WRITE(fp_reg, fp); -+ I915_WRITE(dpll_reg, dpll); -+ I915_READ(dpll_reg); -+ /* Wait for the clocks to stabilize. */ -+ udelay(150); -+ -+ if (IS_I965G(dev)) { -+ int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; -+ I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | -+ ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); -+ } else { -+ /* write it again -- the BIOS does, after all */ -+ I915_WRITE(dpll_reg, dpll); -+ } -+ I915_READ(dpll_reg); -+ /* Wait for the clocks to stabilize. */ -+ udelay(150); -+ -+ I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | -+ ((adjusted_mode->crtc_htotal - 1) << 16)); -+ I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | -+ ((adjusted_mode->crtc_hblank_end - 1) << 16)); -+ I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | -+ ((adjusted_mode->crtc_hsync_end - 1) << 16)); -+ I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | -+ ((adjusted_mode->crtc_vtotal - 1) << 16)); -+ I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | -+ ((adjusted_mode->crtc_vblank_end - 1) << 16)); -+ I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | -+ ((adjusted_mode->crtc_vsync_end - 1) << 16)); -+ I915_WRITE(dspstride_reg, crtc->fb->pitch); -+ /* pipesrc and dspsize control the size that is scaled from, which should -+ * always be the user's requested size. -+ */ -+ I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); -+ I915_WRITE(dsppos_reg, 0); -+ I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); -+ I915_WRITE(pipeconf_reg, pipeconf); -+ I915_READ(pipeconf_reg); -+ -+ intel_wait_for_vblank(dev); -+ -+ I915_WRITE(dspcntr_reg, dspcntr); ++ uint32_t feedback_ops; ++ uint32_t feedback_handle; ++ uint32_t feedback_offset; ++ uint32_t feedback_breakpoints; ++ uint32_t feedback_size; ++} drm_psb_cmdbuf_arg_t; + -+ /* Flush the plane changes */ -+ intel_pipe_set_base(crtc, x, y, old_fb); ++struct drm_psb_xhw_init_arg { ++ uint32_t operation; ++ uint32_t buffer_handle; ++}; + -+ intel_wait_for_vblank(dev); -+} ++/* ++ * Feedback components: ++ */ + -+/** Loads the palette/gamma unit for the CRTC with the prepared values */ -+void intel_crtc_load_lut(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B; -+ int i; ++/* ++ * Vistest component. The number of these in the feedback buffer ++ * equals the number of vistest breakpoints + 1. ++ * This is currently the only feedback component. ++ */ + -+ /* The clocks have to be on to load the palette. */ -+ if (!crtc->enabled) -+ return; ++struct drm_psb_vistest { ++ uint32_t vt[8]; ++}; + -+ for (i = 0; i < 256; i++) { -+ I915_WRITE(palreg + 4 * i, -+ (intel_crtc->lut_r[i] << 16) | -+ (intel_crtc->lut_g[i] << 8) | -+ intel_crtc->lut_b[i]); -+ } -+} ++#define PSB_HW_COOKIE_SIZE 16 ++#define PSB_HW_FEEDBACK_SIZE 8 ++#define PSB_HW_OOM_CMD_SIZE 6 + -+static int intel_crtc_cursor_set(struct drm_crtc *crtc, -+ struct drm_file *file_priv, -+ uint32_t handle, -+ uint32_t width, uint32_t height) -+{ -+ struct drm_device *dev = crtc->dev; -+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; -+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -+ struct drm_gem_object *bo; -+ struct drm_i915_gem_object *obj_priv; -+ int pipe = intel_crtc->pipe; -+ uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; -+ uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; -+ uint32_t temp; -+ size_t addr; ++struct drm_psb_xhw_arg { ++ uint32_t op; + int ret; ++ uint32_t irq_op; ++ uint32_t issue_irq; ++ uint32_t cookie[PSB_HW_COOKIE_SIZE]; ++ union { ++ struct { ++ uint32_t w; ++ uint32_t h; ++ uint32_t size; ++ uint32_t clear_p_start; ++ uint32_t clear_num_pages; ++ } si; ++ struct { ++ uint3