diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-06-23 20:20:51 +0000 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-06-23 20:20:51 +0000 |
commit | 74d83b7eedab14e4b963a2220ff76f98fa6d4cb8 (patch) | |
tree | ff4b10ebd9cf1a057c4b1a703732858a539faff7 /drivers/staging/gma500 | |
parent | [SCSI] target: Convert TASK_ATTR to scsi_tcq.h definitions (diff) | |
parent | Linux 3.0-rc4 (diff) | |
download | linux-dev-74d83b7eedab14e4b963a2220ff76f98fa6d4cb8.tar.xz linux-dev-74d83b7eedab14e4b963a2220ff76f98fa6d4cb8.zip |
Merge tag 'v3.0-rc4' of /pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus
Diffstat (limited to 'drivers/staging/gma500')
39 files changed, 2996 insertions, 6861 deletions
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile index a52ba48be518..db73ec6d8128 100644 --- a/drivers/staging/gma500/Makefile +++ b/drivers/staging/gma500/Makefile @@ -5,6 +5,7 @@ ccflags-y += -Iinclude/drm psb_gfx-y += psb_bl.o \ psb_drv.o \ + psb_gem.o \ psb_fb.o \ psb_2d.o \ psb_gtt.o \ @@ -15,17 +16,11 @@ psb_gfx-y += psb_bl.o \ psb_intel_lvds.o \ psb_intel_modes.o \ psb_intel_sdvo.o \ - psb_reset.o \ - psb_sgx.o \ - psb_pvr_glue.o \ - psb_buffer.o \ - psb_fence.o \ + psb_lid.o \ psb_mmu.o \ - psb_ttm_glue.o \ - psb_ttm_fence.o \ - psb_ttm_fence_user.o \ - psb_ttm_placement_user.o \ psb_powermgmt.o \ - psb_irq.o + psb_irq.o \ + mrst_crtc.o \ + mrst_lvds.o obj-$(CONFIG_DRM_PSB) += psb_gfx.o diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h new file mode 100644 index 000000000000..5e4aaeb3711b --- /dev/null +++ b/drivers/staging/gma500/mrst.h @@ -0,0 +1,217 @@ +/************************************************************************** + * Copyright (c) 2007-2011, 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. + * + **************************************************************************/ + +/* MID device specific descriptors */ + +struct mrst_vbt { + s8 signature[4]; /*4 bytes,"$GCT" */ + u8 revision; + u8 size; + u8 checksum; + void *mrst_gct; +} __attribute__ ((packed)); + +struct mrst_timing_info { + u16 pixel_clock; + u8 hactive_lo; + u8 hblank_lo; + u8 hblank_hi:4; + u8 hactive_hi:4; + u8 vactive_lo; + u8 vblank_lo; + u8 vblank_hi:4; + u8 vactive_hi:4; + u8 hsync_offset_lo; + u8 hsync_pulse_width_lo; + u8 vsync_pulse_width_lo:4; + u8 vsync_offset_lo:4; + u8 vsync_pulse_width_hi:2; + u8 vsync_offset_hi:2; + u8 hsync_pulse_width_hi:2; + u8 hsync_offset_hi:2; + u8 width_mm_lo; + u8 height_mm_lo; + u8 height_mm_hi:4; + u8 width_mm_hi:4; + u8 hborder; + u8 vborder; + u8 unknown0:1; + u8 hsync_positive:1; + u8 vsync_positive:1; + u8 separate_sync:2; + u8 stereo:1; + u8 unknown6:1; + u8 interlaced:1; +} __attribute__((packed)); + +struct gct_r10_timing_info { + u16 pixel_clock; + u32 hactive_lo:8; + u32 hactive_hi:4; + u32 hblank_lo:8; + u32 hblank_hi:4; + u32 hsync_offset_lo:8; + u16 hsync_offset_hi:2; + u16 hsync_pulse_width_lo:8; + u16 hsync_pulse_width_hi:2; + u16 hsync_positive:1; + u16 rsvd_1:3; + u8 vactive_lo:8; + u16 vactive_hi:4; + u16 vblank_lo:8; + u16 vblank_hi:4; + u16 vsync_offset_lo:4; + u16 vsync_offset_hi:2; + u16 vsync_pulse_width_lo:4; + u16 vsync_pulse_width_hi:2; + u16 vsync_positive:1; + u16 rsvd_2:3; +} __attribute__((packed)); + +struct mrst_panel_descriptor_v1 { + u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ + /* 0x61190 if MIPI */ + u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ + u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ + u32 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */ + /* Register 0x61210 */ + struct mrst_timing_info DTD;/*18 bytes, Standard definition */ + u16 Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */ + /* Bit 0, Frequency, 15 bits,0 - 32767Hz */ + /* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */ + u16 Panel_MIPI_Display_Descriptor; + /*16 bits, Defined as follows: */ + /* if MIPI, 0x0000 if LVDS */ + /* Bit 0, Type, 2 bits, */ + /* 0: Type-1, */ + /* 1: Type-2, */ + /* 2: Type-3, */ + /* 3: Type-4 */ + /* Bit 2, Pixel Format, 4 bits */ + /* Bit0: 16bpp (not supported in LNC), */ + /* Bit1: 18bpp loosely packed, */ + /* Bit2: 18bpp packed, */ + /* Bit3: 24bpp */ + /* Bit 6, Reserved, 2 bits, 00b */ + /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ + /* Bit 14, Reserved, 2 bits, 00b */ +} __attribute__ ((packed)); + +struct mrst_panel_descriptor_v2 { + u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ + /* 0x61190 if MIPI */ + u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ + u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ + u8 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */ + /* Register 0x61210 */ + struct mrst_timing_info DTD;/*18 bytes, Standard definition */ + u16 Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/ + /*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/ + u8 Panel_Initial_Brightness;/* [7:0] 0 - 100% */ + /*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/ + u16 Panel_MIPI_Display_Descriptor; + /*16 bits, Defined as follows: */ + /* if MIPI, 0x0000 if LVDS */ + /* Bit 0, Type, 2 bits, */ + /* 0: Type-1, */ + /* 1: Type-2, */ + /* 2: Type-3, */ + /* 3: Type-4 */ + /* Bit 2, Pixel Format, 4 bits */ + /* Bit0: 16bpp (not supported in LNC), */ + /* Bit1: 18bpp loosely packed, */ + /* Bit2: 18bpp packed, */ + /* Bit3: 24bpp */ + /* Bit 6, Reserved, 2 bits, 00b */ + /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ + /* Bit 14, Reserved, 2 bits, 00b */ +} __attribute__ ((packed)); + +union mrst_panel_rx { + struct{ + u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/ + /* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */ + u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */ + /*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/ + u16 SupportedVideoTransferMode:2; /*0: Non-burst only */ + /* 1: Burst and non-burst */ + /* 2/3: Reserved */ + u16 HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/ + u16 DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/ + u16 ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/ + u16 BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */ + u16 Rsvd:5;/*5 bits,00000b */ + } panelrx; + u16 panel_receiver; +} __attribute__ ((packed)); + +struct mrst_gct_v1 { + union{ /*8 bits,Defined as follows: */ + struct { + u8 PanelType:4; /*4 bits, Bit field for panels*/ + /* 0 - 3: 0 = LVDS, 1 = MIPI*/ + /*2 bits,Specifies which of the*/ + u8 BootPanelIndex:2; + /* 4 panels to use by default*/ + u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ + /* the 4 MIPI DSI receivers to use*/ + } PD; + u8 PanelDescriptor; + }; + struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/ + union mrst_panel_rx panelrx[4]; /* panel receivers*/ +} __attribute__ ((packed)); + +struct mrst_gct_v2 { + union{ /*8 bits,Defined as follows: */ + struct { + u8 PanelType:4; /*4 bits, Bit field for panels*/ + /* 0 - 3: 0 = LVDS, 1 = MIPI*/ + /*2 bits,Specifies which of the*/ + u8 BootPanelIndex:2; + /* 4 panels to use by default*/ + u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ + /* the 4 MIPI DSI receivers to use*/ + } PD; + u8 PanelDescriptor; + }; + struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/ + union mrst_panel_rx panelrx[4]; /* panel receivers*/ +} __attribute__ ((packed)); + +struct mrst_gct_data { + u8 bpi; /* boot panel index, number of panel used during boot */ + u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */ + struct mrst_timing_info DTD; /* timing info for the selected panel */ + u32 Panel_Port_Control; + u32 PP_On_Sequencing;/*1 dword,Register 0x61208,*/ + u32 PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/ + u32 PP_Cycle_Delay; + u16 Panel_Backlight_Inverter_Descriptor; + u16 Panel_MIPI_Display_Descriptor; +} __attribute__ ((packed)); + +#define MODE_SETTING_IN_CRTC 0x1 +#define MODE_SETTING_IN_ENCODER 0x2 +#define MODE_SETTING_ON_GOING 0x3 +#define MODE_SETTING_IN_DSR 0x4 +#define MODE_SETTING_ENCODER_DONE 0x8 +#define GCT_R10_HEADER_SIZE 16 +#define GCT_R10_DISPLAY_DESC_SIZE 28 + diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c new file mode 100644 index 000000000000..e4a0c033b5b2 --- /dev/null +++ b/drivers/staging/gma500/mrst_crtc.c @@ -0,0 +1,619 @@ +/* + * Copyright © 2009 Intel Corporation + * + * 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. + */ + +#include <linux/i2c.h> +#include <linux/pm_runtime.h> + +#include <drm/drmP.h> +#include "psb_fb.h" +#include "psb_drv.h" +#include "psb_intel_drv.h" +#include "psb_intel_reg.h" +#include "psb_intel_display.h" +#include "psb_powermgmt.h" + +struct psb_intel_range_t { + int min, max; +}; + +struct mrst_limit_t { + struct psb_intel_range_t dot, m, p1; +}; + +struct mrst_clock_t { + /* derived values */ + int dot; + int m; + int p1; +}; + +#define MRST_LIMIT_LVDS_100L 0 +#define MRST_LIMIT_LVDS_83 1 +#define MRST_LIMIT_LVDS_100 2 + +#define MRST_DOT_MIN 19750 +#define MRST_DOT_MAX 120000 +#define MRST_M_MIN_100L 20 +#define MRST_M_MIN_100 10 +#define MRST_M_MIN_83 12 +#define MRST_M_MAX_100L 34 +#define MRST_M_MAX_100 17 +#define MRST_M_MAX_83 20 +#define MRST_P1_MIN 2 +#define MRST_P1_MAX_0 7 +#define MRST_P1_MAX_1 8 + +static const struct mrst_limit_t mrst_limits[] = { + { /* MRST_LIMIT_LVDS_100L */ + .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, + .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L}, + .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, + }, + { /* MRST_LIMIT_LVDS_83L */ + .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, + .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83}, + .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0}, + }, + { /* MRST_LIMIT_LVDS_100 */ + .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, + .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100}, + .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, + }, +}; + +#define MRST_M_MIN 10 +static const u32 mrst_m_converts[] = { + 0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C, + 0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25, + 0x12, 0x09, 0x24, 0x32, 0x39, 0x1c, +}; + +static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc) +{ + const struct mrst_limit_t *limit = NULL; + struct drm_device *dev = crtc->dev; + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; + + if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) + || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) { + switch (dev_priv->core_freq) { + case 100: + limit = &mrst_limits[MRST_LIMIT_LVDS_100L]; + break; + case 166: + limit = &mrst_limits[MRST_LIMIT_LVDS_83]; + break; + case 200: + limit = &mrst_limits[MRST_LIMIT_LVDS_100]; + break; + } + } else { + limit = NULL; + PSB_DEBUG_ENTRY("mrst_limit Wrong display type.\n"); + } + + return limit; +} + +/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ +static void mrst_clock(int refclk, struct mrst_clock_t *clock) +{ + clock->dot = (refclk * clock->m) / (14 * clock->p1); +} + +void mrstPrintPll(char *prefix, struct mrst_clock_t *clock) +{ + PSB_DEBUG_ENTRY("%s: dotclock = %d, m = %d, p1 = %d.\n", + prefix, clock->dot, clock->m, clock->p1); +} + +/** + * Returns a set of divisors for the desired target clock with the given refclk, + * or FALSE. Divisor values are the actual divisors for + */ +static bool +mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk, + struct mrst_clock_t *best_clock) +{ + struct mrst_clock_t clock; + const struct mrst_limit_t *limit = mrst_limit(crtc); + int err = target; + + memset(best_clock, 0, sizeof(*best_clock)); + + for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { + for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; + clock.p1++) { + int this_err; + + mrst_clock(refclk, &clock); + + this_err = abs(clock.dot - target); + if (this_err < err) { + *best_clock = clock; + err = this_err; + } + } + } + DRM_DEBUG("mrstFindBestPLL err = %d.\n", err); + + return err != target; +} + +/** + * 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 mrst_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct drm_device *dev = crtc->dev; + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); + int pipe = psb_intel_crtc->pipe; + int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE; + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; + u32 temp; + bool enabled; + + PSB_DEBUG_ENTRY("mode = %d, pipe = %d\n", mode, pipe); + + if (!gma_power_begin(dev, true)) + return; + + /* 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 = REG_READ(dpll_reg); + if ((temp & DPLL_VCO_ENABLE) == 0) { + REG_WRITE(dpll_reg, temp); + REG_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); + REG_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); + REG_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + } + /* Enable the pipe */ + temp = REG_READ(pipeconf_reg); + if ((temp & PIPEACONF_ENABLE) == 0) + REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); + /* Enable the plane */ + temp = REG_READ(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) == 0) { + REG_WRITE(dspcntr_reg, + temp | DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); + } + + psb_intel_crtc_load_lut(crtc); + + /* Give the overlay scaler a chance to enable + if it's on this pipe */ + /* psb_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 */ + /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ + + /* Disable the VGA plane that we never use */ + REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); + /* Disable display plane */ + temp = REG_READ(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) != 0) { + REG_WRITE(dspcntr_reg, + temp & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); + REG_READ(dspbase_reg); + } + + /* Next, disable display pipes */ + temp = REG_READ(pipeconf_reg); + if ((temp & PIPEACONF_ENABLE) != 0) { + REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); + REG_READ(pipeconf_reg); + } + /* Wait for for the pipe disable to take effect. */ + psb_intel_wait_for_vblank(dev); + + temp = REG_READ(dpll_reg); + if ((temp & DPLL_VCO_ENABLE) != 0) { + REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); + REG_READ(dpll_reg); + } + + /* Wait for the clocks to turn off. */ + udelay(150); + break; + } + + enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; + + /*Set FIFO Watermarks*/ + REG_WRITE(DSPARB, 0x3FFF); + REG_WRITE(DSPFW1, 0x3F88080A); + REG_WRITE(DSPFW2, 0x0b060808); + REG_WRITE(DSPFW3, 0x0); + REG_WRITE(DSPFW4, 0x08030404); + REG_WRITE(DSPFW5, 0x04040404); + REG_WRITE(DSPFW6, 0x78); + REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000); + /* Must write Bit 14 of the Chicken Bit Register */ + + gma_power_end(dev); +} + +/** + * Return the pipe currently connected to the panel fitter, + * or -1 if the panel fitter is not present or not in use + */ +static int mrst_panel_fitter_pipe(struct drm_device *dev) +{ + u32 pfit_control; + + pfit_control = REG_READ(PFIT_CONTROL); + + /* See if the panel fitter is in use */ + if ((pfit_control & PFIT_ENABLE) == 0) + return -1; + return (pfit_control >> 29) & 3; +} + +static int mrst_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; + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; + int pipe = psb_intel_crtc->pipe; + int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0; + int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; + 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 pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; + int refclk = 0; + struct mrst_clock_t clock; + u32 dpll = 0, fp = 0, dspcntr, pipeconf; + bool ok, is_sdvo = false; + bool is_crt = false, is_lvds = false, is_tv = false; + bool is_mipi = false; + struct drm_mode_config *mode_config = &dev->mode_config; + struct psb_intel_output *psb_intel_output = NULL; + uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; + struct drm_encoder *encoder; + + PSB_DEBUG_ENTRY("pipe = 0x%x\n", pipe); + + if (!gma_power_begin(dev, true)) + return 0; + + memcpy(&psb_intel_crtc->saved_mode, + mode, + sizeof(struct drm_display_mode)); + memcpy(&psb_intel_crtc->saved_adjusted_mode, + adjusted_mode, + sizeof(struct drm_display_mode)); + + list_for_each_entry(encoder, &mode_config->encoder_list, head) { + + if (encoder->crtc != crtc) + continue; + + psb_intel_output = enc_to_psb_intel_output(encoder); + switch (psb_intel_output->type) { + case INTEL_OUTPUT_LVDS: + is_lvds = true; + break; + case INTEL_OUTPUT_SDVO: + is_sdvo = true; + break; + case INTEL_OUTPUT_TVOUT: + is_tv = true; + break; + case INTEL_OUTPUT_ANALOG: + is_crt = true; + break; + case INTEL_OUTPUT_MIPI: + is_mipi = true; + break; + } + } + + /* Disable the VGA plane that we never use */ + REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); + + /* Disable the panel fitter if it was on our pipe */ + if (mrst_panel_fitter_pipe(dev) == pipe) + REG_WRITE(PFIT_CONTROL, 0); + + REG_WRITE(pipesrc_reg, + ((mode->crtc_hdisplay - 1) << 16) | + (mode->crtc_vdisplay - 1)); + + if (psb_intel_output) + drm_connector_property_get_value(&psb_intel_output->base, + dev->mode_config.scaling_mode_property, &scalingType); + + if (scalingType == DRM_MODE_SCALE_NO_SCALE) { + /* Moorestown doesn't have register support for centering so + * we need to mess with the h/vblank and h/vsync start and + * ends to get centering */ + int offsetX = 0, offsetY = 0; + + offsetX = (adjusted_mode->crtc_hdisplay - + mode->crtc_hdisplay) / 2; + offsetY = (adjusted_mode->crtc_vdisplay - + mode->crtc_vdisplay) / 2; + + REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | + ((adjusted_mode->crtc_htotal - 1) << 16)); + REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | + ((adjusted_mode->crtc_vtotal - 1) << 16)); + REG_WRITE(hblank_reg, + (adjusted_mode->crtc_hblank_start - offsetX - 1) | + ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); + REG_WRITE(hsync_reg, + (adjusted_mode->crtc_hsync_start - offsetX - 1) | + ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); + REG_WRITE(vblank_reg, + (adjusted_mode->crtc_vblank_start - offsetY - 1) | + ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); + REG_WRITE(vsync_reg, + (adjusted_mode->crtc_vsync_start - offsetY - 1) | + ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); + } else { + REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | + ((adjusted_mode->crtc_htotal - 1) << 16)); + REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | + ((adjusted_mode->crtc_vtotal - 1) << 16)); + REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | + ((adjusted_mode->crtc_hblank_end - 1) << 16)); + REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | + ((adjusted_mode->crtc_hsync_end - 1) << 16)); + REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | + ((adjusted_mode->crtc_vblank_end - 1) << 16)); + REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | + ((adjusted_mode->crtc_vsync_end - 1) << 16)); + } + + /* Flush the plane changes */ + { + struct drm_crtc_helper_funcs *crtc_funcs = + crtc->helper_private; + crtc_funcs->mode_set_base(crtc, x, y, old_fb); + } + + /* setup pipeconf */ + pipeconf = REG_READ(pipeconf_reg); + + /* Set up the display plane register */ + dspcntr = REG_READ(dspcntr_reg); + dspcntr |= DISPPLANE_GAMMA_ENABLE; + + if (pipe == 0) + dspcntr |= DISPPLANE_SEL_PIPE_A; + else + dspcntr |= DISPPLANE_SEL_PIPE_B; + + dev_priv->dspcntr = dspcntr |= DISPLAY_PLANE_ENABLE; + dev_priv->pipeconf = pipeconf |= PIPEACONF_ENABLE; + + if (is_mipi) + goto mrst_crtc_mode_set_exit; + + refclk = dev_priv->core_freq * 1000; + + dpll = 0; /*BIT16 = 0 for 100MHz reference */ + + ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock); + + if (!ok) { + PSB_DEBUG_ENTRY( + "mrstFindBestPLL fail in mrst_crtc_mode_set.\n"); + } else { + PSB_DEBUG_ENTRY("mrst_crtc_mode_set pixel clock = %d," + "m = %x, p1 = %x.\n", clock.dot, clock.m, + clock.p1); + } + + fp = mrst_m_converts[(clock.m - MRST_M_MIN)] << 8; + + dpll |= DPLL_VGA_MODE_DIS; + + + dpll |= DPLL_VCO_ENABLE; + + if (is_lvds) + dpll |= DPLLA_MODE_LVDS; + else + dpll |= DPLLB_MODE_DAC_SERIAL; + + if (is_sdvo) { + int sdvo_pixel_multiply = + adjusted_mode->clock / mode->clock; + + dpll |= DPLL_DVO_HIGH_SPEED; + dpll |= + (sdvo_pixel_multiply - + 1) << SDVO_MULTIPLIER_SHIFT_HIRES; + } + + + /* compute bitmask from p1 value */ + dpll |= (1 << (clock.p1 - 2)) << 17; + + dpll |= DPLL_VCO_ENABLE; + + mrstPrintPll("chosen", &clock); + + if (dpll & DPLL_VCO_ENABLE) { + REG_WRITE(fp_reg, fp); + REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); + REG_READ(dpll_reg); + /* Check the DPLLA lock bit PIPEACONF[29] */ + udelay(150); + } + + REG_WRITE(fp_reg, fp); + REG_WRITE(dpll_reg, dpll); + REG_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + + /* write it again -- the BIOS does, after all */ + REG_WRITE(dpll_reg, dpll); + REG_READ(dpll_reg); + /* Wait for the clocks to stabilize. */ + udelay(150); + + REG_WRITE(pipeconf_reg, pipeconf); + REG_READ(pipeconf_reg); + psb_intel_wait_for_vblank(dev); + + REG_WRITE(dspcntr_reg, dspcntr); + psb_intel_wait_for_vblank(dev); + +mrst_crtc_mode_set_exit: + gma_power_end(dev); + return 0; +} + +static bool mrst_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +int mrst_pipe_set_base(struct drm_crtc *crtc, + int x, int y, struct drm_framebuffer *old_fb) +{ + struct drm_device *dev = crtc->dev; + /* struct drm_i915_master_private *master_priv; */ + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); + struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); + int pipe = psb_intel_crtc->pipe; + unsigned long start, offset; + /* FIXME: check if we need this surely MRST is pipe 0 only */ + int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE); + int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); + int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; + int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + u32 dspcntr; + int ret = 0; + + PSB_DEBUG_ENTRY("\n"); + + /* no fb bound */ + if (!crtc->fb) { + DRM_DEBUG("No FB bound\n"); + return 0; + } + + if (!gma_power_begin(dev, true)) + return 0; + + start = psbfb->gtt->offset; + offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); + + REG_WRITE(dspstride, crtc->fb->pitch); + + dspcntr = REG_READ(dspcntr_reg); + dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; + + 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 24: + case 32: + dspcntr |= DISPPLANE_32BPP_NO_ALPHA; + break; + default: + DRM_ERROR("Unknown color depth\n"); + ret = -EINVAL; + goto pipe_set_base_exit; + } + REG_WRITE(dspcntr_reg, dspcntr); + + DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y); + if (0 /* FIXMEAC - check what PSB needs */) { + REG_WRITE(dspbase, offset); + REG_READ(dspbase); + REG_WRITE(dspsurf, start); + REG_READ(dspsurf); + } else { + REG_WRITE(dspbase, start + offset); + REG_READ(dspbase); + } + +pipe_set_base_exit: + gma_power_end(dev); + return ret; +} + +static void mrst_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 mrst_crtc_commit(struct drm_crtc *crtc) +{ + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); +} + +const struct drm_crtc_helper_funcs mrst_helper_funcs = { + .dpms = mrst_crtc_dpms, + .mode_fixup = mrst_crtc_mode_fixup, + .mode_set = mrst_crtc_mode_set, + .mode_set_base = mrst_pipe_set_base, + .prepare = mrst_crtc_prepare, + .commit = mrst_crtc_commit, +}; + diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c new file mode 100644 index 000000000000..4a08b74f5ff9 --- /dev/null +++ b/drivers/staging/gma500/mrst_lvds.c @@ -0,0 +1,371 @@ +/* + * Copyright © 2006-2009 Intel Corporation + * + * 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. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * Dave Airlie <airlied@linux.ie> + * Jesse Barnes <jesse.barnes@intel.com> + */ + +#include <linux/i2c.h> +#include <drm/drmP.h> +#include <asm/mrst.h> + +#include "psb_intel_bios.h" +#include "psb_drv.h" +#include "psb_intel_drv.h" +#include "psb_intel_reg.h" +#include "psb_powermgmt.h" +#include <linux/pm_runtime.h> + +/* The max/min PWM frequency in BPCR[31:17] - */ +/* The smallest number is 1 (not 0) that can fit in the + * 15-bit field of the and then*/ +/* shifts to the left by one bit to get the actual 16-bit + * value that the 15-bits correspond to.*/ +#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF +#define BRIGHTNESS_MAX_LEVEL 100 + +/** + * Sets the power state for the panel. + */ +static void mrst_lvds_set_power(struct drm_device *dev, + struct psb_intel_output *output, bool on) +{ + u32 pp_status; + DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; + PSB_DEBUG_ENTRY("\n"); + + if (!gma_power_begin(dev, true)) + return; + + if (on) { + REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | + POWER_TARGET_ON); + do { + pp_status = REG_READ(PP_STATUS); + } while ((pp_status & (PP_ON | PP_READY)) == PP_READY); + dev_priv->is_lvds_on = true; + } else { + REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & + ~POWER_TARGET_ON); + do { + pp_status = REG_READ(PP_STATUS); + } while (pp_status & PP_ON); + dev_priv->is_lvds_on = false; + pm_request_idle(&dev->pdev->dev); + } + + gma_power_end(dev); +} + +static void mrst_lvds_dpms(struct drm_encoder *encoder, int mode) +{ + struct drm_device *dev = encoder->dev; + struct psb_intel_output *output = enc_to_psb_intel_output(encoder); + + PSB_DEBUG_ENTRY("\n"); + + if (mode == DRM_MODE_DPMS_ON) + mrst_lvds_set_power(dev, output, true); + else + mrst_lvds_set_power(dev, output, false); + + /* XXX: We never power down the LVDS pairs. */ +} + +static void mrst_lvds_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct psb_intel_mode_device *mode_dev = + enc_to_psb_intel_output(encoder)->mode_dev; + struct drm_device *dev = encoder->dev; + u32 lvds_port; + uint64_t v = DRM_MODE_SCALE_FULLSCREEN; + + PSB_DEBUG_ENTRY("\n"); + + if (!gma_power_begin(dev, true)) + return; + + /* + * The LVDS pin pair will already have been turned on in the + * psb_intel_crtc_mode_set since it has a large impact on the DPLL + * settings. + */ + lvds_port = (REG_READ(LVDS) & + (~LVDS_PIPEB_SELECT)) | + LVDS_PORT_EN | + LVDS_BORDER_EN; + + if (mode_dev->panel_wants_dither) + lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE; + + REG_WRITE(LVDS, lvds_port); + + drm_connector_property_get_value( + &enc_to_psb_intel_output(encoder)->base, + dev->mode_config.scaling_mode_property, + &v); + + if (v == DRM_MODE_SCALE_NO_SCALE) + REG_WRITE(PFIT_CONTROL, 0); + else if (v == DRM_MODE_SCALE_ASPECT) { + if ((mode->vdisplay != adjusted_mode->crtc_vdisplay) || + (mode->hdisplay != adjusted_mode->crtc_hdisplay)) { + if ((adjusted_mode->crtc_hdisplay * mode->vdisplay) == + (mode->hdisplay * adjusted_mode->crtc_vdisplay)) + REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); + else if ((adjusted_mode->crtc_hdisplay * + mode->vdisplay) > (mode->hdisplay * + adjusted_mode->crtc_vdisplay)) + REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | + PFIT_SCALING_MODE_PILLARBOX); + else + REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | + PFIT_SCALING_MODE_LETTERBOX); + } else + REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); + } else /*(v == DRM_MODE_SCALE_FULLSCREEN)*/ + REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); + + gma_power_end(dev); +} + + +static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = { + .dpms = mrst_lvds_dpms, + .mode_fixup = psb_intel_lvds_mode_fixup, + .prepare = psb_intel_lvds_prepare, + .mode_set = mrst_lvds_mode_set, + .commit = psb_intel_lvds_commit, +}; + +static struct drm_display_mode lvds_configuration_modes[] = { + /* hard coded fixed mode for TPO LTPS LPJ040K001A */ + { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 33264, 800, 836, + 846, 1056, 0, 480, 489, 491, 525, 0, 0) }, + /* hard coded fixed mode for LVDS 800x480 */ + { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 30994, 800, 801, + 802, 1024, 0, 480, 481, 482, 525, 0, 0) }, + /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ + { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072, + 1104, 1184, 0, 600, 603, 604, 608, 0, 0) }, + /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ + { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104, + 1136, 1184, 0, 600, 603, 604, 608, 0, 0) }, + /* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */ + { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124, + 1204, 1312, 0, 600, 607, 610, 621, 0, 0) }, + /* hard coded fixed mode for LVDS 1024x768 */ + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, + 1184, 1344, 0, 768, 771, 777, 806, 0, 0) }, + /* hard coded fixed mode for LVDS 1366x768 */ + { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430, + 1558, 1664, 0, 768, 769, 770, 776, 0, 0) }, +}; + +/* Returns the panel fixed mode from configuration. */ + +static struct drm_display_mode * +mrst_lvds_get_configuration_mode(struct drm_device *dev) +{ + struct drm_display_mode *mode = NULL; + struct drm_psb_private *dev_priv = dev->dev_private; + struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; + + if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/ + mode = kzalloc(sizeof(*mode), GFP_KERNEL); + if (!mode) + return NULL; + + mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; + mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; + mode->hsync_start = mode->hdisplay + \ + ((ti->hsync_offset_hi << 8) | \ + ti->hsync_offset_lo); + mode->hsync_end = mode->hsync_start + \ + ((ti->hsync_pulse_width_hi << 8) | \ + ti->hsync_pulse_width_lo); + mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ + ti->hblank_lo); + mode->vsync_start = \ + mode->vdisplay + ((ti->vsync_offset_hi << 4) | \ + ti->vsync_offset_lo); + mode->vsync_end = \ + mode->vsync_start + ((ti->vsync_pulse_width_hi << 4) | \ + ti->vsync_pulse_width_lo); + mode->vtotal = mode->vdisplay + \ + ((ti->vblank_hi << 8) | ti->vblank_lo); + mode->clock = ti->pixel_clock * 10; +#if 0 + printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay); + printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay); + printk(KERN_INFO "HSS is %d\n", mode->hsync_start); + printk(KERN_INFO "HSE is %d\n", mode->hsync_end); + printk(KERN_INFO "htotal is %d\n", mode->htotal); + printk(KERN_INFO "VSS is %d\n", mode->vsync_start); + printk(KERN_INFO "VSE is %d\n", mode->vsync_end); + printk(KERN_INFO "vtotal is %d\n", mode->vtotal); + printk(KERN_INFO "clock is %d\n", mode->clock); +#endif + } else + mode = drm_mode_duplicate(dev, &lvds_configuration_modes[2]); + + drm_mode_set_name(mode); + drm_mode_set_crtcinfo(mode, 0); + + return mode; +} + +/** + * mrst_lvds_init - setup LVDS connectors on this device + * @dev: drm device + * + * Create the connector, register the LVDS DDC bus, and try to figure out what + * modes we can display on the LVDS panel (if present). + */ +void mrst_lvds_init(struct drm_device *dev, + struct psb_intel_mode_device *mode_dev) +{ + struct psb_intel_output *psb_intel_output; + struct drm_connector *connector; + struct drm_encoder *encoder; + struct drm_psb_private *dev_priv = + (struct drm_psb_private *) dev->dev_private; + struct edid *edid; + int ret = 0; + struct i2c_adapter *i2c_adap; + struct drm_display_mode *scan; /* *modes, *bios_mode; */ + + PSB_DEBUG_ENTRY("\n"); + + psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); + if (!psb_intel_output) + return; + + psb_intel_output->mode_dev = mode_dev; + connector = &psb_intel_output->base; + encoder = &psb_intel_output->enc; + dev_priv->is_lvds_on = true; + drm_connector_init(dev, &psb_intel_output->base, + &psb_intel_lvds_connector_funcs, + DRM_MODE_CONNECTOR_LVDS); + + drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs, + DRM_MODE_ENCODER_LVDS); + + drm_mode_connector_attach_encoder(&psb_intel_output->base, + &psb_intel_output->enc); + psb_intel_output->type = INTEL_OUTPUT_LVDS; + + drm_encoder_helper_add(encoder, &mrst_lvds_helper_funcs); + drm_connector_helper_add(connector, + &psb_intel_lvds_connector_helper_funcs); + connector->display_info.subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = false; + connector->doublescan_allowed = false; + + drm_connector_attach_property(connector, + dev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_FULLSCREEN); + drm_connector_attach_property(connector, + dev_priv->backlight_property, + BRIGHTNESS_MAX_LEVEL); + + mode_dev->panel_wants_dither = false; + if (dev_priv->vbt_data.size != 0x00) + mode_dev->panel_wants_dither = (dev_priv->gct_data. + Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE); + + /* + * LVDS discovery: + * 1) check for EDID on DDC + * 2) check for VBT data + * 3) check to see if LVDS is already on + * if none of the above, no panel + * 4) make sure lid is open + * if closed, act like it's not there for now + */ + + /* This ifdef can go once the cpu ident stuff is cleaned up in arch */ +#if defined(CONFIG_X86_MRST) + if (mrst_identify_cpu()) + i2c_adap = i2c_get_adapter(2); + else /* Oaktrail uses I2C 1 */ +#endif + i2c_adap = i2c_get_adapter(1); + + if (i2c_adap == NULL) + printk(KERN_ALERT "No ddc adapter available!\n"); + /* + * Attempt to get the fixed panel mode from DDC. Assume that the + * preferred mode is the right one. + */ + if (i2c_adap) { + edid = drm_get_edid(connector, i2c_adap); + if (edid) { + drm_mode_connector_update_edid_property(connector, + edid); + ret = drm_add_edid_modes(connector, edid); + kfree(edid); + } + + list_for_each_entry(scan, &connector->probed_modes, head) { + if (scan->type & DRM_MODE_TYPE_PREFERRED) { + mode_dev->panel_fixed_mode = + drm_mode_duplicate(dev, scan); + goto out; /* FIXME: check for quirks */ + } + } + } + + /* + * If we didn't get EDID, try geting panel timing + * from configuration data + */ + mode_dev->panel_fixed_mode = mrst_lvds_get_configuration_mode(dev); + + if (mode_dev->panel_fixed_mode) { + mode_dev->panel_fixed_mode->type |= + DRM_MODE_TYPE_PREFERRED; + goto out; /* FIXME: check for quirks */ + } + + /* If we still don't have a mode after all that, give up. */ + if (!mode_dev->panel_fixed_mode) { + DRM_DEBUG + ("Found no modes on the lvds, ignoring the LVDS\n"); + goto failed_find; + } + +out: + drm_sysfs_connector_add(connector); + return; + +failed_find: + DRM_DEBUG("No LVDS modes found, disabling.\n"); + if (psb_intel_output->ddc_bus) + psb_intel_i2c_destroy(psb_intel_output->ddc_bus); + +/* failed_ddc: */ + + drm_encoder_cleanup(encoder); + drm_connector_cleanup(connector); + kfree(connector); +} + diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c index e4cae5d77d01..0bd834c982d3 100644 --- a/drivers/staging/gma500/psb_2d.c +++ b/drivers/staging/gma500/psb_2d.c @@ -40,7 +40,6 @@ #include "psb_reg.h" #include "psb_drv.h" #include "psb_fb.h" -#include "psb_sgx.h" void psb_spank(struct drm_psb_private *dev_priv) { @@ -85,7 +84,7 @@ static int psb_2d_wait_available(struct drm_psb_private *dev_priv, /* FIXME: Remember if we expose the 2D engine to the DRM we need to serialize it with console use */ -static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, +int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, unsigned size) { int ret = 0; @@ -161,7 +160,7 @@ static void psbfb_fillrect_accel(struct fb_info *info, if (!fb) return; - offset = psbfb->offset; + offset = psbfb->gtt->offset; stride = fb->pitch; switch (fb->depth) { @@ -304,7 +303,7 @@ static void psbfb_copyarea_accel(struct fb_info *info, if (!fb) return; - offset = psbfb->offset; + offset = psbfb->gtt->offset; stride = fb->pitch; switch (fb->depth) { @@ -344,7 +343,7 @@ void psbfb_copyarea(struct fb_info *info, if (unlikely(info->state != FBINFO_STATE_RUNNING)) return; - if (1 || (info->flags & FBINFO_HWACCEL_DISABLED)) + if (info->flags & FBINFO_HWACCEL_DISABLED) return cfb_copyarea(info, region); /* psb_check_power_state(dev, PSB_DEVICE_SGX); */ diff --git a/drivers/staging/gma500/psb_bl.c b/drivers/staging/gma500/psb_bl.c index 70c17b352f9f..5dffc71c5125 100644 --- a/drivers/staging/gma500/psb_bl.c +++ b/drivers/staging/gma500/psb_bl.c @@ -33,7 +33,6 @@ #define BLC_PWM_FREQ_CALC_CONSTANT 32 #define MHz 1000000 #define BRIGHTNESS_MIN_LEVEL 1 -#define BRIGHTNESS_MAX_LEVEL 100 #define BRIGHTNESS_MASK 0xFF #define BLC_POLARITY_NORMAL 0 #define BLC_POLARITY_INVERSE 1 @@ -59,15 +58,57 @@ int psb_set_brightness(struct backlight_device *bd) DRM_DEBUG_DRIVER("backlight level set to %d\n", level); - /* Perform value bounds checking */ - if (level < BRIGHTNESS_MIN_LEVEL) - level = BRIGHTNESS_MIN_LEVEL; + /* Percentage 1-100% being valid */ + if (level < 1) + level = 1; psb_intel_lvds_set_brightness(dev, level); psb_brightness = level; return 0; } +int mrst_set_brightness(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(psb_backlight_device); + struct drm_psb_private *dev_priv = dev->dev_private; + int level = bd->props.brightness; + u32 blc_pwm_ctl; + u32 max_pwm_blc; + + DRM_DEBUG_DRIVER("backlight level set to %d\n", level); + + /* Percentage 1-100% being valid */ + if (level < 1) + level = 1; + + if (gma_power_begin(dev, 0)) { + /* Calculate and set the brightness value */ + max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16; + blc_pwm_ctl = level * max_pwm_blc / 100; + + /* Adjust the backlight level with the percent in + * dev_priv->blc_adj1; + */ + blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1; + blc_pwm_ctl = blc_pwm_ctl / 100; + + /* Adjust the backlight level with the percent in + * dev_priv->blc_adj2; + */ + blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2; + blc_pwm_ctl = blc_pwm_ctl / 100; + + if (blc_pol == BLC_POLARITY_INVERSE) + blc_pwm_ctl = max_pwm_blc - blc_pwm_ctl; + /* force PWM bit on */ + REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); + REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl); + gma_power_end(dev); + } + psb_brightness = level; + return 0; +} + int psb_get_brightness(struct backlight_device *bd) { DRM_DEBUG_DRIVER("brightness = 0x%x\n", psb_brightness); @@ -85,24 +126,33 @@ static const struct backlight_ops psb_ops = { static int device_backlight_init(struct drm_device *dev) { + struct drm_psb_private *dev_priv = dev->dev_private; unsigned long core_clock; /* u32 bl_max_freq; */ /* unsigned long value; */ u16 bl_max_freq; uint32_t value; uint32_t blc_pwm_precision_factor; - struct drm_psb_private *dev_priv = dev->dev_private; - /* get bl_max_freq and pol from dev_priv*/ - if (!dev_priv->lvds_bl) { - DRM_ERROR("Has no valid LVDS backlight info\n"); - return 1; + if (IS_MRST(dev)) { + dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; + dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; + bl_max_freq = 256; + /* this needs to be set elsewhere */ + blc_pol = BLC_POLARITY_NORMAL; + blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR; + } else { + /* get bl_max_freq and pol from dev_priv*/ + if (!dev_priv->lvds_bl) { + DRM_ERROR("Has no valid LVDS backlight info\n"); + return 1; + } + bl_max_freq = dev_priv->lvds_bl->freq; + blc_pol = dev_priv->lvds_bl->pol; + blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; + blc_brightnesscmd = dev_priv->lvds_bl->brightnesscmd; + blc_type = dev_priv->lvds_bl->type; } - bl_max_freq = dev_priv->lvds_bl->freq; - blc_pol = dev_priv->lvds_bl->pol; - blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; - blc_brightnesscmd = dev_priv->lvds_bl->brightnesscmd; - blc_type = dev_priv->lvds_bl->type; core_clock = dev_priv->core_freq; @@ -111,20 +161,27 @@ static int device_backlight_init(struct drm_device *dev) value /= bl_max_freq; value /= blc_pwm_precision_factor; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { - /* Check: may be MFLD only */ - if ( - value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || - value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) - return 2; - else { - value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; - REG_WRITE(BLC_PWM_CTL, - (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | - (value)); + if (gma_power_begin(dev, false)) { + if (IS_MRST(dev)) { + if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ) + return 2; + else { + REG_WRITE(BLC_PWM_CTL2, + (0x80000000 | REG_READ(BLC_PWM_CTL2))); + REG_WRITE(BLC_PWM_CTL, value | (value << 16)); + } + } else { + if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || + value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) + return 2; + else { + value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; + REG_WRITE(BLC_PWM_CTL, + (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | + (value)); + } } - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } return 0; } @@ -136,7 +193,8 @@ int psb_backlight_init(struct drm_device *dev) struct backlight_properties props; memset(&props, 0, sizeof(struct backlight_properties)); - props.max_brightness = BRIGHTNESS_MAX_LEVEL; + props.max_brightness = 100; + props.type = BACKLIGHT_PLATFORM; psb_backlight_device = backlight_device_register("psb-bl", NULL, (void *)dev, &psb_ops, &props); @@ -147,8 +205,8 @@ int psb_backlight_init(struct drm_device *dev) if (ret < 0) return ret; - psb_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL; - psb_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL; + psb_backlight_device->props.brightness = 100; + psb_backlight_device->props.max_brightness = 100; backlight_update_status(psb_backlight_device); #endif return 0; diff --git a/drivers/staging/gma500/psb_buffer.c b/drivers/staging/gma500/psb_buffer.c deleted file mode 100644 index 3077f6a7b7dc..000000000000 --- a/drivers/staging/gma500/psb_buffer.c +++ /dev/null @@ -1,450 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007, Intel Corporation. - * - * 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. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com> - */ -#include "ttm/ttm_placement.h" -#include "ttm/ttm_execbuf_util.h" -#include "psb_ttm_fence_api.h" -#include <drm/drmP.h> -#include "psb_drv.h" - -#define DRM_MEM_TTM 26 - -struct drm_psb_ttm_backend { - struct 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; -}; - -/* - * MSVDX/TOPAZ GPU virtual space looks like this - * (We currently use only one MMU context). - * PSB_MEM_MMU_START: from 0x00000000~0xe000000, for generic buffers - * TTM_PL_CI: from 0xe0000000+half GTT space, for camear/video buffer sharing - * TTM_PL_RAR: from TTM_PL_CI+CI size, for RAR/video buffer sharing - * TTM_PL_TT: from TTM_PL_RAR+RAR size, for buffers need to mapping into GTT - */ -static int psb_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - - struct drm_psb_private *dev_priv = - container_of(bdev, struct drm_psb_private, bdev); - struct psb_gtt *pg = dev_priv->pg; - - switch (type) { - case TTM_PL_SYSTEM: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_CACHED | - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case DRM_PSB_MEM_MMU: - man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | - TTM_MEMTYPE_FLAG_CMA; - man->gpu_offset = PSB_MEM_MMU_START; - man->available_caching = TTM_PL_FLAG_CACHED | - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - break; - case TTM_PL_CI: - man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | - TTM_MEMTYPE_FLAG_FIXED; - man->gpu_offset = pg->mmu_gatt_start + (pg->ci_start); - man->available_caching = TTM_PL_FLAG_UNCACHED; - man->default_caching = TTM_PL_FLAG_UNCACHED; - break; - case TTM_PL_RAR: /* Unmappable RAR memory */ - man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | - TTM_MEMTYPE_FLAG_FIXED; - man->available_caching = TTM_PL_FLAG_UNCACHED; - man->default_caching = TTM_PL_FLAG_UNCACHED; - man->gpu_offset = pg->mmu_gatt_start + (pg->rar_start); - break; - case TTM_PL_TT: /* Mappable GATT memory */ - man->func = &ttm_bo_manager_func; -#ifdef PSB_WORKING_HOST_MMU_ACCESS - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; -#else - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | - TTM_MEMTYPE_FLAG_CMA; -#endif - man->available_caching = TTM_PL_FLAG_CACHED | - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - man->gpu_offset = pg->mmu_gatt_start + - (pg->rar_start + dev_priv->rar_region_size); - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned) type); - return -EINVAL; - } - return 0; -} - - -static void psb_evict_mask(struct ttm_buffer_object *bo, - struct ttm_placement *placement) -{ - static uint32_t cur_placement; - - cur_placement = bo->mem.placement & ~TTM_PL_MASK_MEM; - cur_placement |= TTM_PL_FLAG_SYSTEM; - - placement->fpfn = 0; - placement->lpfn = 0; - placement->num_placement = 1; - placement->placement = &cur_placement; - placement->num_busy_placement = 0; - placement->busy_placement = NULL; - - /* all buffers evicted to system memory */ - /* return cur_placement | TTM_PL_FLAG_SYSTEM; */ -} - -static int psb_invalidate_caches(struct ttm_bo_device *bdev, - uint32_t placement) -{ - return 0; -} - -static int psb_move_blit(struct ttm_buffer_object *bo, - bool evict, bool no_wait, - struct ttm_mem_reg *new_mem) -{ - BUG(); - return 0; -} - -/* - * Flip destination ttm into GATT, - * then blit and subsequently move out again. - */ - -static int psb_move_flip(struct ttm_buffer_object *bo, - bool evict, bool interruptible, bool no_wait, - struct ttm_mem_reg *new_mem) -{ - /*struct ttm_bo_device *bdev = bo->bdev;*/ - struct ttm_mem_reg tmp_mem; - int ret; - struct ttm_placement placement; - uint32_t flags = TTM_PL_FLAG_TT; - - tmp_mem = *new_mem; - tmp_mem.mm_node = NULL; - - placement.fpfn = 0; - placement.lpfn = 0; - placement.num_placement = 1; - placement.placement = &flags; - placement.num_busy_placement = 0; /* FIXME */ - placement.busy_placement = NULL; - - ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, - false, no_wait); - if (ret) - return ret; - ret = ttm_tt_bind(bo->ttm, &tmp_mem); - if (ret) - goto out_cleanup; - ret = psb_move_blit(bo, true, no_wait, &tmp_mem); - if (ret) - goto out_cleanup; - - ret = ttm_bo_move_ttm(bo, evict, false, no_wait, new_mem); -out_cleanup: - if (tmp_mem.mm_node) { - drm_mm_put_block(tmp_mem.mm_node); - tmp_mem.mm_node = NULL; - } - return ret; -} - -static int psb_move(struct ttm_buffer_object *bo, - bool evict, bool interruptible, bool no_wait_reserve, - bool no_wait, struct ttm_mem_reg *new_mem) -{ - struct ttm_mem_reg *old_mem = &bo->mem; - - if ((old_mem->mem_type == TTM_PL_RAR) || - (new_mem->mem_type == TTM_PL_RAR)) { - if (old_mem->mm_node) { - spin_lock(&bo->glob->lru_lock); - drm_mm_put_block(old_mem->mm_node); - spin_unlock(&bo->glob->lru_lock); - } - old_mem->mm_node = NULL; - *old_mem = *new_mem; - } else if (old_mem->mem_type == TTM_PL_SYSTEM) { - return ttm_bo_move_memcpy(bo, evict, false, no_wait, new_mem); - } else if (new_mem->mem_type == TTM_PL_SYSTEM) { - int ret = psb_move_flip(bo, evict, interruptible, - no_wait, new_mem); - if (unlikely(ret != 0)) { - if (ret == -ERESTART) - return ret; - else - return ttm_bo_move_memcpy(bo, evict, false, - no_wait, new_mem); - } - } else { - if (psb_move_blit(bo, evict, no_wait, new_mem)) - return ttm_bo_move_memcpy(bo, evict, false, no_wait, - new_mem); - } - return 0; -} - -static int drm_psb_tbe_populate(struct ttm_backend *backend, - unsigned long num_pages, - struct page **pages, - struct page *dummy_read_page, - dma_addr_t *dma_addrs) -{ - struct drm_psb_ttm_backend *psb_be = - container_of(backend, struct drm_psb_ttm_backend, base); - - psb_be->pages = pages; - return 0; -} - -static int drm_psb_tbe_unbind(struct ttm_backend *backend) -{ - struct ttm_bo_device *bdev = backend->bdev; - struct drm_psb_private *dev_priv = - container_of(bdev, struct drm_psb_private, bdev); - 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 ttm_mem_type_manager *man = &bdev->man[psb_be->mem_type]; */ - - if (psb_be->mem_type == TTM_PL_TT) { - uint32_t gatt_p_offset = - (psb_be->offset - dev_priv->pg->mmu_gatt_start) - >> PAGE_SHIFT; - - (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, 0); - } - - psb_mmu_remove_pages(pd, psb_be->offset, - psb_be->num_pages, - psb_be->desired_tile_stride, - psb_be->hw_tile_stride); - - return 0; -} - -static int drm_psb_tbe_bind(struct ttm_backend *backend, - struct ttm_mem_reg *bo_mem) -{ - struct ttm_bo_device *bdev = backend->bdev; - struct drm_psb_private *dev_priv = - container_of(bdev, struct drm_psb_private, bdev); - 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 ttm_mem_type_manager *man = &bdev->man[bo_mem->mem_type]; - struct drm_mm_node *mm_node = bo_mem->mm_node; - int type; - int ret = 0; - - psb_be->mem_type = bo_mem->mem_type; - psb_be->num_pages = bo_mem->num_pages; - psb_be->desired_tile_stride = 0; - psb_be->hw_tile_stride = 0; - psb_be->offset = (mm_node->start << PAGE_SHIFT) + - man->gpu_offset; - - type = - (bo_mem-> - placement & TTM_PL_FLAG_CACHED) ? PSB_MMU_CACHED_MEMORY : 0; - - if (psb_be->mem_type == TTM_PL_TT) { - uint32_t gatt_p_offset = - (psb_be->offset - dev_priv->pg->mmu_gatt_start) - >> PAGE_SHIFT; - - 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); - } - - 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; - - return 0; -out_err: - drm_psb_tbe_unbind(backend); - return ret; - -} - -static void drm_psb_tbe_clear(struct ttm_backend *backend) -{ - struct drm_psb_ttm_backend *psb_be = - container_of(backend, struct drm_psb_ttm_backend, base); - - psb_be->pages = NULL; - return; -} - -static void drm_psb_tbe_destroy(struct ttm_backend *backend) -{ - struct drm_psb_ttm_backend *psb_be = - container_of(backend, struct drm_psb_ttm_backend, base); - - if (backend) - kfree(psb_be); -} - -static struct ttm_backend_func psb_ttm_backend = { - .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, -}; - -static struct ttm_backend *drm_psb_tbe_init(struct ttm_bo_device *bdev) -{ - struct drm_psb_ttm_backend *psb_be; - - psb_be = kzalloc(sizeof(*psb_be), GFP_KERNEL); - if (!psb_be) - return NULL; - psb_be->pages = NULL; - psb_be->base.func = &psb_ttm_backend; - psb_be->base.bdev = bdev; - return &psb_be->base; -} - -static int psb_ttm_io_mem_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) -{ - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct drm_psb_private *dev_priv = - container_of(bdev, struct drm_psb_private, bdev); - struct psb_gtt *pg = dev_priv->pg; - struct drm_mm_node *mm_node = mem->mm_node; - - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - mem->bus.is_iomem = false; - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) - return -EINVAL; - switch (mem->mem_type) { - case TTM_PL_SYSTEM: - /* system memory */ - return 0; - case TTM_PL_TT: - mem->bus.offset = mm_node->start << PAGE_SHIFT; - mem->bus.base = pg->gatt_start; - mem->bus.is_iomem = false; - /* Don't know whether it is IO_MEM, this flag - used in vm_fault handle */ - break; - case DRM_PSB_MEM_MMU: - mem->bus.offset = mm_node->start << PAGE_SHIFT; - mem->bus.base = 0x00000000; - break; - case TTM_PL_CI: - mem->bus.offset = mm_node->start << PAGE_SHIFT; - mem->bus.base = dev_priv->ci_region_start;; - mem->bus.is_iomem = true; - break; - case TTM_PL_RAR: - mem->bus.offset = mm_node->start << PAGE_SHIFT; - mem->bus.base = dev_priv->rar_region_start;; - mem->bus.is_iomem = true; - break; - default: - return -EINVAL; - } - return 0; -} - -static void psb_ttm_io_mem_free(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) -{ -} - -/* - * Use this memory type priority if no eviction is needed. - */ -/* -static uint32_t psb_mem_prios[] = { - TTM_PL_CI, - TTM_PL_RAR, - TTM_PL_TT, - DRM_PSB_MEM_MMU, - TTM_PL_SYSTEM -}; -*/ -/* - * Use this memory type priority if need to evict. - */ -/* -static uint32_t psb_busy_prios[] = { - TTM_PL_TT, - TTM_PL_CI, - TTM_PL_RAR, - DRM_PSB_MEM_MMU, - TTM_PL_SYSTEM -}; -*/ -struct ttm_bo_driver psb_ttm_bo_driver = { -/* - .mem_type_prio = psb_mem_prios, - .mem_busy_prio = psb_busy_prios, - .num_mem_type_prio = ARRAY_SIZE(psb_mem_prios), - .num_mem_busy_prio = ARRAY_SIZE(psb_busy_prios), -*/ - .create_ttm_backend_entry = &drm_psb_tbe_init, - .invalidate_caches = &psb_invalidate_caches, - .init_mem_type = &psb_init_mem_type, - .evict_flags = &psb_evict_mask, - .move = &psb_move, - .verify_access = &psb_verify_access, - .sync_obj_signaled = &ttm_fence_sync_obj_signaled, - .sync_obj_wait = &ttm_fence_sync_obj_wait, - .sync_obj_flush = &ttm_fence_sync_obj_flush, - .sync_obj_unref = &ttm_fence_sync_obj_unref, - .sync_obj_ref = &ttm_fence_sync_obj_ref, - .io_mem_reserve = &psb_ttm_io_mem_reserve, - .io_mem_free = &psb_ttm_io_mem_free -}; diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h index a339406052ef..49ffdd5b90e2 100644 --- a/drivers/staging/gma500/psb_drm.h +++ b/drivers/staging/gma500/psb_drm.h @@ -28,9 +28,6 @@ #include "drm_mode.h" #endif -#include "psb_ttm_fence_user.h" -#include "psb_ttm_placement_user.h" - #define DRM_PSB_SAREA_MAJOR 0 #define DRM_PSB_SAREA_MINOR 2 #define PSB_FIXED_SHIFT 16 @@ -41,15 +38,6 @@ * Public memory types. */ -#define DRM_PSB_MEM_MMU TTM_PL_PRIV1 -#define DRM_PSB_FLAG_MEM_MMU TTM_PL_FLAG_PRIV1 - -#define TTM_PL_CI TTM_PL_PRIV0 -#define TTM_PL_FLAG_CI TTM_PL_FLAG_PRIV0 - -#define TTM_PL_RAR TTM_PL_PRIV2 -#define TTM_PL_FLAG_RAR TTM_PL_FLAG_PRIV2 - typedef s32 psb_fixed; typedef u32 psb_ufixed; @@ -112,111 +100,12 @@ struct drm_psb_sarea { u32 num_active_scanouts; }; -#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 - -#define PSB_RELOC_OP_OFFSET 0 /* Offset of the indicated - * buffer - */ - -struct drm_psb_reloc { - u32 reloc_op; - u32 where; /* offset in destination buffer */ - u32 buffer; /* Buffer reloc applies to */ - u32 mask; /* Destination format: */ - u32 shift; /* Destination format: */ - u32 pre_add; /* Destination format: */ - u32 background; /* Destination add */ - u32 dst_buffer; /* Destination buffer. Index into buffer_list */ - u32 arg0; /* Reloc-op dependent */ - u32 arg1; -}; - - #define PSB_GPU_ACCESS_READ (1ULL << 32) #define PSB_GPU_ACCESS_WRITE (1ULL << 33) #define PSB_GPU_ACCESS_MASK (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) #define PSB_BO_FLAG_COMMAND (1ULL << 52) -#define PSB_ENGINE_2D 0 -#define PSB_ENGINE_VIDEO 1 -#define LNC_ENGINE_ENCODE 5 - -/* - * For this fence class we have a couple of - * fence types. - */ - -#define _PSB_FENCE_EXE_SHIFT 0 -#define _PSB_FENCE_FEEDBACK_SHIFT 4 - -#define _PSB_FENCE_TYPE_EXE (1 << _PSB_FENCE_EXE_SHIFT) -#define _PSB_FENCE_TYPE_FEEDBACK (1 << _PSB_FENCE_FEEDBACK_SHIFT) - -#define PSB_NUM_ENGINES 6 - - -#define PSB_FEEDBACK_OP_VISTEST (1 << 0) - -struct drm_psb_extension_rep { - s32 exists; - u32 driver_ioctl_offset; - u32 sarea_offset; - u32 major; - u32 minor; - u32 pl; -}; - -#define DRM_PSB_EXT_NAME_LEN 128 - -union drm_psb_extension_arg { - char extension[DRM_PSB_EXT_NAME_LEN]; - struct drm_psb_extension_rep rep; -}; - -struct psb_validate_req { - u64 set_flags; - u64 clear_flags; - u64 next; - u64 presumed_gpu_offset; - u32 buffer_handle; - u32 presumed_flags; - u32 group; - u32 pad64; -}; - -struct psb_validate_rep { - u64 gpu_offset; - u32 placement; - u32 fence_type_mask; -}; - -#define PSB_USE_PRESUMED (1 << 0) - -struct psb_validate_arg { - int handled; - int ret; - union { - struct psb_validate_req req; - struct psb_validate_rep rep; - } d; -}; - - -#define DRM_PSB_FENCE_NO_USER (1 << 0) - -struct psb_ttm_fence_rep { - u32 handle; - u32 fence_class; - u32 fence_type; - u32 signaled_types; - u32 error; -}; - /* * Feedback components: */ @@ -330,17 +219,6 @@ struct drm_psb_register_rw_arg { u32 subpicture_disable_mask; }; -struct psb_gtt_mapping_arg { - void *hKernelMemInfo; - u32 offset_pages; -}; - -struct drm_psb_getpageaddrs_arg { - u32 handle; - unsigned long *page_addrs; - unsigned long gtt_offset; -}; - /* Controlling the kernel modesetting buffers */ #define DRM_PSB_KMS_OFF 0x00 diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c index d01d45e7a14d..aa87b1b6a44a 100644 --- a/drivers/staging/gma500/psb_drv.c +++ b/drivers/staging/gma500/psb_drv.c @@ -38,30 +38,29 @@ int drm_psb_debug; static int drm_psb_trap_pagefaults; -int drm_psb_disable_vsync = 1; int drm_psb_no_fb; -int gfxrtdelay = 2 * 1000; static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); MODULE_PARM_DESC(debug, "Enable debug output"); MODULE_PARM_DESC(no_fb, "Disable FBdev"); MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults"); -MODULE_PARM_DESC(disable_vsync, "Disable vsync interrupts"); -MODULE_PARM_DESC(force_pipeb, "Forces PIPEB to become primary fb"); -MODULE_PARM_DESC(ta_mem_size, "TA memory size in kiB"); -MODULE_PARM_DESC(ospm, "switch for ospm support"); -MODULE_PARM_DESC(rtpm, "Specifies Runtime PM delay for GFX"); -MODULE_PARM_DESC(hdmi_edid, "EDID info for HDMI monitor"); module_param_named(debug, drm_psb_debug, int, 0600); module_param_named(no_fb, drm_psb_no_fb, int, 0600); module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600); -module_param_named(rtpm, gfxrtdelay, int, 0600); static struct pci_device_id pciidlist[] = { { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108 }, { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109 }, + { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, + { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, + { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, + { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, + { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, + { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, + { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, + { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, { 0, 0, 0} }; MODULE_DEVICE_TABLE(pci, pciidlist); @@ -74,10 +73,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist); DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE) #define DRM_IOCTL_PSB_KMS_ON \ DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE) -#define DRM_IOCTL_PSB_VT_LEAVE \ - DRM_IO(DRM_PSB_VT_LEAVE + DRM_COMMAND_BASE) -#define DRM_IOCTL_PSB_VT_ENTER \ - DRM_IO(DRM_PSB_VT_ENTER + DRM_COMMAND_BASE) #define DRM_IOCTL_PSB_SIZES \ DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \ struct drm_psb_sizes_arg) @@ -97,18 +92,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist); #define DRM_IOCTL_PSB_REGISTER_RW \ DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \ struct drm_psb_register_rw_arg) -#define DRM_IOCTL_PSB_GTT_MAP \ - DRM_IOWR(DRM_PSB_GTT_MAP + DRM_COMMAND_BASE, \ - struct psb_gtt_mapping_arg) -#define DRM_IOCTL_PSB_GTT_UNMAP \ - DRM_IOW(DRM_PSB_GTT_UNMAP + DRM_COMMAND_BASE, \ - struct psb_gtt_mapping_arg) -#define DRM_IOCTL_PSB_GETPAGEADDRS \ - DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_GETPAGEADDRS,\ - struct drm_psb_getpageaddrs_arg) -#define DRM_IOCTL_PSB_UPDATE_GUARD \ - DRM_IOWR(DRM_PSB_UPDATE_GUARD + DRM_COMMAND_BASE, \ - uint32_t) #define DRM_IOCTL_PSB_DPST \ DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \ uint32_t) @@ -122,74 +105,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist); DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \ struct drm_psb_get_pipe_from_crtc_id_arg) -/* - * TTM execbuf extension. - */ - -#define DRM_PSB_CMDBUF 0x23 -#define DRM_PSB_SCENE_UNREF 0x24 -#define DRM_IOCTL_PSB_KMS_OFF DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE) -#define DRM_IOCTL_PSB_KMS_ON DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE) -/* - * TTM placement user extension. - */ - -#define DRM_PSB_PLACEMENT_OFFSET (DRM_PSB_SCENE_UNREF + 1) - -#define DRM_PSB_TTM_PL_CREATE (TTM_PL_CREATE + DRM_PSB_PLACEMENT_OFFSET) -#define DRM_PSB_TTM_PL_REFERENCE (TTM_PL_REFERENCE + DRM_PSB_PLACEMENT_OFFSET) -#define DRM_PSB_TTM_PL_UNREF (TTM_PL_UNREF + DRM_PSB_PLACEMENT_OFFSET) -#define DRM_PSB_TTM_PL_SYNCCPU (TTM_PL_SYNCCPU + DRM_PSB_PLACEMENT_OFFSET) -#define DRM_PSB_TTM_PL_WAITIDLE (TTM_PL_WAITIDLE + DRM_PSB_PLACEMENT_OFFSET) -#define DRM_PSB_TTM_PL_SETSTATUS (TTM_PL_SETSTATUS + DRM_PSB_PLACEMENT_OFFSET) -#define DRM_PSB_TTM_PL_CREATE_UB (TTM_PL_CREATE_UB + DRM_PSB_PLACEMENT_OFFSET) - -/* - * TTM fence extension. - */ - -#define DRM_PSB_FENCE_OFFSET (DRM_PSB_TTM_PL_CREATE_UB + 1) -#define DRM_PSB_TTM_FENCE_SIGNALED (TTM_FENCE_SIGNALED + DRM_PSB_FENCE_OFFSET) -#define DRM_PSB_TTM_FENCE_FINISH (TTM_FENCE_FINISH + DRM_PSB_FENCE_OFFSET) -#define DRM_PSB_TTM_FENCE_UNREF (TTM_FENCE_UNREF + DRM_PSB_FENCE_OFFSET) - -#define DRM_PSB_FLIP (DRM_PSB_TTM_FENCE_UNREF + 1) /*20*/ - -#define DRM_IOCTL_PSB_TTM_PL_CREATE \ - DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE,\ - union ttm_pl_create_arg) -#define DRM_IOCTL_PSB_TTM_PL_REFERENCE \ - DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_REFERENCE,\ - union ttm_pl_reference_arg) -#define DRM_IOCTL_PSB_TTM_PL_UNREF \ - DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_UNREF,\ - struct ttm_pl_reference_req) -#define DRM_IOCTL_PSB_TTM_PL_SYNCCPU \ - DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SYNCCPU,\ - struct ttm_pl_synccpu_arg) -#define DRM_IOCTL_PSB_TTM_PL_WAITIDLE \ - DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_WAITIDLE,\ - struct ttm_pl_waitidle_arg) -#define DRM_IOCTL_PSB_TTM_PL_SETSTATUS \ - DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SETSTATUS,\ - union ttm_pl_setstatus_arg) -#define DRM_IOCTL_PSB_TTM_PL_CREATE_UB \ - DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE_UB,\ - union ttm_pl_create_ub_arg) -#define DRM_IOCTL_PSB_TTM_FENCE_SIGNALED \ - DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_SIGNALED, \ - union ttm_fence_signaled_arg) -#define DRM_IOCTL_PSB_TTM_FENCE_FINISH \ - DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_FINISH, \ - union ttm_fence_finish_arg) -#define DRM_IOCTL_PSB_TTM_FENCE_UNREF \ - DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_UNREF, \ - struct ttm_fence_unref_arg) - -static int psb_vt_leave_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -static int psb_vt_enter_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); static int psb_sizes_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); static int psb_dc_state_ioctl(struct drm_device *dev, void * data, @@ -218,11 +133,6 @@ static struct drm_ioctl_desc psb_ioctls[] = { PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_ON, psbfb_kms_on_ioctl, DRM_ROOT_ONLY), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_LEAVE, psb_vt_leave_ioctl, - DRM_ROOT_ONLY), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_ENTER, - psb_vt_enter_ioctl, - DRM_ROOT_ONLY), PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH), PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH), PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH), @@ -232,92 +142,226 @@ static struct drm_ioctl_desc psb_ioctls[] = { DRM_AUTH), PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl, DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_MAP, - psb_gtt_map_meminfo_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_UNMAP, - psb_gtt_unmap_meminfo_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_GETPAGEADDRS, - psb_getpageaddrs_ioctl, - DRM_AUTH), PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH), PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH), PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH), PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID, psb_intel_get_pipe_from_crtc_id, 0), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE, psb_pl_create_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_REFERENCE, psb_pl_reference_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_UNREF, psb_pl_unref_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SYNCCPU, psb_pl_synccpu_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_WAITIDLE, psb_pl_waitidle_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SETSTATUS, psb_pl_setstatus_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE_UB, psb_pl_ub_create_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_SIGNALED, - psb_fence_signaled_ioctl, DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_FINISH, psb_fence_finish_ioctl, - DRM_AUTH), - PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_UNREF, psb_fence_unref_ioctl, - DRM_AUTH), }; -static void psb_set_uopt(struct drm_psb_uopt *uopt) +static void psb_lastclose(struct drm_device *dev) { return; } -static void psb_lastclose(struct drm_device *dev) +static void psb_do_takedown(struct drm_device *dev) { - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; + /* FIXME: do we need to clean up the gtt here ? */ +} - return; +void mrst_get_fuse_settings(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); + uint32_t fuse_value = 0; + uint32_t fuse_value_tmp = 0; - if (!dev->dev_private) - return; +#define FB_REG06 0xD0810600 +#define FB_MIPI_DISABLE (1 << 11) +#define FB_REG09 0xD0810900 +#define FB_REG09 0xD0810900 +#define FB_SKU_MASK 0x7000 +#define FB_SKU_SHIFT 12 +#define FB_SKU_100 0 +#define FB_SKU_100L 1 +#define FB_SKU_83 2 + pci_write_config_dword(pci_root, 0xD0, FB_REG06); + pci_read_config_dword(pci_root, 0xD4, &fuse_value); + + dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE; + + DRM_INFO("internal display is %s\n", + dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display"); + + /*prevent Runtime suspend at start*/ + if (dev_priv->iLVDS_enable) { + dev_priv->is_lvds_on = true; + dev_priv->is_mipi_on = false; + } + else { + dev_priv->is_mipi_on = true; + dev_priv->is_lvds_on = false; + } + + dev_priv->video_device_fuse = fuse_value; + + pci_write_config_dword(pci_root, 0xD0, FB_REG09); + pci_read_config_dword(pci_root, 0xD4, &fuse_value); + + DRM_INFO("SKU values is 0x%x. \n", fuse_value); + fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT; - mutex_lock(&dev_priv->cmdbuf_mutex); - if (dev_priv->context.buffers) { - vfree(dev_priv->context.buffers); - dev_priv->context.buffers = NULL; + dev_priv->fuse_reg_value = fuse_value; + + switch (fuse_value_tmp) { + case FB_SKU_100: + dev_priv->core_freq = 200; + break; + case FB_SKU_100L: + dev_priv->core_freq = 100; + break; + case FB_SKU_83: + dev_priv->core_freq = 166; + break; + default: + DRM_ERROR("Invalid SKU values, SKU value = 0x%08x\n", fuse_value_tmp); + dev_priv->core_freq = 0; } - mutex_unlock(&dev_priv->cmdbuf_mutex); + DRM_INFO("LNC core clk is %dMHz.\n", dev_priv->core_freq); + pci_dev_put(pci_root); } -static void psb_do_takedown(struct drm_device *dev) +void mid_get_pci_revID (struct drm_psb_private *dev_priv) { - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - struct ttm_bo_device *bdev = &dev_priv->bdev; + uint32_t platform_rev_id = 0; + struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); + /*get the revison ID, B0:D2:F0;0x08 */ + pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); + dev_priv->platform_rev_id = (uint8_t) platform_rev_id; + pci_dev_put(pci_gfx_root); + PSB_DEBUG_ENTRY("platform_rev_id is %x\n", dev_priv->platform_rev_id); +} - if (dev_priv->have_mem_mmu) { - ttm_bo_clean_mm(bdev, DRM_PSB_MEM_MMU); - dev_priv->have_mem_mmu = 0; - } +void mrst_get_vbt_data(struct drm_psb_private *dev_priv) +{ + struct mrst_vbt *vbt = &dev_priv->vbt_data; + u32 platform_config_address; + u16 new_size; + u8 *vbt_virtual; + u8 bpi; + u8 number_desc = 0; + struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD; + struct gct_r10_timing_info ti; + void *pGCT; + struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); - if (dev_priv->have_tt) { - ttm_bo_clean_mm(bdev, TTM_PL_TT); - dev_priv->have_tt = 0; - } + /*get the address of the platform config vbt, B0:D2:F0;0xFC */ + pci_read_config_dword(pci_gfx_root, 0xFC, &platform_config_address); + pci_dev_put(pci_gfx_root); + DRM_INFO("drm platform config address is %x\n", + platform_config_address); - if (dev_priv->have_camera) { - ttm_bo_clean_mm(bdev, TTM_PL_CI); - dev_priv->have_camera = 0; - } - if (dev_priv->have_rar) { - ttm_bo_clean_mm(bdev, TTM_PL_RAR); - dev_priv->have_rar = 0; + /* check for platform config address == 0. */ + /* this means fw doesn't support vbt */ + + if (platform_config_address == 0) { + vbt->size = 0; + return; } + /* get the virtual address of the vbt */ + vbt_virtual = ioremap(platform_config_address, sizeof(*vbt)); + + memcpy(vbt, vbt_virtual, sizeof(*vbt)); + iounmap(vbt_virtual); /* Free virtual address space */ + + printk(KERN_ALERT "GCT revision is %x\n", vbt->revision); + + switch (vbt->revision) { + case 0: + vbt->mrst_gct = NULL; + vbt->mrst_gct = \ + ioremap(platform_config_address + sizeof(*vbt) - 4, + vbt->size - sizeof(*vbt) + 4); + pGCT = vbt->mrst_gct; + bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex; + dev_priv->gct_data.bpi = bpi; + dev_priv->gct_data.pt = + ((struct mrst_gct_v1 *)pGCT)->PD.PanelType; + memcpy(&dev_priv->gct_data.DTD, + &((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD, + sizeof(struct mrst_timing_info)); + dev_priv->gct_data.Panel_Port_Control = + ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; + dev_priv->gct_data.Panel_MIPI_Display_Descriptor = + ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; + break; + case 1: + vbt->mrst_gct = NULL; + vbt->mrst_gct = \ + ioremap(platform_config_address + sizeof(*vbt) - 4, + vbt->size - sizeof(*vbt) + 4); + pGCT = vbt->mrst_gct; + bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex; + dev_priv->gct_data.bpi = bpi; + dev_priv->gct_data.pt = + ((struct mrst_gct_v2 *)pGCT)->PD.PanelType; + memcpy(&dev_priv->gct_data.DTD, + &((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD, + sizeof(struct mrst_timing_info)); + dev_priv->gct_data.Panel_Port_Control = + ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; + dev_priv->gct_data.Panel_MIPI_Display_Descriptor = + ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; + break; + case 0x10: + /*header definition changed from rev 01 (v2) to rev 10h. */ + /*so, some values have changed location*/ + new_size = vbt->checksum; /*checksum contains lo size byte*/ + /*LSB of mrst_gct contains hi size byte*/ + new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8; + + vbt->checksum = vbt->size; /*size contains the checksum*/ + if (new_size > 0xff) + vbt->size = 0xff; /*restrict size to 255*/ + else + vbt->size = new_size; + + /* number of descriptors defined in the GCT */ + number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8; + bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16; + vbt->mrst_gct = NULL; + vbt->mrst_gct = \ + ioremap(platform_config_address + GCT_R10_HEADER_SIZE, + GCT_R10_DISPLAY_DESC_SIZE * number_desc); + pGCT = vbt->mrst_gct; + pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); + dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ + + /*copy the GCT display timings into a temp structure*/ + memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); + + /*now copy the temp struct into the dev_priv->gct_data*/ + dp_ti->pixel_clock = ti.pixel_clock; + dp_ti->hactive_hi = ti.hactive_hi; + dp_ti->hactive_lo = ti.hactive_lo; + dp_ti->hblank_hi = ti.hblank_hi; + dp_ti->hblank_lo = ti.hblank_lo; + dp_ti->hsync_offset_hi = ti.hsync_offset_hi; + dp_ti->hsync_offset_lo = ti.hsync_offset_lo; + dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; + dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; + dp_ti->vactive_hi = ti.vactive_hi; + dp_ti->vactive_lo = ti.vactive_lo; + dp_ti->vblank_hi = ti.vblank_hi; + dp_ti->vblank_lo = ti.vblank_lo; + dp_ti->vsync_offset_hi = ti.vsync_offset_hi; + dp_ti->vsync_offset_lo = ti.vsync_offset_lo; + dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; + dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; + + /*mov the MIPI_Display_Descriptor data from GCT to dev priv*/ + dev_priv->gct_data.Panel_MIPI_Display_Descriptor = + *((u8 *)pGCT + 0x0d); + dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= + (*((u8 *)pGCT + 0x0e)) << 8; + break; + default: + printk(KERN_ERR "Unknown revision of GCT!\n"); + vbt->size = 0; + } } static void psb_get_core_freq(struct drm_device *dev) @@ -358,36 +402,10 @@ static void psb_get_core_freq(struct drm_device *dev) } } -#define FB_REG06 0xD0810600 -#define FB_TOPAZ_DISABLE BIT0 -#define FB_MIPI_DISABLE BIT11 -#define FB_REG09 0xD0810900 -#define FB_SKU_MASK (BIT12|BIT13|BIT14) -#define FB_SKU_SHIFT 12 -#define FB_SKU_100 0 -#define FB_SKU_100L 1 -#define FB_SKU_83 2 - -bool mid_get_pci_revID(struct drm_psb_private *dev_priv) -{ - uint32_t platform_rev_id = 0; - struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); - - /*get the revison ID, B0:D2:F0;0x08 */ - pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); - dev_priv->platform_rev_id = (uint8_t) platform_rev_id; - pci_dev_put(pci_gfx_root); - PSB_DEBUG_ENTRY("platform_rev_id is %x\n", - dev_priv->platform_rev_id); - - return true; -} - static int psb_do_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private; - struct ttm_bo_device *bdev = &dev_priv->bdev; struct psb_gtt *pg = dev_priv->pg; uint32_t stolen_gtt; @@ -396,16 +414,6 @@ static int psb_do_init(struct drm_device *dev) int ret = -ENOMEM; - - /* - * Initialize sequence numbers for the different command - * submission mechanisms. - */ - - dev_priv->sequence[PSB_ENGINE_2D] = 0; - dev_priv->sequence[PSB_ENGINE_VIDEO] = 0; - dev_priv->sequence[LNC_ENGINE_ENCODE] = 0; - if (pg->mmu_gatt_start & 0x0FFFFFFF) { DRM_ERROR("Gatt must be 256M aligned. This is a bug.\n"); ret = -EINVAL; @@ -445,6 +453,7 @@ static int psb_do_init(struct drm_device *dev) pg->gatt_pages : PSB_TT_PRIV0_PLIMIT; tt_start = dev_priv->gatt_free_offset - pg->mmu_gatt_start; tt_pages -= tt_start >> PAGE_SHIFT; + /* FIXME: can we kill ta_mem_size ? */ dev_priv->sizes.ta_mem_size = 0; PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); @@ -453,30 +462,10 @@ static int psb_do_init(struct drm_device *dev) PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK, PSB_CR_BIF_CTRL); psb_spank(dev_priv); - - PSB_WSGX32(pg->mmu_gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); - - /* TT region managed by TTM. */ - if (!ttm_bo_init_mm(bdev, TTM_PL_TT, - pg->gatt_pages - - (pg->ci_start >> PAGE_SHIFT) - - ((dev_priv->ci_region_size + dev_priv->rar_region_size) - >> PAGE_SHIFT))) { - - dev_priv->have_tt = 1; - dev_priv->sizes.tt_size = - (tt_pages << PAGE_SHIFT) / (1024 * 1024) / 2; - } - if (!ttm_bo_init_mm(bdev, - DRM_PSB_MEM_MMU, - PSB_MEM_TT_START >> PAGE_SHIFT)) { - dev_priv->have_mem_mmu = 1; - dev_priv->sizes.mmu_size = - PSB_MEM_TT_START / (1024*1024); - } + /* mmu_gatt ?? */ + PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); - PSB_DEBUG_INIT("Init MSVDX\n"); return 0; out_err: psb_do_takedown(dev); @@ -510,39 +499,19 @@ static int psb_driver_unload(struct drm_device *dev) down_read(&pg->sem); psb_mmu_remove_pfn_sequence( - psb_mmu_get_default_pd - (dev_priv->mmu), - pg->mmu_gatt_start, - pg->vram_stolen_size >> PAGE_SHIFT); - if (pg->ci_stolen_size != 0) - psb_mmu_remove_pfn_sequence( - psb_mmu_get_default_pd - (dev_priv->mmu), - pg->ci_start, - pg->ci_stolen_size >> PAGE_SHIFT); - if (pg->rar_stolen_size != 0) - psb_mmu_remove_pfn_sequence( - psb_mmu_get_default_pd - (dev_priv->mmu), - pg->rar_start, - pg->rar_stolen_size >> PAGE_SHIFT); + psb_mmu_get_default_pd + (dev_priv->mmu), + pg->mmu_gatt_start, + dev_priv->vram_stolen_size >> PAGE_SHIFT); up_read(&pg->sem); psb_mmu_driver_takedown(dev_priv->mmu); dev_priv->mmu = NULL; } - psb_gtt_takedown(dev_priv->pg, 1); + psb_gtt_takedown(dev); if (dev_priv->scratch_page) { __free_page(dev_priv->scratch_page); dev_priv->scratch_page = NULL; } - if (dev_priv->has_bo_device) { - ttm_bo_device_release(&dev_priv->bdev); - dev_priv->has_bo_device = 0; - } - if (dev_priv->has_fence_device) { - ttm_fence_device_release(&dev_priv->fdev); - dev_priv->has_fence_device = 0; - } if (dev_priv->vdc_reg) { iounmap(dev_priv->vdc_reg); dev_priv->vdc_reg = NULL; @@ -552,12 +521,6 @@ static int psb_driver_unload(struct drm_device *dev) dev_priv->sgx_reg = NULL; } - if (dev_priv->tdev) - ttm_object_device_release(&dev_priv->tdev); - - if (dev_priv->has_global) - psb_ttm_global_release(dev_priv); - kfree(dev_priv); dev->dev_private = NULL; @@ -565,7 +528,7 @@ static int psb_driver_unload(struct drm_device *dev) psb_intel_destroy_bios(dev); } - ospm_power_uninit(); + gma_power_uninit(dev); return 0; } @@ -574,49 +537,27 @@ static int psb_driver_unload(struct drm_device *dev) static int psb_driver_load(struct drm_device *dev, unsigned long chipset) { struct drm_psb_private *dev_priv; - struct ttm_bo_device *bdev; unsigned long resource_start; struct psb_gtt *pg; unsigned long irqflags; int ret = -ENOMEM; uint32_t tt_pages; + struct drm_connector *connector; + struct psb_intel_output *psb_intel_output; dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); if (dev_priv == NULL) return -ENOMEM; - INIT_LIST_HEAD(&dev_priv->video_ctx); - - dev_priv->num_pipe = 2; + if (IS_MRST(dev)) + dev_priv->num_pipe = 1; + else + dev_priv->num_pipe = 2; dev_priv->dev = dev; - bdev = &dev_priv->bdev; - - ret = psb_ttm_global_init(dev_priv); - if (unlikely(ret != 0)) - goto out_err; - dev_priv->has_global = 1; - - dev_priv->tdev = ttm_object_device_init - (dev_priv->mem_global_ref.object, PSB_OBJECT_HASH_ORDER); - if (unlikely(dev_priv->tdev == NULL)) - goto out_err; - - mutex_init(&dev_priv->temp_mem); - mutex_init(&dev_priv->cmdbuf_mutex); - mutex_init(&dev_priv->reset_mutex); - INIT_LIST_HEAD(&dev_priv->context.validate_list); - INIT_LIST_HEAD(&dev_priv->context.kern_validate_list); - -/* mutex_init(&dev_priv->dsr_mutex); */ - - spin_lock_init(&dev_priv->reloc_lock); - - DRM_INIT_WAITQUEUE(&dev_priv->rel_mapped_queue); dev->dev_private = (void *) dev_priv; dev_priv->chipset = chipset; - psb_set_uopt(&dev_priv->uopt); PSB_DEBUG_INIT("Mapping MMIO\n"); resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE); @@ -626,34 +567,28 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) if (!dev_priv->vdc_reg) goto out_err; - dev_priv->sgx_reg = ioremap(resource_start + PSB_SGX_OFFSET, + if (IS_MRST(dev)) + dev_priv->sgx_reg = ioremap(resource_start + MRST_SGX_OFFSET, + PSB_SGX_SIZE); + else + dev_priv->sgx_reg = ioremap(resource_start + PSB_SGX_OFFSET, PSB_SGX_SIZE); if (!dev_priv->sgx_reg) goto out_err; - psb_get_core_freq(dev); - psb_intel_opregion_init(dev); - psb_intel_init_bios(dev); - - PSB_DEBUG_INIT("Init TTM fence and BO driver\n"); + if (IS_MRST(dev)) { + mrst_get_fuse_settings(dev); + mrst_get_vbt_data(dev_priv); + mid_get_pci_revID(dev_priv); + } else { + psb_get_core_freq(dev); + psb_intel_opregion_init(dev); + psb_intel_init_bios(dev); + } /* Init OSPM support */ - ospm_power_init(dev); - - ret = psb_ttm_fence_device_init(&dev_priv->fdev); - if (unlikely(ret != 0)) - goto out_err; - - dev_priv->has_fence_device = 1; - ret = ttm_bo_device_init(bdev, - dev_priv->bo_global_ref.ref.object, - &psb_ttm_bo_driver, - DRM_PSB_FILE_PAGE_OFFSET, false); - if (unlikely(ret != 0)) - goto out_err; - dev_priv->has_bo_device = 1; - ttm_lock_init(&dev_priv->ttm_lock); + gma_power_init(dev); ret = -ENOMEM; @@ -663,15 +598,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) set_pages_uc(dev_priv->scratch_page, 1); - dev_priv->pg = psb_gtt_alloc(dev); - if (!dev_priv->pg) - goto out_err; - - ret = psb_gtt_init(dev_priv->pg, 0); - if (ret) - goto out_err; - - ret = psb_gtt_mm_init(dev_priv->pg); + ret = psb_gtt_init(dev, 0); if (ret) goto out_err; @@ -686,40 +613,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ? (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT; - /* CI/RAR use the lower half of TT. */ - pg->ci_start = (tt_pages / 2) << PAGE_SHIFT; - pg->rar_start = pg->ci_start + pg->ci_stolen_size; - - - /* - * Make MSVDX/TOPAZ MMU aware of the CI stolen memory area. - */ - if (dev_priv->pg->ci_stolen_size != 0) { - down_read(&pg->sem); - ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd - (dev_priv->mmu), - dev_priv->ci_region_start >> PAGE_SHIFT, - pg->mmu_gatt_start + pg->ci_start, - pg->ci_stolen_size >> PAGE_SHIFT, 0); - up_read(&pg->sem); - if (ret) - goto out_err; - } - - /* - * Make MSVDX/TOPAZ MMU aware of the rar stolen memory area. - */ - if (dev_priv->pg->rar_stolen_size != 0) { - down_read(&pg->sem); - ret = psb_mmu_insert_pfn_sequence( - psb_mmu_get_default_pd(dev_priv->mmu), - dev_priv->rar_region_start >> PAGE_SHIFT, - pg->mmu_gatt_start + pg->rar_start, - pg->rar_stolen_size >> PAGE_SHIFT, 0); - up_read(&pg->sem); - if (ret) - goto out_err; - } dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0); if (!dev_priv->pf_pd) @@ -728,14 +621,13 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0); psb_mmu_set_pd_context(dev_priv->pf_pd, 1); - spin_lock_init(&dev_priv->sequence_lock); - - PSB_DEBUG_INIT("Begin to init MSVDX/Topaz\n"); - ret = psb_do_init(dev); if (ret) return ret; + PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE); + PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE); + /* igd_opregion_init(&dev_priv->opregion_dev); */ acpi_video_register(); if (dev_priv->lid_state) @@ -773,7 +665,18 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) drm_kms_helper_poll_init(dev); } - ret = psb_backlight_init(dev); + /* Only add backlight support if we have LVDS output */ + list_for_each_entry(connector, &dev->mode_config.connector_list, + head) { + psb_intel_output = to_psb_intel_output(connector); + + switch (psb_intel_output->type) { + case INTEL_OUTPUT_LVDS: + ret = psb_backlight_init(dev); + break; + } + } + if (ret) return ret; #if 0 @@ -783,11 +686,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) #endif /*Intel drm driver load is done, continue doing pvr load*/ DRM_DEBUG("Pvr driver load\n"); - -/* if (PVRCore_Init() < 0) - goto out_err; */ -/* if (MRSTLFBInit(dev) < 0) - goto out_err;*/ return 0; out_err: psb_driver_unload(dev); @@ -800,45 +698,6 @@ int psb_driver_device_is_agp(struct drm_device *dev) } -static int psb_vt_leave_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_private *dev_priv = psb_priv(dev); - struct ttm_bo_device *bdev = &dev_priv->bdev; - struct ttm_mem_type_manager *man; - int ret; - - ret = ttm_vt_lock(&dev_priv->ttm_lock, 1, - psb_fpriv(file_priv)->tfile); - if (unlikely(ret != 0)) - return ret; - - ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_TT); - if (unlikely(ret != 0)) - goto out_unlock; - - man = &bdev->man[TTM_PL_TT]; - -#if 0 /* What to do with this ? */ - if (unlikely(!drm_mm_clean(&man->manager))) - DRM_INFO("Warning: GATT was not clean after VT switch.\n"); -#endif - - ttm_bo_swapout_all(&dev_priv->bdev); - - return 0; -out_unlock: - (void) ttm_vt_unlock(&dev_priv->ttm_lock); - return ret; -} - -static int psb_vt_enter_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_private *dev_priv = psb_priv(dev); - return ttm_vt_unlock(&dev_priv->ttm_lock); -} - static int psb_sizes_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -945,13 +804,12 @@ static int psb_dpst_ioctl(struct drm_device *dev, void *data, uint32_t y; uint32_t reg; - if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) - return 0; + if (!gma_power_begin(dev, 0)) + return -EIO; reg = PSB_RVDC32(PIPEASRC); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); /* horizontal is the left 16 bits */ x = reg >> 16; @@ -1028,13 +886,12 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, drm_fb = obj_to_fb(obj); psb_fb = to_psb_fb(drm_fb); - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { - REG_WRITE(DSPASURF, psb_fb->offset); + if (gma_power_begin(dev, 0)) { + REG_WRITE(DSPASURF, psb_fb->gtt->offset); REG_READ(DSPASURF); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else { - dev_priv->saveDSPASURF = psb_fb->offset; + dev_priv->saveDSPASURF = psb_fb->gtt->offset; } return 0; @@ -1107,8 +964,8 @@ static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, struct drm_psb_private *dev_priv = psb_priv(dev); struct drm_psb_stolen_memory_arg *arg = data; - arg->base = dev_priv->pg->stolen_base; - arg->size = dev_priv->pg->vram_stolen_size; + arg->base = dev_priv->stolen_base; + arg->size = dev_priv->vram_stolen_size; return 0; } @@ -1118,11 +975,10 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, { struct drm_psb_private *dev_priv = psb_priv(dev); struct drm_psb_register_rw_arg *arg = data; - UHBUsage usage = - arg->b_force_hw_on ? OSPM_UHB_FORCE_POWER_ON : OSPM_UHB_ONLY_IF_ON; + bool usage = arg->b_force_hw_on ? true : false; if (arg->display_write_mask != 0) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { + if (gma_power_begin(dev, usage)) { if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) PSB_WVDC32(arg->display.pfit_controls, PFIT_CONTROL); @@ -1147,7 +1003,7 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, if (arg->display_write_mask & REGRWBITS_VTOTAL_B) PSB_WVDC32(arg->display.vtotal_b, VTOTAL_B); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else { if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) dev_priv->savePFIT_CONTROL = @@ -1172,7 +1028,7 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, } if (arg->display_read_mask != 0) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { + if (gma_power_begin(dev, usage)) { if (arg->display_read_mask & REGRWBITS_PFIT_CONTROLS) arg->display.pfit_controls = @@ -1193,7 +1049,7 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A); if (arg->display_read_mask & REGRWBITS_VTOTAL_B) arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else { if (arg->display_read_mask & REGRWBITS_PFIT_CONTROLS) @@ -1219,7 +1075,7 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, } if (arg->overlay_write_mask != 0) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { + if (gma_power_begin(dev, usage)) { if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5); PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4); @@ -1270,7 +1126,7 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, } } } - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else { if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5; @@ -1296,7 +1152,7 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, } if (arg->overlay_read_mask != 0) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { + if (gma_power_begin(dev, usage)) { if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5); arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4); @@ -1317,7 +1173,7 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, arg->overlay.OVADD = PSB_RVDC32(OV_OVADD); if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD) arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else { if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5; @@ -1343,7 +1199,7 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, } if (arg->sprite_enable_mask != 0) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { + if (gma_power_begin(dev, usage)) { PSB_WVDC32(0x1F3E, DSPARB); PSB_WVDC32(arg->sprite.dspa_control | PSB_RVDC32(DSPACNTR), DSPACNTR); @@ -1358,22 +1214,22 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE); PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); PSB_RVDC32(DSPCSURF); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } } if (arg->sprite_disable_mask != 0) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { + if (gma_power_begin(dev, usage)) { PSB_WVDC32(0x3F3E, DSPARB); PSB_WVDC32(0x0, DSPCCNTR); PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); PSB_RVDC32(DSPCSURF); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } } if (arg->subpicture_enable_mask != 0) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { + if (gma_power_begin(dev, usage)) { uint32_t temp; if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) { temp = PSB_RVDC32(DSPACNTR); @@ -1417,12 +1273,12 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, PSB_WVDC32(temp, DSPCSURF); PSB_RVDC32(DSPCSURF); } - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } } if (arg->subpicture_disable_mask != 0) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) { + if (gma_power_begin(dev, usage)) { uint32_t temp; if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) { temp = PSB_RVDC32(DSPACNTR); @@ -1463,42 +1319,20 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data, PSB_WVDC32(temp, DSPCSURF); PSB_RVDC32(DSPCSURF); } - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } } return 0; } -/* always available as we are SIGIO'd */ -static unsigned int psb_poll(struct file *filp, - struct poll_table_struct *wait) -{ - return POLLIN | POLLRDNORM; -} - -/* Not sure what we will need yet - in the PVR driver this disappears into - a tangle of abstracted handlers and per process crap */ - -struct psb_priv { - int dummy; -}; - static int psb_driver_open(struct drm_device *dev, struct drm_file *priv) { - struct psb_priv *psb = kzalloc(sizeof(struct psb_priv), GFP_KERNEL); - if (psb == NULL) - return -ENOMEM; - priv->driver_priv = psb; - DRM_DEBUG("\n"); - /*return PVRSRVOpen(dev, priv);*/ return 0; } static void psb_driver_close(struct drm_device *dev, struct drm_file *priv) { - kfree(priv->driver_priv); - priv->driver_priv = NULL; } static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, @@ -1517,30 +1351,9 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, pm_runtime_allow(&dev->pdev->dev); dev_priv->rpm_enabled = 1; } - /* - * The driver private ioctls and TTM ioctls should be - * thread-safe. - */ - - if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) - && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) { - struct drm_ioctl_desc *ioctl = - &psb_ioctls[nr - DRM_COMMAND_BASE]; - - if (unlikely(ioctl->cmd != cmd)) { - DRM_ERROR( - "Invalid drm cmnd %d ioctl->cmd %x, cmd %x\n", - nr - DRM_COMMAND_BASE, ioctl->cmd, cmd); - return -EINVAL; - } - - return drm_ioctl(filp, cmd, arg); - } - /* - * Not all old drm ioctls are thread-safe. - */ - return drm_ioctl(filp, cmd, arg); + + /* FIXME: do we need to wrap the other side of this */ } @@ -1557,16 +1370,21 @@ static void psb_remove(struct pci_dev *pdev) drm_put_dev(dev); } - static const struct dev_pm_ops psb_pm_ops = { .runtime_suspend = psb_runtime_suspend, .runtime_resume = psb_runtime_resume, .runtime_idle = psb_runtime_idle, }; +static struct vm_operations_struct psb_gem_vm_ops = { + .fault = psb_gem_fault, + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + static struct drm_driver driver = { .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \ - DRIVER_IRQ_VBL | DRIVER_MODESET, + DRIVER_IRQ_VBL | DRIVER_MODESET| DRIVER_GEM , .load = psb_driver_load, .unload = psb_driver_unload, @@ -1580,27 +1398,29 @@ static struct drm_driver driver = { .enable_vblank = psb_enable_vblank, .disable_vblank = psb_disable_vblank, .get_vblank_counter = psb_get_vblank_counter, - .firstopen = NULL, .lastclose = psb_lastclose, .open = psb_driver_open, - .postclose = psb_driver_close, -#if 0 /* ACFIXME */ - .get_map_ofs = drm_core_get_map_ofs, - .get_reg_ofs = drm_core_get_reg_ofs, - .proc_init = psb_proc_init, - .proc_cleanup = psb_proc_cleanup, -#endif .preclose = psb_driver_preclose, + .postclose = psb_driver_close, + .reclaim_buffers = drm_core_reclaim_buffers, + + .gem_init_object = psb_gem_init_object, + .gem_free_object = psb_gem_free_object, + .gem_vm_ops = &psb_gem_vm_ops, + .dumb_create = psb_gem_dumb_create, + .dumb_map_offset = psb_gem_dumb_map_gtt, + .dumb_destroy = psb_gem_dumb_destroy, + .fops = { .owner = THIS_MODULE, - .open = psb_open, - .release = psb_release, + .open = drm_open, + .release = drm_release, .unlocked_ioctl = psb_unlocked_ioctl, - .mmap = psb_mmap, - .poll = psb_poll, + .mmap = drm_gem_mmap, + .poll = drm_poll, .fasync = drm_fasync, .read = drm_read, - }, + }, .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = PSB_DRM_DRIVER_DATE, @@ -1612,8 +1432,8 @@ static struct drm_driver driver = { static struct pci_driver psb_pci_driver = { .name = DRIVER_NAME, .id_table = pciidlist, - .resume = ospm_power_resume, - .suspend = ospm_power_suspend, + .resume = gma_power_resume, + .suspend = gma_power_suspend, .probe = psb_probe, .remove = psb_remove, #ifdef CONFIG_PM diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h index 29a36056d664..e19a45478757 100644 --- a/drivers/staging/gma500/psb_drv.h +++ b/drivers/staging/gma500/psb_drv.h @@ -21,6 +21,7 @@ #define _PSB_DRV_H_ #include <linux/version.h> +#include <linux/kref.h> #include <drm/drmP.h> #include "drm_global.h" @@ -29,22 +30,19 @@ #include "psb_intel_drv.h" #include "psb_gtt.h" #include "psb_powermgmt.h" -#include "ttm/ttm_object.h" -#include "psb_ttm_fence_driver.h" -#include "psb_ttm_userobj_api.h" -#include "ttm/ttm_bo_driver.h" -#include "ttm/ttm_lock.h" +#include "mrst.h" /*Append new drm mode definition here, align with libdrm definition*/ #define DRM_MODE_SCALE_NO_SCALE 2 -extern struct ttm_bo_driver psb_ttm_bo_driver; - enum { CHIP_PSB_8108 = 0, CHIP_PSB_8109 = 1, + CHIP_MRST_4100 = 2, }; +#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100) + /* *Hardware bugfixes */ @@ -52,10 +50,6 @@ enum { #define DRIVER_NAME "pvrsrvkm" #define DRIVER_DESC "drm driver for the Intel GMA500" #define DRIVER_AUTHOR "Intel Corporation" -#define OSPM_PROC_ENTRY "ospm" -#define RTPM_PROC_ENTRY "rtpm" -#define BLC_PROC_ENTRY "mrst_blc" -#define DISPLAY_PROC_ENTRY "display_status" #define PSB_DRM_DRIVER_DATE "2009-03-10" #define PSB_DRM_DRIVER_MAJOR 8 @@ -92,26 +86,10 @@ enum { #define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT) #define PSB_NUM_VALIDATE_BUFFERS 2048 -#define PSB_MEM_MMU_START 0x00000000 -#define PSB_MEM_TT_START 0xE0000000 - -#define PSB_GL3_CACHE_CTL 0x2100 -#define PSB_GL3_CACHE_STAT 0x2108 - /* *Flags for external memory type field. */ -#define MRST_MSVDX_OFFSET 0x90000 /*MSVDX Base offset */ -#define PSB_MSVDX_OFFSET 0x50000 /*MSVDX Base offset */ -/* MSVDX MMIO region is 0x50000 - 0x57fff ==> 32KB */ -#define PSB_MSVDX_SIZE 0x10000 - -#define LNC_TOPAZ_OFFSET 0xA0000 -#define PNW_TOPAZ_OFFSET 0xC0000 -#define PNW_GL3_OFFSET 0xB0000 -#define LNC_TOPAZ_SIZE 0x10000 -#define PNW_TOPAZ_SIZE 0x30000 /* PNW VXE285 has two cores */ #define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */ #define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */ #define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */ @@ -223,20 +201,6 @@ enum { #define MDFLD_PNW_B0 0x04 #define MDFLD_PNW_C0 0x08 -#define MDFLD_DSR_2D_3D_0 BIT0 -#define MDFLD_DSR_2D_3D_2 BIT1 -#define MDFLD_DSR_CURSOR_0 BIT2 -#define MDFLD_DSR_CURSOR_2 BIT3 -#define MDFLD_DSR_OVERLAY_0 BIT4 -#define MDFLD_DSR_OVERLAY_2 BIT5 -#define MDFLD_DSR_MIPI_CONTROL BIT6 -#define MDFLD_DSR_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2) - -#define MDFLD_DSR_RR 45 -#define MDFLD_DPU_ENABLE BIT31 -#define MDFLD_DSR_FULLSCREEN BIT30 -#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR) - #define PSB_PWR_STATE_ON 1 #define PSB_PWR_STATE_OFF 2 @@ -250,9 +214,6 @@ enum { #define PSB_PCIx_MSI_ADDR_LOC 0x94 #define PSB_PCIx_MSI_DATA_LOC 0x98 -#define MDFLD_PLANE_MAX_WIDTH 2048 -#define MDFLD_PLANE_MAX_HEIGHT 2048 - struct opregion_header; struct opregion_acpi; struct opregion_swsci; @@ -266,142 +227,55 @@ struct psb_intel_opregion { int enabled; }; -/* - *User options. - */ - -struct drm_psb_uopt { - int pad; /*keep it here in case we use it in future*/ -}; - -/** - *struct psb_context - * - *@buffers: array of pre-allocated validate buffers. - *@used_buffers: number of buffers in @buffers array currently in use. - *@validate_buffer: buffers validated from user-space. - *@kern_validate_buffers : buffers validated from kernel-space. - *@fence_flags : Fence flags to be used for fence creation. - * - *This structure is used during execbuf validation. - */ - -struct psb_context { - struct psb_validate_buffer *buffers; - uint32_t used_buffers; - struct list_head validate_list; - struct list_head kern_validate_list; - uint32_t fence_types; - uint32_t val_seq; -}; - -struct psb_validate_buffer; - -/* Currently defined profiles */ -enum VAProfile { - VAProfileMPEG2Simple = 0, - VAProfileMPEG2Main = 1, - VAProfileMPEG4Simple = 2, - VAProfileMPEG4AdvancedSimple = 3, - VAProfileMPEG4Main = 4, - VAProfileH264Baseline = 5, - VAProfileH264Main = 6, - VAProfileH264High = 7, - VAProfileVC1Simple = 8, - VAProfileVC1Main = 9, - VAProfileVC1Advanced = 10, - VAProfileH263Baseline = 11, - VAProfileJPEGBaseline = 12, - VAProfileH264ConstrainedBaseline = 13 -}; - -/* Currently defined entrypoints */ -enum VAEntrypoint { - VAEntrypointVLD = 1, - VAEntrypointIZZ = 2, - VAEntrypointIDCT = 3, - VAEntrypointMoComp = 4, - VAEntrypointDeblocking = 5, - VAEntrypointEncSlice = 6, /* slice level encode */ - VAEntrypointEncPicture = 7 /* pictuer encode, JPEG, etc */ -}; - - -struct psb_video_ctx { - struct list_head head; - struct file *filp; /* DRM device file pointer */ - int ctx_type; /* profile<<8|entrypoint */ - /* todo: more context specific data for multi-context support */ -}; - -#define MODE_SETTING_IN_CRTC 0x1 -#define MODE_SETTING_IN_ENCODER 0x2 -#define MODE_SETTING_ON_GOING 0x3 -#define MODE_SETTING_IN_DSR 0x4 -#define MODE_SETTING_ENCODER_DONE 0x8 -#define GCT_R10_HEADER_SIZE 16 -#define GCT_R10_DISPLAY_DESC_SIZE 28 struct drm_psb_private { - /* - * DSI info. - */ - void * dbi_dsr_info; - void * dsi_configs[2]; - - /* - *TTM Glue. - */ - - struct drm_global_reference mem_global_ref; - struct ttm_bo_global_ref bo_global_ref; - int has_global; - struct drm_device *dev; - struct ttm_object_device *tdev; - struct ttm_fence_device fdev; - struct ttm_bo_device bdev; - struct ttm_lock ttm_lock; - struct vm_operations_struct *ttm_vm_ops; - int has_fence_device; - int has_bo_device; unsigned long chipset; - struct drm_psb_uopt uopt; - struct psb_gtt *pg; - /*GTT Memory manager*/ + /* GTT Memory manager */ struct psb_gtt_mm *gtt_mm; - struct page *scratch_page; - uint32_t sequence[PSB_NUM_ENGINES]; - uint32_t last_sequence[PSB_NUM_ENGINES]; - uint32_t last_submitted_seq[PSB_NUM_ENGINES]; + u32 *gtt_map; + uint32_t stolen_base; + void *vram_addr; + unsigned long vram_stolen_size; + int gtt_initialized; + u16 gmch_ctrl; /* Saved GTT setup */ + u32 pge_ctl; + + struct mutex gtt_mutex; + struct resource *gtt_mem; /* Our PCI resource */ struct psb_mmu_driver *mmu; struct psb_mmu_pd *pf_pd; + /* + * Register base + */ + uint8_t *sgx_reg; uint8_t *vdc_reg; uint32_t gatt_free_offset; - /* IMG video context */ - struct list_head video_ctx; - - - /* - *Fencing / irq. + * Fencing / irq. */ uint32_t vdc_irq_mask; uint32_t pipestat[PSB_NUM_PIPE]; - bool vblanksEnabledForFlips; spinlock_t irqmask_lock; - spinlock_t sequence_lock; + + /* + * Power + */ + + bool suspended; + bool display_power; + int display_count; /* *Modesetting @@ -413,40 +287,9 @@ struct drm_psb_private { uint32_t num_pipe; /* - * CI share buffer - */ - unsigned int ci_region_start; - unsigned int ci_region_size; - - /* - * RAR share buffer; - */ - unsigned int rar_region_start; - unsigned int rar_region_size; - - /* *Memory managers */ - int have_camera; - int have_rar; - int have_tt; - int have_mem_mmu; - struct mutex temp_mem; - - /* - *Relocation buffer mapping. - */ - - spinlock_t reloc_lock; - unsigned int rel_mapped_pages; - wait_queue_head_t rel_mapped_queue; - - /* - *SAREA - */ - struct drm_psb_sarea *sarea_priv; - /* *OSPM info */ @@ -458,7 +301,8 @@ struct drm_psb_private { struct drm_psb_sizes_arg sizes; - uint32_t fuse_reg_value; + u32 fuse_reg_value; + u32 video_device_fuse; /* pci revision id for B0:D2:F0 */ uint8_t platform_rev_id; @@ -483,6 +327,7 @@ struct drm_psb_private { unsigned int lvds_use_ssc:1; int lvds_ssc_freq; bool is_lvds_on; + bool is_mipi_on; unsigned int core_freq; uint32_t iLVDS_enable; @@ -490,6 +335,20 @@ struct drm_psb_private { /*runtime PM state*/ int rpm_enabled; + /* Moorestown specific */ + struct mrst_vbt vbt_data; + struct mrst_gct_data gct_data; + + /* Moorestown pipe config register value cache */ + uint32_t pipeconf; + uint32_t pipeconf1; + uint32_t pipeconf2; + + /* Moorestown plane control register value cache */ + uint32_t dspcntr; + uint32_t dspcntr1; + uint32_t dspcntr2; + /* *Register state */ @@ -595,98 +454,11 @@ struct drm_psb_private { uint32_t saveOVC_OGAMC4; uint32_t saveOVC_OGAMC5; - /* - * extra MDFLD Register state - */ - uint32_t saveHDMIPHYMISCCTL; - uint32_t saveHDMIB_CONTROL; - uint32_t saveDSPCCNTR; - uint32_t savePIPECCONF; - uint32_t savePIPECSRC; - uint32_t saveHTOTAL_C; - uint32_t saveHBLANK_C; - uint32_t saveHSYNC_C; - uint32_t saveVTOTAL_C; - uint32_t saveVBLANK_C; - uint32_t saveVSYNC_C; - uint32_t saveDSPCSTRIDE; - uint32_t saveDSPCSIZE; - uint32_t saveDSPCPOS; - uint32_t saveDSPCSURF; - uint32_t saveDSPCLINOFF; - uint32_t saveDSPCTILEOFF; - uint32_t saveDSPCCURSOR_CTRL; - uint32_t saveDSPCCURSOR_BASE; - uint32_t saveDSPCCURSOR_POS; - uint32_t save_palette_c[256]; - uint32_t saveOV_OVADD_C; - uint32_t saveOV_OGAMC0_C; - uint32_t saveOV_OGAMC1_C; - uint32_t saveOV_OGAMC2_C; - uint32_t saveOV_OGAMC3_C; - uint32_t saveOV_OGAMC4_C; - uint32_t saveOV_OGAMC5_C; - - /* DSI reg save */ - uint32_t saveDEVICE_READY_REG; - uint32_t saveINTR_EN_REG; - uint32_t saveDSI_FUNC_PRG_REG; - uint32_t saveHS_TX_TIMEOUT_REG; - uint32_t saveLP_RX_TIMEOUT_REG; - uint32_t saveTURN_AROUND_TIMEOUT_REG; - uint32_t saveDEVICE_RESET_REG; - uint32_t saveDPI_RESOLUTION_REG; - uint32_t saveHORIZ_SYNC_PAD_COUNT_REG; - uint32_t saveHORIZ_BACK_PORCH_COUNT_REG; - uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG; - uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG; - uint32_t saveVERT_SYNC_PAD_COUNT_REG; - uint32_t saveVERT_BACK_PORCH_COUNT_REG; - uint32_t saveVERT_FRONT_PORCH_COUNT_REG; - uint32_t saveHIGH_LOW_SWITCH_COUNT_REG; - uint32_t saveINIT_COUNT_REG; - uint32_t saveMAX_RET_PAK_REG; - uint32_t saveVIDEO_FMT_REG; - uint32_t saveEOT_DISABLE_REG; - uint32_t saveLP_BYTECLK_REG; - uint32_t saveHS_LS_DBI_ENABLE_REG; - uint32_t saveTXCLKESC_REG; - uint32_t saveDPHY_PARAM_REG; - uint32_t saveMIPI_CONTROL_REG; - uint32_t saveMIPI; - uint32_t saveMIPI_C; - void (*init_drvIC)(struct drm_device *dev); - void (*dsi_prePowerState)(struct drm_device *dev); - void (*dsi_postPowerState)(struct drm_device *dev); - - /* DPST Register Save */ - uint32_t saveHISTOGRAM_INT_CONTROL_REG; - uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG; - uint32_t savePWM_CONTROL_LOGIC; - /* MSI reg save */ - uint32_t msi_addr; uint32_t msi_data; /* - *Scheduling. - */ - - struct mutex reset_mutex; - struct mutex cmdbuf_mutex; - /*uint32_t ta_mem_pages; - struct psb_ta_mem *ta_mem; - int force_ta_mem_load;*/ - atomic_t val_seq; - - /* - *TODO: change this to be per drm-context. - */ - - struct psb_context context; - - /* * LID-Switch */ spinlock_t lid_lock; @@ -699,8 +471,6 @@ struct drm_psb_private { *Watchdog */ - int timer_available; - uint32_t apm_reg; uint16_t apm_base; @@ -716,73 +486,17 @@ struct drm_psb_private { }; -struct psb_file_data { /* TODO: Audit this, remove the indirection and set - it up properly in open/postclose ACFIXME */ - void *priv; -}; - -struct psb_fpriv { - struct ttm_object_file *tfile; -}; - struct psb_mmu_driver; extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int); extern int drm_pick_crtcs(struct drm_device *dev); -static inline struct psb_fpriv *psb_fpriv(struct drm_file *file_priv) -{ - struct psb_file_data *pvr_file_priv - = (struct psb_file_data *)file_priv->driver_priv; - return (struct psb_fpriv *) pvr_file_priv->priv; -} - static inline struct drm_psb_private *psb_priv(struct drm_device *dev) { return (struct drm_psb_private *) dev->dev_private; } /* - *TTM glue. psb_ttm_glue.c - */ - -extern int psb_open(struct inode *inode, struct file *filp); -extern int psb_release(struct inode *inode, struct file *filp); -extern int psb_mmap(struct file *filp, struct vm_area_struct *vma); - -extern int psb_fence_signaled_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_verify_access(struct ttm_buffer_object *bo, - struct file *filp); -extern ssize_t psb_ttm_read(struct file *filp, char __user *buf, - size_t count, loff_t *f_pos); -extern ssize_t psb_ttm_write(struct file *filp, const char __user *buf, - size_t count, loff_t *f_pos); -extern int psb_fence_finish_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_fence_unref_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_pl_waitidle_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_pl_setstatus_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_pl_synccpu_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_pl_unref_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_pl_reference_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_pl_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_pl_ub_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_extension_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_ttm_global_init(struct drm_psb_private *dev_priv); -extern void psb_ttm_global_release(struct drm_psb_private *dev_priv); -extern int psb_getpageaddrs_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -/* *MMU stuff. */ @@ -825,31 +539,6 @@ extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd, uint32_t desired_tile_stride, uint32_t hw_tile_stride); /* - *psb_sgx.c - */ - - - -extern int psb_cmdbuf_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_reg_submit(struct drm_psb_private *dev_priv, - uint32_t *regs, unsigned int cmds); - - -extern void psb_fence_or_sync(struct drm_file *file_priv, - uint32_t engine, - uint32_t fence_types, - uint32_t fence_flags, - struct list_head *list, - struct psb_ttm_fence_rep *fence_arg, - struct ttm_fence_object **fence_p); -extern int psb_validate_kernel_buffer(struct psb_context *context, - struct ttm_buffer_object *bo, - uint32_t fence_class, - uint64_t set_flags, - uint64_t clr_flags); - -/* *psb_irq.c */ @@ -859,8 +548,6 @@ extern int psb_irq_disable_dpst(struct drm_device *dev); extern void psb_irq_preinstall(struct drm_device *dev); extern int psb_irq_postinstall(struct drm_device *dev); extern void psb_irq_uninstall(struct drm_device *dev); -extern void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands); -extern int psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands); extern void psb_irq_turn_on_dpst(struct drm_device *dev); extern void psb_irq_turn_off_dpst(struct drm_device *dev); @@ -878,29 +565,6 @@ psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc); /* - *psb_fence.c - */ - -extern void psb_fence_handler(struct drm_device *dev, uint32_t class); - -extern int psb_fence_emit_sequence(struct ttm_fence_device *fdev, - uint32_t fence_class, - uint32_t flags, uint32_t *sequence, - unsigned long *timeout_jiffies); -extern void psb_fence_error(struct drm_device *dev, - uint32_t class, - uint32_t sequence, uint32_t type, int error); -extern int psb_ttm_fence_device_init(struct ttm_fence_device *fdev); - -/* MSVDX/Topaz stuff */ -extern int psb_remove_videoctx(struct drm_psb_private *dev_priv, struct file *filp); - -extern int lnc_video_frameskip(struct drm_device *dev, - uint64_t user_pointer); -extern int lnc_video_getparam(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* * psb_opregion.c */ extern int psb_intel_opregion_init(struct drm_device *dev); @@ -930,6 +594,9 @@ extern int psbfb_sync(struct fb_info *info); extern void psb_spank(struct drm_psb_private *dev_priv); +extern int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, + unsigned size); + /* *psb_reset.c */ @@ -950,8 +617,36 @@ int psb_set_brightness(struct backlight_device *bd); int psb_get_brightness(struct backlight_device *bd); struct backlight_device * psb_get_backlight_device(void); +/* mrst_crtc.c */ +extern const struct drm_crtc_helper_funcs mrst_helper_funcs; + +/* mrst_lvds.c */ +extern void mrst_lvds_init(struct drm_device *dev, + struct psb_intel_mode_device *mode_dev); + +/* psb_intel_lvds.c */ +extern void psb_intel_lvds_prepare(struct drm_encoder *encoder); +extern void psb_intel_lvds_commit(struct drm_encoder *encoder); +extern const struct drm_connector_helper_funcs + psb_intel_lvds_connector_helper_funcs; +extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs; + +/* psb_gem.c */ +extern int psb_gem_init_object(struct drm_gem_object *obj); +extern void psb_gem_free_object(struct drm_gem_object *obj); +extern int psb_gem_get_aperture(struct drm_device *dev, void *data, + struct drm_file *file); +extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, + struct drm_mode_create_dumb *args); +extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, + uint32_t handle); +extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, + uint32_t handle, uint64_t *offset); +extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); + + /* - *Debug print bits setting + * Debug print bits setting */ #define PSB_D_GENERAL (1 << 0) #define PSB_D_INIT (1 << 1) @@ -975,7 +670,6 @@ struct backlight_device * psb_get_backlight_device(void); extern int drm_psb_debug; extern int drm_psb_no_fb; -extern int drm_psb_disable_vsync; extern int drm_idle_check_interval; #define PSB_DEBUG_GENERAL(_fmt, _arg...) \ diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c index f67f53b12937..084c36bbfe86 100644 --- a/drivers/staging/gma500/psb_fb.c +++ b/drivers/staging/gma500/psb_fb.c @@ -36,10 +36,7 @@ #include "psb_drv.h" #include "psb_intel_reg.h" #include "psb_intel_drv.h" -#include "psb_ttm_userobj_api.h" #include "psb_fb.h" -#include "psb_sgx.h" -#include "psb_pvr_glue.h" static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb); static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, @@ -193,8 +190,7 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) struct psb_framebuffer *psbfb = vma->vm_private_data; struct drm_device *dev = psbfb->base.dev; struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_gtt *pg = dev_priv->pg; - unsigned long phys_addr = (unsigned long)pg->stolen_base;; + unsigned long phys_addr = (unsigned long)dev_priv->stolen_base; page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; @@ -243,7 +239,6 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) char *fb_screen_base = NULL; struct drm_device *dev = psbfb->base.dev; struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_gtt *pg = dev_priv->pg; if (vma->vm_pgoff != 0) return -EINVAL; @@ -256,22 +251,48 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) fb_screen_base = (char *)info->screen_base; DRM_DEBUG("vm_pgoff 0x%lx, screen base %p vram_addr %p\n", - vma->vm_pgoff, fb_screen_base, pg->vram_addr); + vma->vm_pgoff, fb_screen_base, + dev_priv->vram_addr); - /*if using stolen memory, */ - if (fb_screen_base == pg->vram_addr) { + /* FIXME: ultimately this needs to become 'if entirely stolen memory' */ + if (1 || fb_screen_base == dev_priv->vram_addr) { vma->vm_ops = &psbfb_vm_ops; vma->vm_private_data = (void *)psbfb; vma->vm_flags |= VM_RESERVED | VM_IO | VM_MIXEDMAP | VM_DONTEXPAND; } else { - /*using IMG meminfo, can I use pvrmmap to map it?*/ - + /* GTT memory backed by kernel/user pages, needs a different + approach ? - GEM ? */ } return 0; } +static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) +{ + struct psb_fbdev *fbdev = info->par; + struct psb_framebuffer *psbfb = fbdev->pfb; + struct drm_device *dev = psbfb->base.dev; + struct drm_psb_private *dev_priv = dev->dev_private; + u32 __user *p = (u32 __user *)arg; + u32 l; + u32 buf[32]; + switch (cmd) { + case 0x12345678: + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + if (get_user(l, p)) + return -EFAULT; + if (l > 32) + return -EMSGSIZE; + if (copy_from_user(buf, p + 1, l * sizeof(u32))) + return -EFAULT; + psbfb_2d_submit(dev_priv, buf, l); + return 0; + default: + return -ENOTTY; + } +} static struct fb_ops psbfb_ops = { .owner = THIS_MODULE, @@ -284,11 +305,12 @@ static struct fb_ops psbfb_ops = { .fb_imageblit = psbfb_imageblit, .fb_mmap = psbfb_mmap, .fb_sync = psbfb_sync, + .fb_ioctl = psbfb_ioctl, }; static struct drm_framebuffer *psb_framebuffer_create (struct drm_device *dev, struct drm_mode_fb_cmd *r, - void *mm_private) + struct gtt_range *gt) { struct psb_framebuffer *fb; int ret; @@ -304,7 +326,7 @@ static struct drm_framebuffer *psb_framebuffer_create drm_helper_mode_fill_fb_struct(&fb->base, r); - fb->bo = mm_private; + fb->gtt = gt; return &fb->base; @@ -313,136 +335,58 @@ err: return NULL; } -static struct drm_framebuffer *psb_user_framebuffer_create - (struct drm_device *dev, struct drm_file *filp, - struct drm_mode_fb_cmd *r) -{ - struct ttm_buffer_object *bo = NULL; - uint64_t size; - - bo = ttm_buffer_object_lookup(psb_fpriv(filp)->tfile, r->handle); - if (!bo) - return NULL; - - /* JB: TODO not drop, make smarter */ - size = ((uint64_t) bo->num_pages) << PAGE_SHIFT; - if (size < r->width * r->height * 4) - return NULL; - - /* JB: TODO not drop, refcount buffer */ - return psb_framebuffer_create(dev, r, bo); - -#if 0 - struct psb_framebuffer *psbfb; - struct drm_framebuffer *fb; - struct fb_info *info; - void *psKernelMemInfo = NULL; - void * hKernelMemInfo = (void *)r->handle; - struct drm_psb_private *dev_priv - = (struct drm_psb_private *)dev->dev_private; - struct psb_fbdev *fbdev = dev_priv->fbdev; - struct psb_gtt *pg = dev_priv->pg; - int ret; - uint32_t offset; - uint64_t size; - - ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo); - if (ret) { - DRM_ERROR("Cannot get meminfo for handle 0x%x\n", - (u32)hKernelMemInfo); - return NULL; - } - - DRM_DEBUG("Got Kernel MemInfo for handle %lx\n", - (u32)hKernelMemInfo); - - /* JB: TODO not drop, make smarter */ - size = psKernelMemInfo->ui32AllocSize; - if (size < r->height * r->pitch) +/** + * psbfb_alloc - allocate frame buffer memory + * @dev: the DRM device + * @aligned_size: space needed + * + * Allocate the frame buffer. In the usual case we get a GTT range that + * is stolen memory backed and life is simple. If there isn't sufficient + * stolen memory or the system has no stolen memory we allocate a range + * and back it with a GEM object. + * + * In this case the GEM object has no handle. + */ +static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size) +{ + struct gtt_range *backing; + /* Begin by trying to use stolen memory backing */ + backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1); + if (backing) + return backing; + /* Next try using GEM host memory */ + backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0); + if (backing == NULL) return NULL; - /* JB: TODO not drop, refcount buffer */ - /* return psb_framebuffer_create(dev, r, bo); */ - - fb = psb_framebuffer_create(dev, r, (void *)psKernelMemInfo); - if (!fb) { - DRM_ERROR("failed to allocate fb.\n"); + /* Now back it with an object */ + if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) { + psb_gtt_free_range(dev, backing); return NULL; } - - psbfb = to_psb_fb(fb); - psbfb->size = size; - psbfb->hKernelMemInfo = hKernelMemInfo; - - DRM_DEBUG("Mapping to gtt..., KernelMemInfo %p\n", psKernelMemInfo); - - /*if not VRAM, map it into tt aperture*/ - if (psKernelMemInfo->pvLinAddrKM != pg->vram_addr) { - ret = psb_gtt_map_meminfo(dev, hKernelMemInfo, &offset); - if (ret) { - DRM_ERROR("map meminfo for 0x%x failed\n", - (u32)hKernelMemInfo); - return NULL; - } - psbfb->offset = (offset << PAGE_SHIFT); - } else { - psbfb->offset = 0; - } - info = framebuffer_alloc(0, &dev->pdev->dev); - if (!info) - return NULL; - - strcpy(info->fix.id, "psbfb"); - - info->flags = FBINFO_DEFAULT; - info->fix.accel = FB_ACCEL_I830; /*FIXMEAC*/ - info->fbops = &psbfb_ops; - - info->fix.smem_start = dev->mode_config.fb_base; - info->fix.smem_len = size; - - info->screen_base = psKernelMemInfo->pvLinAddrKM; - info->screen_size = size; - - drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); - drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, - fb->width, fb->height); - - info->fix.mmio_start = pci_resource_start(dev->pdev, 0); - info->fix.mmio_len = pci_resource_len(dev->pdev, 0); - - info->pixmap.size = 64 * 1024; - info->pixmap.buf_align = 8; - info->pixmap.access_align = 32; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 1; - - psbfb->fbdev = info; - fbdev->pfb = psbfb; - - fbdev->psb_fb_helper.fb = fb; - fbdev->psb_fb_helper.fbdev = info; - MRSTLFBHandleChangeFB(dev, psbfb); - - return fb; -#endif + return backing; } - + +/** + * psbfb_create - create a framebuffer + * @fbdev: the framebuffer device + * @sizes: specification of the layout + * + * Create a framebuffer to the specifications provided + */ static int psbfb_create(struct psb_fbdev *fbdev, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = fbdev->psb_fb_helper.dev; struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_gtt *pg = dev_priv->pg; struct fb_info *info; struct drm_framebuffer *fb; struct psb_framebuffer *psbfb; struct drm_mode_fb_cmd mode_cmd; struct device *device = &dev->pdev->dev; - - struct ttm_buffer_object *fbo = NULL; int size, aligned_size; int ret; + struct gtt_range *backing; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; @@ -455,15 +399,19 @@ static int psbfb_create(struct psb_fbdev *fbdev, size = mode_cmd.pitch * mode_cmd.height; aligned_size = ALIGN(size, PAGE_SIZE); + /* Allocate the framebuffer in the GTT with stolen page backing */ + backing = psbfb_alloc(dev, aligned_size); + if (backing == NULL) + return -ENOMEM; + mutex_lock(&dev->struct_mutex); - fb = psb_framebuffer_create(dev, &mode_cmd, fbo); + fb = psb_framebuffer_create(dev, &mode_cmd, backing); if (!fb) { DRM_ERROR("failed to allocate fb.\n"); ret = -ENOMEM; goto out_err1; } psbfb = to_psb_fb(fb); - psbfb->size = size; info = framebuffer_alloc(sizeof(struct psb_fbdev), device); if (!info) { @@ -485,10 +433,24 @@ static int psbfb_create(struct psb_fbdev *fbdev, info->fbops = &psbfb_ops; info->fix.smem_start = dev->mode_config.fb_base; info->fix.smem_len = size; - info->screen_base = (char *)pg->vram_addr; + + /* Accessed via stolen memory directly, This only works for stolem + memory however. Need to address this once we start using gtt + pages we allocate */ + info->screen_base = (char *)dev_priv->vram_addr + backing->offset; info->screen_size = size; memset(info->screen_base, 0, size); + if (dev_priv->pg->stolen_size) { + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto out_err0; + } + info->apertures->ranges[0].base = dev->mode_config.fb_base; + info->apertures->ranges[0].size = dev_priv->pg->stolen_size; + } + drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, sizes->fb_width, sizes->fb_height); @@ -515,9 +477,51 @@ out_err0: fb->funcs->destroy(fb); out_err1: mutex_unlock(&dev->struct_mutex); + psb_gtt_free_range(dev, backing); return ret; } +/** + * psb_user_framebuffer_create - create framebuffer + * @dev: our DRM device + * @filp: client file + * @cmd: mode request + * + * Create a new framebuffer backed by a userspace GEM object + */ +static struct drm_framebuffer *psb_user_framebuffer_create + (struct drm_device *dev, struct drm_file *filp, + struct drm_mode_fb_cmd *cmd) +{ + struct gtt_range *r; + struct drm_gem_object *obj; + struct psb_framebuffer *psbfb; + + /* Find the GEM object and thus the gtt range object that is + to back this space */ + obj = drm_gem_object_lookup(dev, filp, cmd->handle); + if (obj == NULL) + return ERR_PTR(-ENOENT); + + /* Allocate a framebuffer */ + psbfb = kzalloc(sizeof(*psbfb), GFP_KERNEL); + if (psbfb == NULL) { + drm_gem_object_unreference_unlocked(obj); + return ERR_PTR(-ENOMEM); + } + + /* Let the core code do all the work */ + r = container_of(obj, struct gtt_range, gem); + if (psb_framebuffer_create(dev, cmd, r) == NULL) { + drm_gem_object_unreference_unlocked(obj); + kfree(psbfb); + return ERR_PTR(-EINVAL); + } + /* Return the drm_framebuffer contained within the psb fbdev which + has been initialized by the framebuffer creation */ + return &psbfb->base; +} + static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno) { @@ -561,15 +565,20 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev) if (fbdev->psb_fb_helper.fbdev) { info = fbdev->psb_fb_helper.fbdev; + /* FIXME: this is a bit more inside knowledge than I'd like + but I don't see how to make a fake GEM object of the + stolen space nicely */ + if (psbfb->gtt->stolen) + psb_gtt_free_range(dev, psbfb->gtt); + else + drm_gem_object_unreference(&psbfb->gtt->gem); unregister_framebuffer(info); iounmap(info->screen_base); framebuffer_release(info); } drm_fb_helper_fini(&fbdev->psb_fb_helper); - drm_framebuffer_cleanup(&psbfb->base); - return 0; } @@ -610,7 +619,6 @@ void psb_fbdev_fini(struct drm_device *dev) dev_priv->fbdev = NULL; } - static void psbfb_output_poll_changed(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; @@ -627,7 +635,6 @@ int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) return 0; info = psbfb->fbdev; - psbfb->pvrBO = NULL; if (info) framebuffer_release(info); @@ -635,28 +642,48 @@ int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) } /*EXPORT_SYMBOL(psbfb_remove); */ +/** + * psb_user_framebuffer_create_handle - add hamdle to a framebuffer + * @fb: framebuffer + * @file_priv: our DRM file + * @handle: returned handle + * + * Our framebuffer object is a GTT range which also contains a GEM + * object. We need to turn it into a handle for userspace. GEM will do + * the work for us + */ static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, struct drm_file *file_priv, unsigned int *handle) { - /* JB: TODO currently we can't go from a bo to a handle with ttm */ - (void) file_priv; - *handle = 0; - return 0; + struct psb_framebuffer *psbfb = to_psb_fb(fb); + struct gtt_range *r = psbfb->gtt; + if (r->stolen) + return -EOPNOTSUPP; + return drm_gem_handle_create(file_priv, &r->gem, handle); } +/** + * psb_user_framebuffer_destroy - destruct user created fb + * @fb: framebuffer + * + * User framebuffers are backed by GEM objects so all we have to do is + * clean up a bit and drop the reference, GEM will handle the fallout + */ static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb) { struct drm_device *dev = fb->dev; struct psb_framebuffer *psbfb = to_psb_fb(fb); + struct gtt_range *r = psbfb->gtt; - /*ummap gtt pages*/ - psb_gtt_unmap_meminfo(dev, psbfb->hKernelMemInfo); if (psbfb->fbdev) psbfb_remove(dev, fb); - /* JB: TODO not drop, refcount buffer */ + /* Let DRM do its clean up */ drm_framebuffer_cleanup(fb); + /* We are no longer using the resource in GEM */ + drm_gem_object_unreference_unlocked(&r->gem); + kfree(fb); } @@ -698,8 +725,15 @@ static void psb_setup_outputs(struct drm_device *dev) psb_create_backlight_property(dev); - psb_intel_lvds_init(dev, &dev_priv->mode_dev); - /* psb_intel_sdvo_init(dev, SDVOB); */ + if (IS_MRST(dev)) { + if (dev_priv->iLVDS_enable) + mrst_lvds_init(dev, &dev_priv->mode_dev); + else + DRM_ERROR("DSI is not supported\n"); + } else { + psb_intel_lvds_init(dev, &dev_priv->mode_dev); + psb_intel_sdvo_init(dev, SDVOB); + } list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -716,7 +750,10 @@ static void psb_setup_outputs(struct drm_device *dev) break; case INTEL_OUTPUT_LVDS: PSB_DEBUG_ENTRY("LVDS.\n"); - crtc_mask = (1 << 1); + if (IS_MRST(dev)) + crtc_mask = (1 << 0); + else + crtc_mask = (1 << 1); clone_mask = (1 << INTEL_OUTPUT_LVDS); break; case INTEL_OUTPUT_MIPI: @@ -743,52 +780,6 @@ static void psb_setup_outputs(struct drm_device *dev) } } -static void *psb_bo_from_handle(struct drm_device *dev, - struct drm_file *file_priv, - unsigned int handle) -{ - void *psKernelMemInfo = NULL; - void * hKernelMemInfo = (void *)handle; - int ret; - - ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo); - if (ret) { - DRM_ERROR("Cannot get meminfo for handle 0x%x\n", - (u32)hKernelMemInfo); - return NULL; - } - - return (void *)psKernelMemInfo; -} - -static size_t psb_bo_size(struct drm_device *dev, void *bof) -{ -#if 0 - void *psKernelMemInfo = (void *)bof; - return (size_t)psKernelMemInfo->ui32AllocSize; -#else - return 0; -#endif -} - -static size_t psb_bo_offset(struct drm_device *dev, void *bof) -{ - struct psb_framebuffer *psbfb - = (struct psb_framebuffer *)bof; - - return (size_t)psbfb->offset; -} - -static int psb_bo_pin_for_scanout(struct drm_device *dev, void *bo) -{ - return 0; -} - -static int psb_bo_unpin_for_scanout(struct drm_device *dev, void *bo) -{ - return 0; -} - void psb_modeset_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = @@ -797,12 +788,6 @@ void psb_modeset_init(struct drm_device *dev) int i; PSB_DEBUG_ENTRY("\n"); - /* Init mm functions */ - mode_dev->bo_from_handle = psb_bo_from_handle; - mode_dev->bo_size = psb_bo_size; - mode_dev->bo_offset = psb_bo_offset; - mode_dev->bo_pin_for_scanout = psb_bo_pin_for_scanout; - mode_dev->bo_unpin_for_scanout = psb_bo_unpin_for_scanout; drm_mode_config_init(dev); diff --git a/drivers/staging/gma500/psb_fb.h b/drivers/staging/gma500/psb_fb.h index b4fab9262db5..c8ec0d6febb1 100644 --- a/drivers/staging/gma500/psb_fb.h +++ b/drivers/staging/gma500/psb_fb.h @@ -28,32 +28,22 @@ #include "psb_drv.h" -/*IMG Headers*/ -/*#include "servicesint.h"*/ - struct psb_framebuffer { struct drm_framebuffer base; struct address_space *addr_space; - struct ttm_buffer_object *bo; - struct fb_info * fbdev; - /* struct ttm_bo_kmap_obj kmap; */ - void *pvrBO; /* FIXME: sort this out */ - void * hKernelMemInfo; - uint32_t size; - uint32_t offset; + struct fb_info *fbdev; + struct gtt_range *gtt; }; struct psb_fbdev { struct drm_fb_helper psb_fb_helper; - struct psb_framebuffer * pfb; + struct psb_framebuffer *pfb; }; #define to_psb_fb(x) container_of(x, struct psb_framebuffer, base) - extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask); - #endif diff --git a/drivers/staging/gma500/psb_fence.c b/drivers/staging/gma500/psb_fence.c deleted file mode 100644 index a70aa64f2cad..000000000000 --- a/drivers/staging/gma500/psb_fence.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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. - * - * - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - */ - -#include <drm/drmP.h> -#include "psb_drv.h" - - -static void psb_fence_poll(struct ttm_fence_device *fdev, - uint32_t fence_class, uint32_t waiting_types) -{ - struct drm_psb_private *dev_priv = - container_of(fdev, struct drm_psb_private, fdev); - - - if (unlikely(!dev_priv)) - return; - - if (waiting_types == 0) - return; - - /* DRM_ERROR("Polling fence sequence, got 0x%08x\n", sequence); */ - ttm_fence_handler(fdev, fence_class, 0 /* Sequence */, - _PSB_FENCE_TYPE_EXE, 0); -} - -void psb_fence_error(struct drm_device *dev, - uint32_t fence_class, - uint32_t sequence, uint32_t type, int error) -{ - struct drm_psb_private *dev_priv = psb_priv(dev); - struct ttm_fence_device *fdev = &dev_priv->fdev; - unsigned long irq_flags; - struct ttm_fence_class_manager *fc = - &fdev->fence_class[fence_class]; - - BUG_ON(fence_class >= PSB_NUM_ENGINES); - write_lock_irqsave(&fc->lock, irq_flags); - ttm_fence_handler(fdev, fence_class, sequence, type, error); - write_unlock_irqrestore(&fc->lock, irq_flags); -} - -int psb_fence_emit_sequence(struct ttm_fence_device *fdev, - uint32_t fence_class, - uint32_t flags, uint32_t *sequence, - unsigned long *timeout_jiffies) -{ - struct drm_psb_private *dev_priv = - container_of(fdev, struct drm_psb_private, fdev); - - if (!dev_priv) - return -EINVAL; - - if (fence_class >= PSB_NUM_ENGINES) - return -EINVAL; - - DRM_ERROR("Unexpected fence class\n"); - return -EINVAL; -} - -static void psb_fence_lockup(struct ttm_fence_object *fence, - uint32_t fence_types) -{ - DRM_ERROR("Unsupported fence class\n"); -} - -void psb_fence_handler(struct drm_device *dev, uint32_t fence_class) -{ - struct drm_psb_private *dev_priv = psb_priv(dev); - struct ttm_fence_device *fdev = &dev_priv->fdev; - struct ttm_fence_class_manager *fc = - &fdev->fence_class[fence_class]; - unsigned long irq_flags; - - write_lock_irqsave(&fc->lock, irq_flags); - psb_fence_poll(fdev, fence_class, fc->waiting_types); - write_unlock_irqrestore(&fc->lock, irq_flags); -} - - -static struct ttm_fence_driver psb_ttm_fence_driver = { - .has_irq = NULL, - .emit = psb_fence_emit_sequence, - .flush = NULL, - .poll = psb_fence_poll, - .needed_flush = NULL, - .wait = NULL, - .signaled = NULL, - .lockup = psb_fence_lockup, -}; - -int psb_ttm_fence_device_init(struct ttm_fence_device *fdev) -{ - struct drm_psb_private *dev_priv = - container_of(fdev, struct drm_psb_private, fdev); - struct ttm_fence_class_init fci = {.wrap_diff = (1 << 30), - .flush_diff = (1 << 29), - .sequence_mask = 0xFFFFFFFF - }; - - return ttm_fence_device_init(PSB_NUM_ENGINES, - dev_priv->mem_global_ref.object, - fdev, &fci, 1, - &psb_ttm_fence_driver); -} diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c new file mode 100644 index 000000000000..76ff7bacd35b --- /dev/null +++ b/drivers/staging/gma500/psb_gem.c @@ -0,0 +1,320 @@ +/* + * psb GEM interface + * + * Copyright (c) 2011, Intel Corporation. + * + * 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. + * + * Authors: Alan Cox + * + * TODO: + * - we don't actually put GEM objects into the GART yet + * - we need to work out if the MMU is relevant as well (eg for + * accelerated operations on a GEM object) + * - cache coherency + * + * ie this is just an initial framework to get us going. + */ + +#include <drm/drmP.h> +#include <drm/drm.h> +#include "psb_drm.h" +#include "psb_drv.h" + +int psb_gem_init_object(struct drm_gem_object *obj) +{ + return -EINVAL; +} + +void psb_gem_free_object(struct drm_gem_object *obj) +{ + struct gtt_range *gtt = container_of(obj, struct gtt_range, gem); + psb_gtt_free_range(obj->dev, gtt); + if (obj->map_list.map) { + /* Do things GEM should do for us */ + struct drm_gem_mm *mm = obj->dev->mm_private; + struct drm_map_list *list = &obj->map_list; + drm_ht_remove_item(&mm->offset_hash, &list->hash); + drm_mm_put_block(list->file_offset_node); + kfree(list->map); + list->map = NULL; + } + drm_gem_object_release(obj); +} + +int psb_gem_get_aperture(struct drm_device *dev, void *data, + struct drm_file *file) +{ + return -EINVAL; +} + +/** + * psb_gem_create_mmap_offset - invent an mmap offset + * @obj: our object + * + * This is basically doing by hand a pile of ugly crap which should + * be done automatically by the GEM library code but isn't + */ +static int psb_gem_create_mmap_offset(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_gem_mm *mm = dev->mm_private; + struct drm_map_list *list; + struct drm_local_map *map; + int ret; + + list = &obj->map_list; + list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); + if (list->map == NULL) + return -ENOMEM; + map = list->map; + map->type = _DRM_GEM; + map->size = obj->size; + map->handle =obj; + + list->file_offset_node = drm_mm_search_free(&mm->offset_manager, + obj->size / PAGE_SIZE, 0, 0); + if (!list->file_offset_node) { + DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); + ret = -ENOSPC; + goto free_it; + } + list->file_offset_node = drm_mm_get_block(list->file_offset_node, + obj->size / PAGE_SIZE, 0); + if (!list->file_offset_node) { + ret = -ENOMEM; + goto free_it; + } + list->hash.key = list->file_offset_node->start; + ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); + if (ret) { + DRM_ERROR("failed to add to map hash\n"); + goto free_mm; + } + return 0; + +free_mm: + drm_mm_put_block(list->file_offset_node); +free_it: + kfree(list->map); + list->map = NULL; + return ret; +} + +/** + * psb_gem_dumb_map_gtt - buffer mapping for dumb interface + * @file: our drm client file + * @dev: drm device + * @handle: GEM handle to the object (from dumb_create) + * + * Do the necessary setup to allow the mapping of the frame buffer + * into user memory. We don't have to do much here at the moment. + */ +int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, + uint32_t handle, uint64_t *offset) +{ + int ret = 0; + struct drm_gem_object *obj; + + if (!(dev->driver->driver_features & DRIVER_GEM)) + return -ENODEV; + + mutex_lock(&dev->struct_mutex); + + /* GEM does all our handle to object mapping */ + obj = drm_gem_object_lookup(dev, file, handle); + if (obj == NULL) { + ret = -ENOENT; + goto unlock; + } + /* What validation is needed here ? */ + + /* Make it mmapable */ + if (!obj->map_list.map) { + ret = psb_gem_create_mmap_offset(obj); + if (ret) + goto out; + } + /* GEM should really work out the hash offsets for us */ + *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT; +out: + drm_gem_object_unreference(obj); +unlock: + mutex_unlock(&dev->struct_mutex); + return ret; +} + +/** + * psb_gem_create - create a mappable object + * @file: the DRM file of the client + * @dev: our device + * @size: the size requested + * @handlep: returned handle (opaque number) + * + * Create a GEM object, fill in the boilerplate and attach a handle to + * it so that userspace can speak about it. This does the core work + * for the various methods that do/will create GEM objects for things + */ +static int psb_gem_create(struct drm_file *file, + struct drm_device *dev, uint64_t size, uint32_t *handlep) +{ + struct gtt_range *r; + int ret; + u32 handle; + + size = roundup(size, PAGE_SIZE); + + /* Allocate our object - for now a direct gtt range which is not + stolen memory backed */ + r = psb_gtt_alloc_range(dev, size, "gem", 0); + if (r == NULL) + return -ENOSPC; + /* Initialize the extra goodies GEM needs to do all the hard work */ + if (drm_gem_object_init(dev, &r->gem, size) != 0) { + psb_gtt_free_range(dev, r); + /* GEM doesn't give an error code and we don't have an + EGEMSUCKS so make something up for now - FIXME */ + return -ENOMEM; + } + /* Give the object a handle so we can carry it more easily */ + ret = drm_gem_handle_create(file, &r->gem, &handle); + if (ret) { + drm_gem_object_release(&r->gem); + psb_gtt_free_range(dev, r); + return ret; + } + /* We have the initial and handle reference but need only one now */ + drm_gem_object_unreference(&r->gem); + *handlep = handle; + return 0; +} + +/** + * psb_gem_dumb_create - create a dumb buffer + * @drm_file: our client file + * @dev: our device + * @args: the requested arguments copied from userspace + * + * Allocate a buffer suitable for use for a frame buffer of the + * form described by user space. Give userspace a handle by which + * to reference it. + */ +int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); + args->size = args->pitch * args->height; + return psb_gem_create(file, dev, args->size, &args->handle); +} + +/** + * psb_gem_dumb_destroy - destroy a dumb buffer + * @file: client file + * @dev: our DRM device + * @handle: the object handle + * + * Destroy a handle that was created via psb_gem_dumb_create, at least + * we hope it was created that way. i915 seems to assume the caller + * does the checking but that might be worth review ! FIXME + */ +int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, + uint32_t handle) +{ + /* No special work needed, drop the reference and see what falls out */ + return drm_gem_handle_delete(file, handle); +} + +/** + * psb_gem_fault - pagefault handler for GEM objects + * @vma: the VMA of the GEM object + * @vmf: fault detail + * + * Invoked when a fault occurs on an mmap of a GEM managed area. GEM + * does most of the work for us including the actual map/unmap calls + * but we need to do the actual page work. + * + * This code eventually needs to handle faulting objects in and out + * of the GART and repacking it when we run out of space. We can put + * that off for now and for our simple uses + * + * The VMA was set up by GEM. In doing so it also ensured that the + * vma->vm_private_data points to the GEM object that is backing this + * mapping. + * + * To avoid aliasing and cache funnies we want to map the object + * through the GART. For the moment this is slightly hackish. It would + * be nicer if GEM provided mmap opened/closed hooks for us giving + * the object so that we could track things nicely. That needs changes + * to the core GEM code so must be tackled post staging + * + * FIXME + */ +int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct drm_gem_object *obj; + struct gtt_range *r; + int ret; + unsigned long pfn; + pgoff_t page_offset; + struct drm_device *dev; + + obj = vma->vm_private_data; /* GEM object */ + dev = obj->dev; + + r = container_of(obj, struct gtt_range, gem); /* Get the gtt range */ + + /* Make sure we don't parallel update on a fault, nor move or remove + something from beneath our feet */ + mutex_lock(&dev->struct_mutex); + + /* For now the mmap pins the object and it stays pinned. As things + stand that will do us no harm */ + if (r->mmapping == 0) { + ret = psb_gtt_pin(r); + if (ret < 0) { + DRM_ERROR("gma500: pin failed: %d\n", ret); + goto fail; + } + r->mmapping = 1; + } + + /* FIXME: Locking. We may also need to repack the GART sometimes */ + + /* Page relative to the VMA start */ + page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start) + >> PAGE_SHIFT; + + /* Bus address of the page is gart + object offset + page offset */ + /* Assumes gtt allocations are page aligned */ + pfn = (r->resource.start >> PAGE_SHIFT) + page_offset; + + pr_debug("Object GTT base at %p\n", (void *)(r->resource.start)); + pr_debug("Inserting %p pfn %lx, pa %lx\n", vmf->virtual_address, + pfn, pfn << PAGE_SHIFT); + + ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); + +fail: + mutex_unlock(&dev->struct_mutex); + switch (ret) { + case 0: + case -ERESTARTSYS: + case -EINTR: + return VM_FAULT_NOPAGE; + case -ENOMEM: + return VM_FAULT_OOM; + default: + return VM_FAULT_SIGBUS; + } +} diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c index 53c1e1ed3bd2..74c5a6569d08 100644 --- a/drivers/staging/gma500/psb_gtt.c +++ b/drivers/staging/gma500/psb_gtt.c @@ -16,12 +16,24 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com> + * Alan Cox <alan@linux.intel.com> */ #include <drm/drmP.h> #include "psb_drv.h" -#include "psb_pvr_glue.h" + +/* + * GTT resource allocator - manage page mappings in GTT space + */ + +/** + * psb_gtt_mask_pte - generate GART pte entry + * @pfn: page number to encode + * @type: type of memory in the GART + * + * Set the GART entry for the appropriate memory type. + */ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) { uint32_t mask = PSB_PTE_VALID; @@ -36,6 +48,327 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) return (pfn << PAGE_SHIFT) | mask; } +/** + * psb_gtt_entry - find the GART entries for a gtt_range + * @dev: our DRM device + * @r: our GTT range + * + * Given a gtt_range object return the GART offset of the page table + * entries for this gtt_range + */ +u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + unsigned long offset; + + offset = r->resource.start - dev_priv->gtt_mem->start; + + return dev_priv->gtt_map + (offset >> PAGE_SHIFT); +} + +/** + * psb_gtt_insert - put an object into the GART + * @dev: our DRM device + * @r: our GTT range + * + * Take our preallocated GTT range and insert the GEM object into + * the GART. + * + * FIXME: gtt lock ? + */ +static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + u32 *gtt_slot, pte; + int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT; + struct page **pages; + int i; + + if (r->pages == NULL) { + WARN_ON(1); + return -EINVAL; + } + + WARN_ON(r->stolen); /* refcount these maybe ? */ + + gtt_slot = psb_gtt_entry(dev, r); + pages = r->pages; + + /* Make sure we have no alias present */ + wbinvd(); + + /* Write our page entries into the GART itself */ + for (i = 0; i < numpages; i++) { + pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/); + iowrite32(pte, gtt_slot++); + } + /* Make sure all the entries are set before we return */ + ioread32(gtt_slot - 1); + + return 0; +} + +/** + * psb_gtt_remove - remove an object from the GART + * @dev: our DRM device + * @r: our GTT range + * + * Remove a preallocated GTT range from the GART. Overwrite all the + * page table entries with the dummy page + */ + +static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + u32 *gtt_slot, pte; + int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT; + int i; + + WARN_ON(r->stolen); + + gtt_slot = psb_gtt_entry(dev, r); + pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);; + + for (i = 0; i < numpages; i++) + iowrite32(pte, gtt_slot++); + ioread32(gtt_slot - 1); +} + +/** + * psb_gtt_attach_pages - attach and pin GEM pages + * @gt: the gtt range + * + * Pin and build an in kernel list of the pages that back our GEM object. + * While we hold this the pages cannot be swapped out + * + * FIXME: Do we need to cache flush when we update the GTT + */ +static int psb_gtt_attach_pages(struct gtt_range *gt) +{ + struct inode *inode; + struct address_space *mapping; + int i; + struct page *p; + int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT; + + WARN_ON(gt->pages); + + /* This is the shared memory object that backs the GEM resource */ + inode = gt->gem.filp->f_path.dentry->d_inode; + mapping = inode->i_mapping; + + gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL); + if (gt->pages == NULL) + return -ENOMEM; + for (i = 0; i < pages; i++) { + /* FIXME: review flags later */ + p = read_cache_page_gfp(mapping, i, + __GFP_COLD | GFP_KERNEL); + if (IS_ERR(p)) + goto err; + gt->pages[i] = p; + } + return 0; + +err: + while (i--) + page_cache_release(gt->pages[i]); + kfree(gt->pages); + gt->pages = NULL; + return PTR_ERR(p); +} + +/** + * psb_gtt_detach_pages - attach and pin GEM pages + * @gt: the gtt range + * + * Undo the effect of psb_gtt_attach_pages. At this point the pages + * must have been removed from the GART as they could now be paged out + * and move bus address. + * + * FIXME: Do we need to cache flush when we update the GTT + */ +static void psb_gtt_detach_pages(struct gtt_range *gt) +{ + int i; + int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT; + + for (i = 0; i < pages; i++) { + /* FIXME: do we need to force dirty */ + set_page_dirty(gt->pages[i]); + /* Undo the reference we took when populating the table */ + page_cache_release(gt->pages[i]); + } + kfree(gt->pages); + gt->pages = NULL; +} + +/** + * psb_gtt_pin - pin pages into the GTT + * @gt: range to pin + * + * Pin a set of pages into the GTT. The pins are refcounted so that + * multiple pins need multiple unpins to undo. + * + * Non GEM backed objects treat this as a no-op as they are always GTT + * backed objects. + */ +int psb_gtt_pin(struct gtt_range *gt) +{ + int ret; + struct drm_device *dev = gt->gem.dev; + struct drm_psb_private *dev_priv = dev->dev_private; + + mutex_lock(&dev_priv->gtt_mutex); + + if (gt->in_gart == 0 && gt->stolen == 0) { + ret = psb_gtt_attach_pages(gt); + if (ret < 0) + goto out; + ret = psb_gtt_insert(dev, gt); + if (ret < 0) { + psb_gtt_detach_pages(gt); + goto out; + } + } + gt->in_gart++; +out: + mutex_unlock(&dev_priv->gtt_mutex); + return ret; +} + +/** + * psb_gtt_unpin - Drop a GTT pin requirement + * @gt: range to pin + * + * Undoes the effect of psb_gtt_pin. On the last drop the GEM object + * will be removed from the GTT which will also drop the page references + * and allow the VM to clean up or page stuff. + * + * Non GEM backed objects treat this as a no-op as they are always GTT + * backed objects. + */ +void psb_gtt_unpin(struct gtt_range *gt) +{ + struct drm_device *dev = gt->gem.dev; + struct drm_psb_private *dev_priv = dev->dev_private; + + mutex_lock(&dev_priv->gtt_mutex); + + WARN_ON(!gt->in_gart); + + gt->in_gart--; + if (gt->in_gart == 0 && gt->stolen == 0) { + psb_gtt_remove(dev, gt); + psb_gtt_detach_pages(gt); + } + mutex_unlock(&dev_priv->gtt_mutex); +} + +/* + * GTT resource allocator - allocate and manage GTT address space + */ + +/** + * psb_gtt_alloc_range - allocate GTT address space + * @dev: Our DRM device + * @len: length (bytes) of address space required + * @name: resource name + * @backed: resource should be backed by stolen pages + * + * Ask the kernel core to find us a suitable range of addresses + * to use for a GTT mapping. + * + * Returns a gtt_range structure describing the object, or NULL on + * error. On successful return the resource is both allocated and marked + * as in use. + */ +struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, + const char *name, int backed) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct gtt_range *gt; + struct resource *r = dev_priv->gtt_mem; + int ret; + unsigned long start, end; + + if (backed) { + /* The start of the GTT is the stolen pages */ + start = r->start; + end = r->start + dev_priv->pg->stolen_size - 1; + } else { + /* The rest we will use for GEM backed objects */ + start = r->start + dev_priv->pg->stolen_size; + end = r->end; + } + + gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL); + if (gt == NULL) + return NULL; + gt->resource.name = name; + gt->stolen = backed; + gt->in_gart = backed; + /* Ensure this is set for non GEM objects */ + gt->gem.dev = dev; + kref_init(>->kref); + + ret = allocate_resource(dev_priv->gtt_mem, >->resource, + len, start, end, PAGE_SIZE, NULL, NULL); + if (ret == 0) { + gt->offset = gt->resource.start - r->start; + return gt; + } + kfree(gt); + return NULL; +} + +/** + * psb_gtt_destroy - final free up of a gtt + * @kref: the kref of the gtt + * + * Called from the kernel kref put when the final reference to our + * GTT object is dropped. At that point we can free up the resources. + * + * For now we handle mmap clean up here to work around limits in GEM + */ +static void psb_gtt_destroy(struct kref *kref) +{ + struct gtt_range *gt = container_of(kref, struct gtt_range, kref); + + /* Undo the mmap pin if we are destroying the object */ + if (gt->mmapping) { + psb_gtt_unpin(gt); + gt->mmapping = 0; + } + WARN_ON(gt->in_gart && !gt->stolen); + release_resource(>->resource); + kfree(gt); +} + +/** + * psb_gtt_kref_put - drop reference to a GTT object + * @gt: the GT being dropped + * + * Drop a reference to a psb gtt + */ +void psb_gtt_kref_put(struct gtt_range *gt) +{ + kref_put(>->kref, psb_gtt_destroy); +} + +/** + * psb_gtt_free_range - release GTT address space + * @dev: our DRM device + * @gt: a mapping created with psb_gtt_alloc_range + * + * Release a resource that was allocated with psb_gtt_alloc_range + */ +void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt) +{ + psb_gtt_kref_put(gt); +} + + struct psb_gtt *psb_gtt_alloc(struct drm_device *dev) { struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); @@ -49,98 +382,89 @@ struct psb_gtt *psb_gtt_alloc(struct drm_device *dev) return tmp; } -void psb_gtt_takedown(struct psb_gtt *pg, int free) +void psb_gtt_takedown(struct drm_device *dev) { - struct drm_psb_private *dev_priv = pg->dev->dev_private; - - if (!pg) - return; + struct drm_psb_private *dev_priv = dev->dev_private; - if (pg->gtt_map) { - iounmap(pg->gtt_map); - pg->gtt_map = NULL; + /* FIXME: iounmap dev_priv->vram_addr etc */ + if (dev_priv->gtt_map) { + iounmap(dev_priv->gtt_map); + dev_priv->gtt_map = NULL; } - if (pg->initialized) { - pci_write_config_word(pg->dev->pdev, PSB_GMCH_CTRL, - pg->gmch_ctrl); - PSB_WVDC32(pg->pge_ctl, PSB_PGETBL_CTL); + if (dev_priv->gtt_initialized) { + pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, + dev_priv->gmch_ctrl); + PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); (void) PSB_RVDC32(PSB_PGETBL_CTL); } - if (free) - kfree(pg); + kfree(dev_priv->pg); + dev_priv->pg = NULL; } -int psb_gtt_init(struct psb_gtt *pg, int resume) +int psb_gtt_init(struct drm_device *dev, int resume) { - struct drm_device *dev = pg->dev; struct drm_psb_private *dev_priv = dev->dev_private; unsigned gtt_pages; - unsigned long stolen_size, vram_stolen_size, ci_stolen_size; - unsigned long rar_stolen_size; + unsigned long stolen_size, vram_stolen_size; unsigned i, num_pages; unsigned pfn_base; - uint32_t ci_pages, vram_pages; + uint32_t vram_pages; uint32_t tt_pages; uint32_t *ttm_gtt_map; uint32_t dvmt_mode = 0; + struct psb_gtt *pg; int ret = 0; uint32_t pte; - pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &pg->gmch_ctrl); + mutex_init(&dev_priv->gtt_mutex); + + dev_priv->pg = pg = psb_gtt_alloc(dev); + if (pg == NULL) + return -ENOMEM; + + pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, - pg->gmch_ctrl | _PSB_GMCH_ENABLED); + dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); - pg->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); - PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); + dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); + PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); (void) PSB_RVDC32(PSB_PGETBL_CTL); - pg->initialized = 1; + /* The root resource we allocate address space from */ + dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE]; - pg->gtt_phys_start = pg->pge_ctl & PAGE_MASK; + dev_priv->gtt_initialized = 1; + + pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); /* fix me: video mmu has hw bug to access 0x0D0000000, * then make gatt start at 0x0e000,0000 */ - pg->mmu_gatt_start = PSB_MEM_TT_START; + pg->mmu_gatt_start = 0xE0000000; pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE); gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT; pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT; - pci_read_config_dword(dev->pdev, PSB_BSM, &pg->stolen_base); - vram_stolen_size = pg->gtt_phys_start - pg->stolen_base - PAGE_SIZE; + pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base); + vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE; - /* CI is not included in the stolen size since the TOPAZ MMU bug */ - ci_stolen_size = dev_priv->ci_region_size; - /* Don't add CI & RAR share buffer space - * managed by TTM to stolen_size */ stolen_size = vram_stolen_size; - rar_stolen_size = dev_priv->rar_region_size; - printk(KERN_INFO"GMMADR(region 0) start: 0x%08x (%dM).\n", pg->gatt_start, pg->gatt_pages/256); printk(KERN_INFO"GTTADR(region 3) start: 0x%08x (can map %dM RAM), and actual RAM base 0x%08x.\n", pg->gtt_start, gtt_pages * 4, pg->gtt_phys_start); - printk(KERN_INFO "Stole memory information\n"); - printk(KERN_INFO " base in RAM: 0x%x\n", pg->stolen_base); - printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n", + printk(KERN_INFO "Stolen memory information\n"); + printk(KERN_INFO " base in RAM: 0x%x\n", dev_priv->stolen_base); + printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n", vram_stolen_size/1024); - dvmt_mode = (pg->gmch_ctrl >> 4) & 0x7; + dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7; printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n", (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode); - if (ci_stolen_size > 0) - printk(KERN_INFO"CI Stole memory: RAM base = 0x%08x, size = %lu M\n", - dev_priv->ci_region_start, - ci_stolen_size / 1024 / 1024); - if (rar_stolen_size > 0) - printk(KERN_INFO "RAR Stole memory: RAM base = 0x%08x, size = %lu M\n", - dev_priv->rar_region_start, - rar_stolen_size / 1024 / 1024); - if (resume && (gtt_pages != pg->gtt_pages) && (stolen_size != pg->stolen_size)) { DRM_ERROR("GTT resume error.\n"); @@ -150,42 +474,40 @@ int psb_gtt_init(struct psb_gtt *pg, int resume) pg->gtt_pages = gtt_pages; pg->stolen_size = stolen_size; - pg->vram_stolen_size = vram_stolen_size; - pg->ci_stolen_size = ci_stolen_size; - pg->rar_stolen_size = rar_stolen_size; - pg->gtt_map = + dev_priv->vram_stolen_size = vram_stolen_size; + dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT); - if (!pg->gtt_map) { + if (!dev_priv->gtt_map) { DRM_ERROR("Failure to map gtt.\n"); ret = -ENOMEM; goto out_err; } - pg->vram_addr = ioremap_wc(pg->stolen_base, stolen_size); - if (!pg->vram_addr) { + dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); + if (!dev_priv->vram_addr) { DRM_ERROR("Failure to map stolen base.\n"); ret = -ENOMEM; goto out_err; } - DRM_DEBUG("%s: vram kernel virtual address %p\n", pg->vram_addr); + DRM_DEBUG("%s: vram kernel virtual address %p\n", dev_priv->vram_addr); tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ? (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT; - ttm_gtt_map = pg->gtt_map + tt_pages / 2; + ttm_gtt_map = dev_priv->gtt_map + tt_pages / 2; /* * insert vram stolen pages. */ - pfn_base = pg->stolen_base >> PAGE_SHIFT; + pfn_base = dev_priv->stolen_base >> PAGE_SHIFT; vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT; printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n", num_pages, pfn_base, 0); for (i = 0; i < num_pages; ++i) { pte = psb_gtt_mask_pte(pfn_base + i, 0); - iowrite32(pte, pg->gtt_map + i); + iowrite32(pte, dev_priv->gtt_map + i); } /* @@ -194,36 +516,9 @@ int psb_gtt_init(struct psb_gtt *pg, int resume) pfn_base = page_to_pfn(dev_priv->scratch_page); pte = psb_gtt_mask_pte(pfn_base, 0); for (; i < tt_pages / 2 - 1; ++i) - iowrite32(pte, pg->gtt_map + i); - - /* - * insert CI stolen pages - */ - - pfn_base = dev_priv->ci_region_start >> PAGE_SHIFT; - ci_pages = num_pages = ci_stolen_size >> PAGE_SHIFT; - printk(KERN_INFO"Set up %d CI stolen pages starting at 0x%08x, GTT offset %dK\n", - num_pages, pfn_base, (ttm_gtt_map - pg->gtt_map) * 4); - for (i = 0; i < num_pages; ++i) { - pte = psb_gtt_mask_pte(pfn_base + i, 0); - iowrite32(pte, ttm_gtt_map + i); - } + iowrite32(pte, dev_priv->gtt_map + i); /* - * insert RAR stolen pages - */ - if (rar_stolen_size != 0) { - pfn_base = dev_priv->rar_region_start >> PAGE_SHIFT; - num_pages = rar_stolen_size >> PAGE_SHIFT; - printk(KERN_INFO"Set up %d RAR stolen pages starting at 0x%08x, GTT offset %dK\n", - num_pages, pfn_base, - (ttm_gtt_map - pg->gtt_map + i) * 4); - for (; i < num_pages + ci_pages; ++i) { - pte = psb_gtt_mask_pte(pfn_base + i - ci_pages, 0); - iowrite32(pte, ttm_gtt_map + i); - } - } - /* * Init rest of gtt managed by TTM. */ @@ -234,801 +529,11 @@ int psb_gtt_init(struct psb_gtt *pg, int resume) for (; i < pg->gatt_pages - tt_pages / 2; ++i) iowrite32(pte, ttm_gtt_map + i); - (void) ioread32(pg->gtt_map + i - 1); + (void) ioread32(dev_priv->gtt_map + i - 1); return 0; out_err: - psb_gtt_takedown(pg, 0); - return ret; -} - -int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages, - unsigned offset_pages, unsigned num_pages, - unsigned desired_tile_stride, - unsigned hw_tile_stride, int type) -{ - unsigned rows = 1; - unsigned add; - unsigned row_add; - unsigned i; - unsigned j; - uint32_t *cur_page = NULL; - uint32_t pte; - - if (hw_tile_stride) - rows = num_pages / desired_tile_stride; - else - desired_tile_stride = num_pages; - - add = desired_tile_stride; - row_add = hw_tile_stride; - - down_read(&pg->sem); - for (i = 0; i < rows; ++i) { - cur_page = pg->gtt_map + offset_pages; - for (j = 0; j < desired_tile_stride; ++j) { - pte = - psb_gtt_mask_pte(page_to_pfn(*pages++), type); - iowrite32(pte, cur_page++); - } - offset_pages += add; - } - (void) ioread32(cur_page - 1); - up_read(&pg->sem); - - return 0; -} - -int psb_gtt_insert_phys_addresses(struct psb_gtt *pg, dma_addr_t *pPhysFrames, - unsigned offset_pages, unsigned num_pages, int type) -{ - unsigned j; - uint32_t *cur_page = NULL; - uint32_t pte; - u32 ba; - - down_read(&pg->sem); - cur_page = pg->gtt_map + offset_pages; - for (j = 0; j < num_pages; ++j) { - ba = *pPhysFrames++; - pte = psb_gtt_mask_pte(ba >> PAGE_SHIFT, type); - iowrite32(pte, cur_page++); - } - (void) ioread32(cur_page - 1); - up_read(&pg->sem); - return 0; -} - -int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages, - unsigned num_pages, unsigned desired_tile_stride, - unsigned hw_tile_stride, int rc_prot) -{ - struct drm_psb_private *dev_priv = pg->dev->dev_private; - unsigned rows = 1; - unsigned add; - unsigned row_add; - unsigned i; - unsigned j; - uint32_t *cur_page = NULL; - unsigned pfn_base = page_to_pfn(dev_priv->scratch_page); - uint32_t pte = psb_gtt_mask_pte(pfn_base, 0); - - if (hw_tile_stride) - rows = num_pages / desired_tile_stride; - else - desired_tile_stride = num_pages; - - add = desired_tile_stride; - row_add = hw_tile_stride; - - if (rc_prot) - down_read(&pg->sem); - for (i = 0; i < rows; ++i) { - cur_page = pg->gtt_map + offset_pages; - for (j = 0; j < desired_tile_stride; ++j) - iowrite32(pte, cur_page++); - - offset_pages += add; - } - (void) ioread32(cur_page - 1); - if (rc_prot) - up_read(&pg->sem); - - return 0; -} - -int psb_gtt_mm_init(struct psb_gtt *pg) -{ - struct psb_gtt_mm *gtt_mm; - struct drm_psb_private *dev_priv = pg->dev->dev_private; - struct drm_open_hash *ht; - struct drm_mm *mm; - int ret; - uint32_t tt_start; - uint32_t tt_size; - - if (!pg || !pg->initialized) { - DRM_DEBUG("Invalid gtt struct\n"); - return -EINVAL; - } - - gtt_mm = kzalloc(sizeof(struct psb_gtt_mm), GFP_KERNEL); - if (!gtt_mm) - return -ENOMEM; - - spin_lock_init(>t_mm->lock); - - ht = >t_mm->hash; - ret = drm_ht_create(ht, 20); - if (ret) { - DRM_DEBUG("Create hash table failed(%d)\n", ret); - goto err_free; - } - - tt_start = (pg->stolen_size + PAGE_SIZE - 1) >> PAGE_SHIFT; - tt_start = (tt_start < pg->gatt_pages) ? tt_start : pg->gatt_pages; - tt_size = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ? - (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT; - - mm = >t_mm->base; - - /*will use tt_start ~ 128M for IMG TT buffers*/ - ret = drm_mm_init(mm, tt_start, ((tt_size / 2) - tt_start)); - if (ret) { - DRM_DEBUG("drm_mm_int error(%d)\n", ret); - goto err_mm_init; - } - - gtt_mm->count = 0; - - dev_priv->gtt_mm = gtt_mm; - - DRM_INFO("PSB GTT mem manager ready, tt_start %ld, tt_size %ld pages\n", - (unsigned long)tt_start, - (unsigned long)((tt_size / 2) - tt_start)); - return 0; -err_mm_init: - drm_ht_remove(ht); - -err_free: - kfree(gtt_mm); + psb_gtt_takedown(dev); return ret; } - -/** - * Delete all hash entries; - */ -void psb_gtt_mm_takedown(void) -{ - return; -} - -static int psb_gtt_mm_get_ht_by_pid_locked(struct psb_gtt_mm *mm, - u32 tgid, - struct psb_gtt_hash_entry **hentry) -{ - struct drm_hash_item *entry; - struct psb_gtt_hash_entry *psb_entry; - int ret; - - ret = drm_ht_find_item(&mm->hash, tgid, &entry); - if (ret) { - DRM_DEBUG("Cannot find entry pid=%ld\n", tgid); - return ret; - } - - psb_entry = container_of(entry, struct psb_gtt_hash_entry, item); - if (!psb_entry) { - DRM_DEBUG("Invalid entry"); - return -EINVAL; - } - - *hentry = psb_entry; - return 0; -} - - -static int psb_gtt_mm_insert_ht_locked(struct psb_gtt_mm *mm, - u32 tgid, - struct psb_gtt_hash_entry *hentry) -{ - struct drm_hash_item *item; - int ret; - - if (!hentry) { - DRM_DEBUG("Invalid parameters\n"); - return -EINVAL; - } - - item = &hentry->item; - item->key = tgid; - - /** - * NOTE: drm_ht_insert_item will perform such a check - ret = psb_gtt_mm_get_ht_by_pid(mm, tgid, &tmp); - if (!ret) { - DRM_DEBUG("Entry already exists for pid %ld\n", tgid); - return -EAGAIN; - } - */ - - /*Insert the given entry*/ - ret = drm_ht_insert_item(&mm->hash, item); - if (ret) { - DRM_DEBUG("Insert failure\n"); - return ret; - } - - mm->count++; - - return 0; -} - -static int psb_gtt_mm_alloc_insert_ht(struct psb_gtt_mm *mm, - u32 tgid, - struct psb_gtt_hash_entry **entry) -{ - struct psb_gtt_hash_entry *hentry; - int ret; - - /*if the hentry for this tgid exists, just get it and return*/ - spin_lock(&mm->lock); - ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry); - if (!ret) { - DRM_DEBUG("Entry for tgid %ld exist, hentry %p\n", - tgid, hentry); - *entry = hentry; - spin_unlock(&mm->lock); - return 0; - } - spin_unlock(&mm->lock); - - DRM_DEBUG("Entry for tgid %ld doesn't exist, will create it\n", tgid); - - hentry = kzalloc(sizeof(struct psb_gtt_hash_entry), GFP_KERNEL); - if (!hentry) { - DRM_DEBUG("Kmalloc failled\n"); - return -ENOMEM; - } - - ret = drm_ht_create(&hentry->ht, 20); - if (ret) { - DRM_DEBUG("Create hash table failed\n"); - return ret; - } - - spin_lock(&mm->lock); - ret = psb_gtt_mm_insert_ht_locked(mm, tgid, hentry); - spin_unlock(&mm->lock); - - if (!ret) - *entry = hentry; - - return ret; -} - -static struct psb_gtt_hash_entry * -psb_gtt_mm_remove_ht_locked(struct psb_gtt_mm *mm, u32 tgid) -{ - struct psb_gtt_hash_entry *tmp; - int ret; - - ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &tmp); - if (ret) { - DRM_DEBUG("Cannot find entry pid %ld\n", tgid); - return NULL; - } - - /*remove it from ht*/ - drm_ht_remove_item(&mm->hash, &tmp->item); - - mm->count--; - - return tmp; -} - -static int psb_gtt_mm_remove_free_ht_locked(struct psb_gtt_mm *mm, u32 tgid) -{ - struct psb_gtt_hash_entry *entry; - - entry = psb_gtt_mm_remove_ht_locked(mm, tgid); - - if (!entry) { - DRM_DEBUG("Invalid entry"); - return -EINVAL; - } - - /*delete ht*/ - drm_ht_remove(&entry->ht); - - /*free this entry*/ - kfree(entry); - return 0; -} - -static int -psb_gtt_mm_get_mem_mapping_locked(struct drm_open_hash *ht, - u32 key, - struct psb_gtt_mem_mapping **hentry) -{ - struct drm_hash_item *entry; - struct psb_gtt_mem_mapping *mapping; - int ret; - - ret = drm_ht_find_item(ht, key, &entry); - if (ret) { - DRM_DEBUG("Cannot find key %ld\n", key); - return ret; - } - - mapping = container_of(entry, struct psb_gtt_mem_mapping, item); - if (!mapping) { - DRM_DEBUG("Invalid entry\n"); - return -EINVAL; - } - - *hentry = mapping; - return 0; -} - -static int -psb_gtt_mm_insert_mem_mapping_locked(struct drm_open_hash *ht, - u32 key, - struct psb_gtt_mem_mapping *hentry) -{ - struct drm_hash_item *item; - struct psb_gtt_hash_entry *entry; - int ret; - - if (!hentry) { - DRM_DEBUG("hentry is NULL\n"); - return -EINVAL; - } - - item = &hentry->item; - item->key = key; - - ret = drm_ht_insert_item(ht, item); - if (ret) { - DRM_DEBUG("insert_item failed\n"); - return ret; - } - - entry = container_of(ht, struct psb_gtt_hash_entry, ht); - if (entry) - entry->count++; - - return 0; -} - -static int -psb_gtt_mm_alloc_insert_mem_mapping(struct psb_gtt_mm *mm, - struct drm_open_hash *ht, - u32 key, - struct drm_mm_node *node, - struct psb_gtt_mem_mapping **entry) -{ - struct psb_gtt_mem_mapping *mapping; - int ret; - - if (!node || !ht) { - DRM_DEBUG("parameter error\n"); - return -EINVAL; - } - - /*try to get this mem_map */ - spin_lock(&mm->lock); - ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &mapping); - if (!ret) { - DRM_DEBUG("mapping entry for key %ld exists, entry %p\n", - key, mapping); - *entry = mapping; - spin_unlock(&mm->lock); - return 0; - } - spin_unlock(&mm->lock); - - DRM_DEBUG("Mapping entry for key %ld doesn't exist, will create it\n", - key); - - mapping = kzalloc(sizeof(struct psb_gtt_mem_mapping), GFP_KERNEL); - if (!mapping) { - DRM_DEBUG("kmalloc failed\n"); - return -ENOMEM; - } - - mapping->node = node; - - spin_lock(&mm->lock); - ret = psb_gtt_mm_insert_mem_mapping_locked(ht, key, mapping); - spin_unlock(&mm->lock); - - if (!ret) - *entry = mapping; - - return ret; -} - -static struct psb_gtt_mem_mapping * -psb_gtt_mm_remove_mem_mapping_locked(struct drm_open_hash *ht, u32 key) -{ - struct psb_gtt_mem_mapping *tmp; - struct psb_gtt_hash_entry *entry; - int ret; - - ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &tmp); - if (ret) { - DRM_DEBUG("Cannot find key %ld\n", key); - return NULL; - } - - drm_ht_remove_item(ht, &tmp->item); - - entry = container_of(ht, struct psb_gtt_hash_entry, ht); - if (entry) - entry->count--; - - return tmp; -} - -static int psb_gtt_mm_remove_free_mem_mapping_locked(struct drm_open_hash *ht, - u32 key, - struct drm_mm_node **node) -{ - struct psb_gtt_mem_mapping *entry; - - entry = psb_gtt_mm_remove_mem_mapping_locked(ht, key); - if (!entry) { - DRM_DEBUG("entry is NULL\n"); - return -EINVAL; - } - - *node = entry->node; - - kfree(entry); - return 0; -} - -static int psb_gtt_add_node(struct psb_gtt_mm *mm, - u32 tgid, - u32 key, - struct drm_mm_node *node, - struct psb_gtt_mem_mapping **entry) -{ - struct psb_gtt_hash_entry *hentry; - struct psb_gtt_mem_mapping *mapping; - int ret; - - ret = psb_gtt_mm_alloc_insert_ht(mm, tgid, &hentry); - if (ret) { - DRM_DEBUG("alloc_insert failed\n"); - return ret; - } - - ret = psb_gtt_mm_alloc_insert_mem_mapping(mm, - &hentry->ht, - key, - node, - &mapping); - if (ret) { - DRM_DEBUG("mapping alloc_insert failed\n"); - return ret; - } - - *entry = mapping; - - return 0; -} - -static int psb_gtt_remove_node(struct psb_gtt_mm *mm, - u32 tgid, - u32 key, - struct drm_mm_node **node) -{ - struct psb_gtt_hash_entry *hentry; - struct drm_mm_node *tmp; - int ret; - - spin_lock(&mm->lock); - ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry); - if (ret) { - DRM_DEBUG("Cannot find entry for pid %ld\n", tgid); - spin_unlock(&mm->lock); - return ret; - } - spin_unlock(&mm->lock); - - /*remove mapping entry*/ - spin_lock(&mm->lock); - ret = psb_gtt_mm_remove_free_mem_mapping_locked(&hentry->ht, - key, - &tmp); - if (ret) { - DRM_DEBUG("remove_free failed\n"); - spin_unlock(&mm->lock); - return ret; - } - - *node = tmp; - - /*check the count of mapping entry*/ - if (!hentry->count) { - DRM_DEBUG("count of mapping entry is zero, tgid=%ld\n", tgid); - psb_gtt_mm_remove_free_ht_locked(mm, tgid); - } - - spin_unlock(&mm->lock); - - return 0; -} - -static int psb_gtt_mm_alloc_mem(struct psb_gtt_mm *mm, - uint32_t pages, - uint32_t align, - struct drm_mm_node **node) -{ - struct drm_mm_node *tmp_node; - int ret; - - do { - ret = drm_mm_pre_get(&mm->base); - if (unlikely(ret)) { - DRM_DEBUG("drm_mm_pre_get error\n"); - return ret; - } - - spin_lock(&mm->lock); - tmp_node = drm_mm_search_free(&mm->base, pages, align, 1); - if (unlikely(!tmp_node)) { - DRM_DEBUG("No free node found\n"); - spin_unlock(&mm->lock); - break; - } - - tmp_node = drm_mm_get_block_atomic(tmp_node, pages, align); - spin_unlock(&mm->lock); - } while (!tmp_node); - - if (!tmp_node) { - DRM_DEBUG("Node allocation failed\n"); - return -ENOMEM; - } - - *node = tmp_node; - return 0; -} - -static void psb_gtt_mm_free_mem(struct psb_gtt_mm *mm, struct drm_mm_node *node) -{ - spin_lock(&mm->lock); - drm_mm_put_block(node); - spin_unlock(&mm->lock); -} - -int psb_gtt_map_meminfo(struct drm_device *dev, - void *hKernelMemInfo, - uint32_t *offset) -{ - return -EINVAL; - /* FIXMEAC */ -#if 0 - struct drm_psb_private *dev_priv - = (struct drm_psb_private *)dev->dev_private; - void *psKernelMemInfo; - struct psb_gtt_mm *mm = dev_priv->gtt_mm; - struct psb_gtt *pg = dev_priv->pg; - uint32_t size, pages, offset_pages; - void *kmem; - struct drm_mm_node *node; - struct page **page_list; - struct psb_gtt_mem_mapping *mapping = NULL; - int ret; - - ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo); - if (ret) { - DRM_DEBUG("Cannot find kernelMemInfo handle %ld\n", - hKernelMemInfo); - return -EINVAL; - } - - DRM_DEBUG("Got psKernelMemInfo %p for handle %lx\n", - psKernelMemInfo, (u32)hKernelMemInfo); - size = psKernelMemInfo->ui32AllocSize; - kmem = psKernelMemInfo->pvLinAddrKM; - pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; - - DRM_DEBUG("KerMemInfo size %ld, cpuVadr %lx, pages %ld, osMemHdl %lx\n", - size, kmem, pages, psKernelMemInfo->sMemBlk.hOSMemHandle); - - if (!kmem) - DRM_DEBUG("kmem is NULL"); - - /*get pages*/ - ret = psb_get_pages_by_mem_handle(psKernelMemInfo->sMemBlk.hOSMemHandle, - &page_list); - if (ret) { - DRM_DEBUG("get pages error\n"); - return ret; - } - - DRM_DEBUG("get %ld pages\n", pages); - - /*alloc memory in TT apeture*/ - ret = psb_gtt_mm_alloc_mem(mm, pages, 0, &node); - if (ret) { - DRM_DEBUG("alloc TT memory error\n"); - goto failed_pages_alloc; - } - - /*update psb_gtt_mm*/ - ret = psb_gtt_add_node(mm, - task_tgid_nr(current), - (u32)hKernelMemInfo, - node, - &mapping); - if (ret) { - DRM_DEBUG("add_node failed"); - goto failed_add_node; - } - - node = mapping->node; - offset_pages = node->start; - - DRM_DEBUG("get free node for %ld pages, offset %ld pages", - pages, offset_pages); - - /*update gtt*/ - psb_gtt_insert_pages(pg, page_list, - (unsigned)offset_pages, - (unsigned)pages, - 0, - 0, - 0); - - *offset = offset_pages; - return 0; - -failed_add_node: - psb_gtt_mm_free_mem(mm, node); -failed_pages_alloc: - kfree(page_list); - return ret; -#endif -} - -int psb_gtt_unmap_meminfo(struct drm_device *dev, void * hKernelMemInfo) -{ - struct drm_psb_private *dev_priv - = (struct drm_psb_private *)dev->dev_private; - struct psb_gtt_mm *mm = dev_priv->gtt_mm; - struct psb_gtt *pg = dev_priv->pg; - uint32_t pages, offset_pages; - struct drm_mm_node *node; - int ret; - - ret = psb_gtt_remove_node(mm, - task_tgid_nr(current), - (u32)hKernelMemInfo, - &node); - if (ret) { - DRM_DEBUG("remove node failed\n"); - return ret; - } - - /*remove gtt entries*/ - offset_pages = node->start; - pages = node->size; - - psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1); - - - /*free tt node*/ - - psb_gtt_mm_free_mem(mm, node); - return 0; -} - -int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct psb_gtt_mapping_arg *arg - = (struct psb_gtt_mapping_arg *)data; - uint32_t *offset_pages = &arg->offset_pages; - - DRM_DEBUG("\n"); - - return psb_gtt_map_meminfo(dev, arg->hKernelMemInfo, offset_pages); -} - -int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - - struct psb_gtt_mapping_arg *arg - = (struct psb_gtt_mapping_arg *)data; - - DRM_DEBUG("\n"); - - return psb_gtt_unmap_meminfo(dev, arg->hKernelMemInfo); -} - -int psb_gtt_map_pvr_memory(struct drm_device *dev, unsigned int hHandle, - unsigned int ui32TaskId, dma_addr_t *pPages, - unsigned int ui32PagesNum, unsigned int *ui32Offset) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_gtt_mm *mm = dev_priv->gtt_mm; - struct psb_gtt *pg = dev_priv->pg; - uint32_t size, pages, offset_pages; - struct drm_mm_node *node = NULL; - struct psb_gtt_mem_mapping *mapping = NULL; - int ret; - - size = ui32PagesNum * PAGE_SIZE; - pages = 0; - - /*alloc memory in TT apeture*/ - ret = psb_gtt_mm_alloc_mem(mm, ui32PagesNum, 0, &node); - if (ret) { - DRM_DEBUG("alloc TT memory error\n"); - goto failed_pages_alloc; - } - - /*update psb_gtt_mm*/ - ret = psb_gtt_add_node(mm, - (u32)ui32TaskId, - (u32)hHandle, - node, - &mapping); - if (ret) { - DRM_DEBUG("add_node failed"); - goto failed_add_node; - } - - node = mapping->node; - offset_pages = node->start; - - DRM_DEBUG("get free node for %ld pages, offset %ld pages", - pages, offset_pages); - - /*update gtt*/ - psb_gtt_insert_phys_addresses(pg, pPages, (unsigned)offset_pages, - (unsigned)ui32PagesNum, 0); - - *ui32Offset = offset_pages; - return 0; - -failed_add_node: - psb_gtt_mm_free_mem(mm, node); -failed_pages_alloc: - return ret; -} - - -int psb_gtt_unmap_pvr_memory(struct drm_device *dev, unsigned int hHandle, - unsigned int ui32TaskId) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_gtt_mm *mm = dev_priv->gtt_mm; - struct psb_gtt *pg = dev_priv->pg; - uint32_t pages, offset_pages; - struct drm_mm_node *node; - int ret; - - ret = psb_gtt_remove_node(mm, (u32)ui32TaskId, (u32)hHandle, &node); - if (ret) { - printk(KERN_ERR "remove node failed\n"); - return ret; - } - - /*remove gtt entries*/ - offset_pages = node->start; - pages = node->size; - - psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1); - - /*free tt node*/ - psb_gtt_mm_free_mem(mm, node); - return 0; -} diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h index 0272f83b461e..535ae00f2ab9 100644 --- a/drivers/staging/gma500/psb_gtt.h +++ b/drivers/staging/gma500/psb_gtt.h @@ -22,84 +22,40 @@ #include <drm/drmP.h> -/*#include "img_types.h"*/ - struct psb_gtt { struct drm_device *dev; - int initialized; uint32_t gatt_start; uint32_t mmu_gatt_start; - uint32_t ci_start; - uint32_t rar_start; uint32_t gtt_start; uint32_t gtt_phys_start; unsigned gtt_pages; unsigned gatt_pages; - uint32_t stolen_base; - void *vram_addr; - uint32_t pge_ctl; - u16 gmch_ctrl; unsigned long stolen_size; unsigned long vram_stolen_size; - unsigned long ci_stolen_size; - unsigned long rar_stolen_size; - uint32_t *gtt_map; struct rw_semaphore sem; }; -struct psb_gtt_mm { - struct drm_mm base; - struct drm_open_hash hash; - uint32_t count; - spinlock_t lock; -}; - -struct psb_gtt_hash_entry { - struct drm_open_hash ht; - uint32_t count; - struct drm_hash_item item; -}; - -struct psb_gtt_mem_mapping { - struct drm_mm_node *node; - struct drm_hash_item item; -}; - /*Exported functions*/ -extern int psb_gtt_init(struct psb_gtt *pg, int resume); -extern int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages, - unsigned offset_pages, unsigned num_pages, - unsigned desired_tile_stride, - unsigned hw_tile_stride, int type); -extern int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages, - unsigned num_pages, - unsigned desired_tile_stride, - unsigned hw_tile_stride, - int rc_prot); - -extern struct psb_gtt *psb_gtt_alloc(struct drm_device *dev); -extern void psb_gtt_takedown(struct psb_gtt *pg, int free); -extern int psb_gtt_map_meminfo(struct drm_device *dev, - void * hKernelMemInfo, - uint32_t *offset); -extern int psb_gtt_unmap_meminfo(struct drm_device *dev, - void * hKernelMemInfo); -extern int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int psb_gtt_mm_init(struct psb_gtt *pg); -extern void psb_gtt_mm_takedown(void); - -extern int psb_gtt_map_pvr_memory(struct drm_device *dev, - unsigned int hHandle, - unsigned int ui32TaskId, - dma_addr_t *pPages, - unsigned int ui32PagesNum, - unsigned int *ui32Offset); +extern int psb_gtt_init(struct drm_device *dev, int resume); +extern void psb_gtt_takedown(struct drm_device *dev); + +/* Each gtt_range describes an allocation in the GTT area */ +struct gtt_range { + struct resource resource; + u32 offset; + struct kref kref; + struct drm_gem_object gem; /* GEM high level stuff */ + int in_gart; /* Currently in the GART (ref ct) */ + bool stolen; /* Backed from stolen RAM */ + bool mmapping; /* Is mmappable */ + struct page **pages; /* Backing pages if present */ +}; -extern int psb_gtt_unmap_pvr_memory(struct drm_device *dev, - unsigned int hHandle, - unsigned int ui32TaskId); +extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, + const char *name, int backed); +extern void psb_gtt_kref_put(struct gtt_range *gt); +extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt); +extern int psb_gtt_pin(struct gtt_range *gt); +extern void psb_gtt_unpin(struct gtt_range *gt); #endif diff --git a/drivers/staging/gma500/psb_intel_bios.c b/drivers/staging/gma500/psb_intel_bios.c index 48ac8ba7f40b..417965da5e24 100644 --- a/drivers/staging/gma500/psb_intel_bios.c +++ b/drivers/staging/gma500/psb_intel_bios.c @@ -154,10 +154,15 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, fill_detail_timing_data(panel_fixed_mode, dvo_timing); - dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; - - DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); - drm_mode_debug_printmodeline(panel_fixed_mode); + if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) { + dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; + DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); + drm_mode_debug_printmodeline(panel_fixed_mode); + } else { + DRM_DEBUG("Ignoring bogus LVDS VBT mode.\n"); + dev_priv->lvds_vbt = 0; + kfree(panel_fixed_mode); + } return; } diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c index 80b37f4ca10a..4f47d09d65de 100644 --- a/drivers/staging/gma500/psb_intel_display.c +++ b/drivers/staging/gma500/psb_intel_display.c @@ -341,9 +341,8 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc, /* struct drm_i915_master_private *master_priv; */ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); - struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev; int pipe = psb_intel_crtc->pipe; - unsigned long Start, Offset; + unsigned long start, offset; int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; @@ -359,12 +358,17 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc, return 0; } - if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_FORCE_POWER_ON)) + if (!gma_power_begin(dev, true)) return 0; - Start = mode_dev->bo_offset(dev, psbfb); - Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); + /* We are displaying this buffer, make sure it is actually loaded + into the GTT */ + ret = psb_gtt_pin(psbfb->gtt); + if (ret < 0) + goto psb_intel_pipe_set_base_exit; + start = psbfb->gtt->offset; + + offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); REG_WRITE(dspstride, crtc->fb->pitch); @@ -388,25 +392,29 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc, default: DRM_ERROR("Unknown color depth\n"); ret = -EINVAL; + psb_gtt_unpin(psbfb->gtt); goto psb_intel_pipe_set_base_exit; } REG_WRITE(dspcntr_reg, dspcntr); - DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); + + DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y); if (0 /* FIXMEAC - check what PSB needs */) { - REG_WRITE(dspbase, Offset); + REG_WRITE(dspbase, offset); REG_READ(dspbase); - REG_WRITE(dspsurf, Start); + REG_WRITE(dspsurf, start); REG_READ(dspsurf); } else { - REG_WRITE(dspbase, Start + Offset); + REG_WRITE(dspbase, start + offset); REG_READ(dspbase); } -psb_intel_pipe_set_base_exit: - - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + /* If there was a previous display we can now unpin it */ + if (old_fb) + psb_gtt_unpin(to_psb_fb(old_fb)->gtt); +psb_intel_pipe_set_base_exit: + gma_power_end(dev); return ret; } @@ -816,8 +824,7 @@ void psb_intel_crtc_load_lut(struct drm_crtc *crtc) return; } - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { for (i = 0; i < 256; i++) { REG_WRITE(palreg + 4 * i, ((psb_intel_crtc->lut_r[i] + @@ -827,7 +834,7 @@ void psb_intel_crtc_load_lut(struct drm_crtc *crtc) (psb_intel_crtc->lut_b[i] + psb_intel_crtc->lut_adj[i])); } - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else { for (i = 0; i < 256; i++) { dev_priv->save_palette_a[i] = @@ -1022,19 +1029,14 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, uint32_t width, uint32_t height) { struct drm_device *dev = crtc->dev; - struct drm_psb_private *dev_priv = - (struct drm_psb_private *)dev->dev_private; - struct psb_gtt *pg = dev_priv->pg; struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev; int pipe = psb_intel_crtc->pipe; uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; uint32_t temp; size_t addr = 0; - uint32_t page_offset; - size_t size; - void *bo; + struct gtt_range *gt; + struct drm_gem_object *obj; int ret; DRM_DEBUG("\n"); @@ -1043,22 +1045,21 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, if (!handle) { DRM_DEBUG("cursor off\n"); /* turn off the cursor */ - temp = 0; - temp |= CURSOR_MODE_DISABLE; + temp = CURSOR_MODE_DISABLE; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { REG_WRITE(control, temp); REG_WRITE(base, 0); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } - /* unpin the old bo */ - if (psb_intel_crtc->cursor_bo) { - mode_dev->bo_unpin_for_scanout(dev, - psb_intel_crtc-> - cursor_bo); - psb_intel_crtc->cursor_bo = NULL; + /* Unpin the old GEM object */ + if (psb_intel_crtc->cursor_obj) { + gt = container_of(psb_intel_crtc->cursor_obj, + struct gtt_range, gem); + psb_gtt_unpin(gt); + drm_gem_object_unreference(psb_intel_crtc->cursor_obj); + psb_intel_crtc->cursor_obj = NULL; } return 0; @@ -1070,32 +1071,26 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, return -EINVAL; } - bo = mode_dev->bo_from_handle(dev, file_priv, handle); - if (!bo) + obj = drm_gem_object_lookup(dev, file_priv, handle); + if (!obj) return -ENOENT; - ret = mode_dev->bo_pin_for_scanout(dev, bo); - if (ret) - return ret; - size = mode_dev->bo_size(dev, bo); - if (size < width * height * 4) { + if (obj->size < width * height * 4) { DRM_ERROR("buffer is to small\n"); return -ENOMEM; } - /*insert this bo into gtt*/ - DRM_DEBUG("%s: map meminfo for hw cursor. handle %x\n", - __func__, handle); + gt = container_of(obj, struct gtt_range, gem); - ret = psb_gtt_map_meminfo(dev, (void *)handle, &page_offset); + /* Pin the memory into the GTT */ + ret = psb_gtt_pin(gt); if (ret) { - DRM_ERROR("Can not map meminfo to GTT. handle 0x%x\n", handle); + DRM_ERROR("Can not pin down handle 0x%x\n", handle); return ret; } - addr = page_offset << PAGE_SHIFT; - addr += pg->stolen_base; + addr = gt->offset; /* Or resource.start ??? */ psb_intel_crtc->cursor_addr = addr; @@ -1104,17 +1099,19 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, temp |= (pipe << 28); temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { REG_WRITE(control, temp); REG_WRITE(base, addr); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } /* unpin the old bo */ - if (psb_intel_crtc->cursor_bo && psb_intel_crtc->cursor_bo != bo) { - mode_dev->bo_unpin_for_scanout(dev, psb_intel_crtc->cursor_bo); - psb_intel_crtc->cursor_bo = bo; + if (psb_intel_crtc->cursor_obj && psb_intel_crtc->cursor_obj != obj) { + gt = container_of(psb_intel_crtc->cursor_obj, + struct gtt_range, gem); + psb_gtt_unpin(gt); + drm_gem_object_unreference(psb_intel_crtc->cursor_obj); + psb_intel_crtc->cursor_obj = obj; } return 0; @@ -1126,7 +1123,7 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); int pipe = psb_intel_crtc->pipe; uint32_t temp = 0; - uint32_t adder; + uint32_t addr; if (x < 0) { @@ -1141,13 +1138,12 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); - adder = psb_intel_crtc->cursor_addr; + addr = psb_intel_crtc->cursor_addr; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); - REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr); + gma_power_end(dev); } return 0; } @@ -1197,15 +1193,14 @@ static int psb_intel_crtc_clock_get(struct drm_device *dev, bool is_lvds; struct drm_psb_private *dev_priv = dev->dev_private; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) fp = REG_READ((pipe == 0) ? FPA0 : FPB0); else fp = REG_READ((pipe == 0) ? FPA1 : FPB1); is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else { dpll = (pipe == 0) ? dev_priv->saveDPLL_A : dev_priv->saveDPLL_B; @@ -1277,13 +1272,12 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, int vsync; struct drm_psb_private *dev_priv = dev->dev_private; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else { htot = (pipe == 0) ? dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B; @@ -1318,7 +1312,16 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, static void psb_intel_crtc_destroy(struct drm_crtc *crtc) { struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - + struct gtt_range *gt; + + /* Unpin the old GEM object */ + if (psb_intel_crtc->cursor_obj) { + gt = container_of(psb_intel_crtc->cursor_obj, + struct gtt_range, gem); + psb_gtt_unpin(gt); + drm_gem_object_unreference(psb_intel_crtc->cursor_obj); + psb_intel_crtc->cursor_obj = NULL; + } kfree(psb_intel_crtc->crtc_state); drm_crtc_cleanup(crtc); kfree(psb_intel_crtc); @@ -1333,10 +1336,6 @@ static const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { .commit = psb_intel_crtc_commit, }; -static const struct drm_crtc_helper_funcs mrst_helper_funcs; -static const struct drm_crtc_helper_funcs mdfld_helper_funcs; -const struct drm_crtc_funcs mdfld_intel_crtc_funcs; - const struct drm_crtc_funcs psb_intel_crtc_funcs = { .save = psb_intel_crtc_save, .restore = psb_intel_crtc_restore, @@ -1397,7 +1396,11 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, psb_intel_crtc->mode_dev = mode_dev; psb_intel_crtc->cursor_addr = 0; - drm_crtc_helper_add(&psb_intel_crtc->base, + if (IS_MRST(dev)) + drm_crtc_helper_add(&psb_intel_crtc->base, + &mrst_helper_funcs); + else + drm_crtc_helper_add(&psb_intel_crtc->base, &psb_intel_helper_funcs); /* Setup the array of drm_connector pointer array */ diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h index f6229c56de40..6006ddd993f2 100644 --- a/drivers/staging/gma500/psb_intel_drv.h +++ b/drivers/staging/gma500/psb_intel_drv.h @@ -76,13 +76,7 @@ struct psb_intel_mode_device { /* * Abstracted memory manager operations */ - void *(*bo_from_handle) (struct drm_device *dev, - struct drm_file *file_priv, - unsigned int handle); - size_t(*bo_size) (struct drm_device *dev, void *bo); size_t(*bo_offset) (struct drm_device *dev, void *bo); - int (*bo_pin_for_scanout) (struct drm_device *dev, void *bo); - int (*bo_unpin_for_scanout) (struct drm_device *dev, void *bo); /* * Cursor @@ -156,11 +150,8 @@ struct psb_intel_crtc { /* a mode_set for fbdev users on this crtc */ struct drm_mode_set mode_set; - /* current bo we scanout from */ - void *scanout_bo; - - /* current bo we cursor from */ - void *cursor_bo; + /* GEM object that holds our cursor */ + struct drm_gem_object *cursor_obj; struct drm_display_mode saved_mode; struct drm_display_mode saved_adjusted_mode; diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c index d3d210a1026a..b0a225b9f562 100644 --- a/drivers/staging/gma500/psb_intel_lvds.c +++ b/drivers/staging/gma500/psb_intel_lvds.c @@ -32,13 +32,6 @@ #include "psb_powermgmt.h" #include <linux/pm_runtime.h> -/* MRST defines start */ -uint8_t blc_freq; -uint8_t blc_minbrightness; -uint8_t blc_i2caddr; -uint8_t blc_brightnesscmd; -int lvds_backlight; /* restore backlight to this value */ - u32 CoreClock; u32 PWMControlRegFreq; @@ -83,13 +76,12 @@ static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev) struct drm_psb_private *dev_priv = dev->dev_private; u32 retVal; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { retVal = ((REG_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >> BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else retVal = ((dev_priv->saveBLC_PWM_CTL & BACKLIGHT_MODULATION_FREQ_MASK) >> @@ -98,8 +90,11 @@ static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev) return retVal; } -/** +/* * Set LVDS backlight level by I2C command + * + * FIXME: at some point we need to both track this for PM and also + * disable runtime pm on MRST if the brightness is nil (ie blanked) */ static int psb_lvds_i2c_set_brightness(struct drm_device *dev, unsigned int level) @@ -132,7 +127,7 @@ static int psb_lvds_i2c_set_brightness(struct drm_device *dev, if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) { DRM_DEBUG("I2C set brightness.(command, value) (%d, %d)\n", - blc_brightnesscmd, + dev_priv->lvds_bl->brightnesscmd, blc_i2c_brightness); return 0; } @@ -200,14 +195,13 @@ static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level) struct drm_psb_private *dev_priv = dev->dev_private; u32 blc_pwm_ctl; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { blc_pwm_ctl = REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; REG_WRITE(BLC_PWM_CTL, (blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } else { blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL & ~BACKLIGHT_DUTY_CYCLE_MASK; @@ -224,8 +218,7 @@ static void psb_intel_lvds_set_power(struct drm_device *dev, { u32 pp_status; - if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_FORCE_POWER_ON)) + if (!gma_power_begin(dev, true)) return; if (on) { @@ -248,7 +241,7 @@ static void psb_intel_lvds_set_power(struct drm_device *dev, } while (pp_status & PP_ON); } - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) @@ -400,11 +393,15 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, if (psb_intel_output->type == INTEL_OUTPUT_MIPI2) panel_fixed_mode = mode_dev->panel_fixed_mode2; - /* PSB doesn't appear to be GEN4 */ - if (psb_intel_crtc->pipe == 0) { + /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */ + if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) { printk(KERN_ERR "Can't support LVDS on pipe A\n"); return false; } + if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) { + printk(KERN_ERR "Must use PIPE A\n"); + return false; + } /* Should never happen!! */ list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { @@ -445,7 +442,7 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, return true; } -static void psb_intel_lvds_prepare(struct drm_encoder *encoder) +void psb_intel_lvds_prepare(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct psb_intel_output *output = enc_to_psb_intel_output(encoder); @@ -453,8 +450,7 @@ static void psb_intel_lvds_prepare(struct drm_encoder *encoder) PSB_DEBUG_ENTRY("\n"); - if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_FORCE_POWER_ON)) + if (!gma_power_begin(dev, true)) return; mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); @@ -463,10 +459,10 @@ static void psb_intel_lvds_prepare(struct drm_encoder *encoder) psb_intel_lvds_set_power(dev, output, false); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } -static void psb_intel_lvds_commit(struct drm_encoder *encoder) +void psb_intel_lvds_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct psb_intel_output *output = enc_to_psb_intel_output(encoder); @@ -669,14 +665,14 @@ static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = { .commit = psb_intel_lvds_commit, }; -static const struct drm_connector_helper_funcs +const struct drm_connector_helper_funcs psb_intel_lvds_connector_helper_funcs = { .get_modes = psb_intel_lvds_get_modes, .mode_valid = psb_intel_lvds_mode_valid, .best_encoder = psb_intel_best_encoder, }; -static const struct drm_connector_funcs psb_intel_lvds_connector_funcs = { +const struct drm_connector_funcs psb_intel_lvds_connector_funcs = { .dpms = drm_helper_connector_dpms, .save = psb_intel_lvds_save, .restore = psb_intel_lvds_restore, diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c index 1d2bb021c0a5..df1c006ecfaa 100644 --- a/drivers/staging/gma500/psb_intel_sdvo.c +++ b/drivers/staging/gma500/psb_intel_sdvo.c @@ -204,7 +204,7 @@ static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output, struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; int i; - if (1) { + if (0) { DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); for (i = 0; i < args_len; i++) printk(KERN_INFO"%02X ", ((u8 *) args)[i]); @@ -266,7 +266,7 @@ static u8 psb_intel_sdvo_read_response( SDVO_I2C_CMD_STATUS, &status); - if (1) { + if (0) { DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv)); for (i = 0; i < response_len; i++) printk(KERN_INFO"%02X ", ((u8 *) response)[i]); diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c index 4597c8824721..9ea37e588874 100644 --- a/drivers/staging/gma500/psb_irq.c +++ b/drivers/staging/gma500/psb_irq.c @@ -88,13 +88,12 @@ psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) u32 reg = psb_pipestat(pipe); dev_priv->pipestat[pipe] |= mask; /* Enable the interrupt, clear any pending status */ - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev_priv->dev, false)) { u32 writeVal = PSB_RVDC32(reg); writeVal |= (mask | (mask >> 16)); PSB_WVDC32(writeVal, reg); (void) PSB_RVDC32(reg); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev_priv->dev); } } } @@ -105,39 +104,36 @@ psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) if ((dev_priv->pipestat[pipe] & mask) != 0) { u32 reg = psb_pipestat(pipe); dev_priv->pipestat[pipe] &= ~mask; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev_priv->dev, false)) { u32 writeVal = PSB_RVDC32(reg); writeVal &= ~mask; PSB_WVDC32(writeVal, reg); (void) PSB_RVDC32(reg); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev_priv->dev); } } } void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev_priv->dev, false)) { u32 pipe_event = mid_pipe_event(pipe); dev_priv->vdc_irq_mask |= pipe_event; PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev_priv->dev); } } void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe) { if (dev_priv->pipestat[pipe] == 0) { - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev_priv->dev, false)) { u32 pipe_event = mid_pipe_event(pipe); dev_priv->vdc_irq_mask &= ~pipe_event; PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev_priv->dev); } } } @@ -242,7 +238,7 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) vdc_stat &= dev_priv->vdc_irq_mask; spin_unlock(&dev_priv->irqmask_lock); - if (dsp_int && ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) { + if (dsp_int && gma_power_is_on(dev)) { psb_vdc_interrupt(dev, vdc_stat); handled = 1; } @@ -271,54 +267,28 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) void psb_irq_preinstall(struct drm_device *dev) { - psb_irq_preinstall_islands(dev, OSPM_ALL_ISLANDS); -} - -/** - * FIXME: should I remove display irq enable here?? - */ -void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands) -{ struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private; unsigned long irqflags; - PSB_DEBUG_ENTRY("\n"); - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - if (hw_islands & OSPM_DISPLAY_ISLAND) { - if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) { - PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank_enabled[0]) - dev_priv->vdc_irq_mask |= - _PSB_PIPEA_EVENT_FLAG; - if (dev->vblank_enabled[1]) - dev_priv->vdc_irq_mask |= - _MDFLD_PIPEB_EVENT_FLAG; - if (dev->vblank_enabled[2]) - dev_priv->vdc_irq_mask |= - _MDFLD_PIPEC_EVENT_FLAG; - } - } -/* NO I DONT WANT ANY IRQS GRRR FIXMEAC */ - if (hw_islands & OSPM_GRAPHICS_ISLAND) - dev_priv->vdc_irq_mask |= _PSB_IRQ_SGX_FLAG; -/* */ + if (gma_power_is_on(dev)) + PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); + if (dev->vblank_enabled[0]) + dev_priv->vdc_irq_mask |= _PSB_PIPEA_EVENT_FLAG; + if (dev->vblank_enabled[1]) + dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; + if (dev->vblank_enabled[2]) + dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; + /*This register is safe even if display island is off*/ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); } int psb_irq_postinstall(struct drm_device *dev) { - return psb_irq_postinstall_islands(dev, OSPM_ALL_ISLANDS); -} - -int psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands) -{ - struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private; unsigned long irqflags; @@ -327,48 +297,31 @@ int psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands) spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - /*This register is safe even if display island is off*/ + /* This register is safe even if display island is off */ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); + PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (hw_islands & OSPM_DISPLAY_ISLAND) { - if (true/*powermgmt_is_hw_on(dev->pdev, PSB_DISPLAY_ISLAND)*/) { - PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - - if (dev->vblank_enabled[0]) - psb_enable_pipestat(dev_priv, 0, - PIPE_VBLANK_INTERRUPT_ENABLE); - else - psb_disable_pipestat(dev_priv, 0, - PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank_enabled[1]) - psb_enable_pipestat(dev_priv, 1, - PIPE_VBLANK_INTERRUPT_ENABLE); - else - psb_disable_pipestat(dev_priv, 1, - PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank_enabled[2]) - psb_enable_pipestat(dev_priv, 2, - PIPE_VBLANK_INTERRUPT_ENABLE); - else - psb_disable_pipestat(dev_priv, 2, - PIPE_VBLANK_INTERRUPT_ENABLE); - } - } + if (dev->vblank_enabled[0]) + psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); + else + psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); + if (dev->vblank_enabled[1]) + psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); + else + psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); + if (dev->vblank_enabled[2]) + psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); + else + psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); + + spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); return 0; } void psb_irq_uninstall(struct drm_device *dev) { - psb_irq_uninstall_islands(dev, OSPM_ALL_ISLANDS); -} - -void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands) -{ struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private; unsigned long irqflags; @@ -377,39 +330,29 @@ void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands) spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - if (hw_islands & OSPM_DISPLAY_ISLAND) { - if (true/*powermgmt_is_hw_on(dev->pdev, PSB_DISPLAY_ISLAND)*/) { - PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); + PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank_enabled[0]) - psb_disable_pipestat(dev_priv, 0, - PIPE_VBLANK_INTERRUPT_ENABLE); + if (dev->vblank_enabled[0]) + psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[1]) - psb_disable_pipestat(dev_priv, 1, - PIPE_VBLANK_INTERRUPT_ENABLE); + if (dev->vblank_enabled[1]) + psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[2]) - psb_disable_pipestat(dev_priv, 2, - PIPE_VBLANK_INTERRUPT_ENABLE); - } - dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | - _PSB_IRQ_MSVDX_FLAG | - _LNC_IRQ_TOPAZ_FLAG; - } - /*TODO: remove following code*/ - if (hw_islands & OSPM_GRAPHICS_ISLAND) - dev_priv->vdc_irq_mask &= ~_PSB_IRQ_SGX_FLAG; + if (dev->vblank_enabled[2]) + psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); + + dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | + _PSB_IRQ_MSVDX_FLAG | + _LNC_IRQ_TOPAZ_FLAG; - /*These two registers are safe even if display island is off*/ + /* These two registers are safe even if display island is off */ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); wmb(); - /*This register is safe even if display island is off*/ + /* This register is safe even if display island is off */ PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R); - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); } @@ -420,8 +363,7 @@ void psb_irq_turn_on_dpst(struct drm_device *dev) u32 hist_reg; u32 pwm_reg; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL); hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL); @@ -443,7 +385,7 @@ void psb_irq_turn_on_dpst(struct drm_device *dev) PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE, PWM_CONTROL_LOGIC); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } } @@ -472,8 +414,7 @@ void psb_irq_turn_off_dpst(struct drm_device *dev) u32 hist_reg; u32 pwm_reg; - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL); hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); @@ -484,7 +425,7 @@ void psb_irq_turn_off_dpst(struct drm_device *dev) PWM_CONTROL_LOGIC); pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } } @@ -526,18 +467,16 @@ static int psb_vblank_do_wait(struct drm_device *dev, */ int psb_enable_vblank(struct drm_device *dev, int pipe) { - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; + struct drm_psb_private *dev_priv = dev->dev_private; unsigned long irqflags; uint32_t reg_val = 0; uint32_t pipeconf_reg = mid_pipeconf(pipe); PSB_DEBUG_ENTRY("\n"); - if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, - OSPM_UHB_ONLY_IF_ON)) { + if (gma_power_begin(dev, false)) { reg_val = REG_READ(pipeconf_reg); - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); } if (!(reg_val & PIPEACONF_ENABLE)) @@ -545,7 +484,6 @@ int psb_enable_vblank(struct drm_device *dev, int pipe) spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - drm_psb_disable_vsync = 0; mid_enable_pipe_event(dev_priv, pipe); psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); @@ -559,15 +497,13 @@ int psb_enable_vblank(struct drm_device *dev, int pipe) */ void psb_disable_vblank(struct drm_device *dev, int pipe) { - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; + struct drm_psb_private *dev_priv = dev->dev_private; unsigned long irqflags; PSB_DEBUG_ENTRY("\n"); spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - drm_psb_disable_vsync = 1; mid_disable_pipe_event(dev_priv, pipe); psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); @@ -603,7 +539,7 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe) return 0; } - if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, false)) + if (!gma_power_begin(dev, false)) return 0; reg_val = REG_READ(pipeconf_reg); @@ -632,7 +568,7 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe) psb_get_vblank_counter_exit: - ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); + gma_power_end(dev); return count; } diff --git a/drivers/staging/gma500/psb_reset.c b/drivers/staging/gma500/psb_lid.c index 21fd202f2931..21fd202f2931 100644 --- a/drivers/staging/gma500/psb_reset.c +++ b/drivers/staging/gma500/psb_lid.c diff --git a/drivers/staging/gma500/psb_mmu.c b/drivers/staging/gma500/psb_mmu.c index edd0d4923e0f..c904d73b1de3 100644 --- a/drivers/staging/gma500/psb_mmu.c +++ b/drivers/staging/gma500/psb_mmu.c @@ -444,67 +444,6 @@ static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt, pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte; } -#if 0 -static uint32_t psb_mmu_check_pte_locked(struct psb_mmu_pd *pd, - uint32_t mmu_offset) -{ - uint32_t *v; - uint32_t pfn; - - v = kmap_atomic(pd->p, KM_USER0); - if (!v) { - printk(KERN_INFO "Could not kmap pde page.\n"); - return 0; - } - pfn = v[psb_mmu_pd_index(mmu_offset)]; - /* printk(KERN_INFO "pde is 0x%08x\n",pfn); */ - kunmap_atomic(v, KM_USER0); - if (((pfn & 0x0F) != PSB_PTE_VALID)) { - printk(KERN_INFO "Strange pde at 0x%08x: 0x%08x.\n", - mmu_offset, pfn); - } - v = ioremap(pfn & 0xFFFFF000, 4096); - if (!v) { - printk(KERN_INFO "Could not kmap pte page.\n"); - return 0; - } - pfn = v[psb_mmu_pt_index(mmu_offset)]; - /* printk(KERN_INFO "pte is 0x%08x\n",pfn); */ - iounmap(v); - if (((pfn & 0x0F) != PSB_PTE_VALID)) { - printk(KERN_INFO "Strange pte at 0x%08x: 0x%08x.\n", - mmu_offset, pfn); - } - return pfn >> PAGE_SHIFT; -} - -static void psb_mmu_check_mirrored_gtt(struct psb_mmu_pd *pd, - uint32_t mmu_offset, - uint32_t gtt_pages) -{ - uint32_t start; - uint32_t next; - - printk(KERN_INFO "Checking mirrored gtt 0x%08x %d\n", - mmu_offset, gtt_pages); - down_read(&pd->driver->sem); - start = psb_mmu_check_pte_locked(pd, mmu_offset); - mmu_offset += PAGE_SIZE; - gtt_pages -= 1; - while (gtt_pages--) { - next = psb_mmu_check_pte_locked(pd, mmu_offset); - if (next != start + 1) { - printk(KERN_INFO - "Ptes out of order: 0x%08x, 0x%08x.\n", - start, next); - } - start = next; - mmu_offset += PAGE_SIZE; - } - up_read(&pd->driver->sem); -} - -#endif void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset, uint32_t gtt_start, diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/psb_powermgmt.c index 7deb1ba82545..1495415be6c7 100644 --- a/drivers/staging/gma500/psb_powermgmt.c +++ b/drivers/staging/gma500/psb_powermgmt.c @@ -24,83 +24,73 @@ * Authors: * Benjamin Defnet <benjamin.r.defnet@intel.com> * Rajesh Poornachandran <rajesh.poornachandran@intel.com> - * + * Massively reworked + * Alan Cox <alan@linux.intel.com> */ #include "psb_powermgmt.h" #include "psb_drv.h" +#include "psb_reg.h" #include "psb_intel_reg.h" #include <linux/mutex.h> #include <linux/pm_runtime.h> -#undef OSPM_GFX_DPK - -extern u32 gui32SGXDeviceID; -extern u32 gui32MRSTDisplayDeviceID; -extern u32 gui32MRSTMSVDXDeviceID; -extern u32 gui32MRSTTOPAZDeviceID; - -struct drm_device *gpDrmDevice = NULL; static struct mutex power_mutex; -static bool gbSuspendInProgress = false; -static bool gbResumeInProgress = false; -static int g_hw_power_status_mask; -static atomic_t g_display_access_count; -static atomic_t g_graphics_access_count; -static atomic_t g_videoenc_access_count; -static atomic_t g_videodec_access_count; -int allow_runtime_pm = 0; - -void ospm_power_island_up(int hw_islands); -void ospm_power_island_down(int hw_islands); -static bool gbSuspended = false; -bool gbgfxsuspended = false; -/* - * ospm_power_init +/** + * gma_power_init - initialise power manager + * @dev: our device * - * Description: Initialize this ospm power management module + * Set up for power management tracking of our hardware. */ -void ospm_power_init(struct drm_device *dev) +void gma_power_init(struct drm_device *dev) { - struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private; - - gpDrmDevice = dev; + struct drm_psb_private *dev_priv = dev->dev_private; dev_priv->apm_base = dev_priv->apm_reg & 0xffff; dev_priv->ospm_base &= 0xffff; + dev_priv->display_power = true; /* We start active */ + dev_priv->display_count = 0; /* Currently no users */ + dev_priv->suspended = false; /* And not suspended */ mutex_init(&power_mutex); - g_hw_power_status_mask = OSPM_ALL_ISLANDS; - atomic_set(&g_display_access_count, 0); - atomic_set(&g_graphics_access_count, 0); - atomic_set(&g_videoenc_access_count, 0); - atomic_set(&g_videodec_access_count, 0); + + if (!IS_MRST(dev)) { + /* FIXME: wants further review */ + u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); + /* Disable 2D clock gating */ + gating &= ~3; + gating |= 1; + PSB_WSGX32(gating, PSB_CR_CLKGATECTL); + PSB_RSGX32(PSB_CR_CLKGATECTL); + } } -/* - * ospm_power_uninit +/** + * gma_power_uninit - end power manager + * @dev: device to end for * - * Description: Uninitialize this ospm power management module + * Undo the effects of gma_power_init */ -void ospm_power_uninit(void) +void gma_power_uninit(struct drm_device *dev) { mutex_destroy(&power_mutex); - pm_runtime_disable(&gpDrmDevice->pdev->dev); - pm_runtime_set_suspended(&gpDrmDevice->pdev->dev); + pm_runtime_disable(&dev->pdev->dev); + pm_runtime_set_suspended(&dev->pdev->dev); } -/* - * save_display_registers +/** + * save_display_registers - save registers lost on suspend + * @dev: our DRM device * - * Description: We are going to suspend so save current display - * register state. + * Save the state we need in order to be able to restore the interface + * upon resume from suspend */ static int save_display_registers(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_crtc * crtc; - struct drm_connector * connector; + struct drm_crtc *crtc; + struct drm_connector *connector; /* Display arbitration control + watermarks */ dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); @@ -112,37 +102,31 @@ static int save_display_registers(struct drm_device *dev) dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); - /*save crtc and output state*/ + /* Save crtc and output state */ mutex_lock(&dev->mode_config.mutex); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if(drm_helper_crtc_in_use(crtc)) { + if (drm_helper_crtc_in_use(crtc)) crtc->funcs->save(crtc); - } } - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + list_for_each_entry(connector, &dev->mode_config.connector_list, head) connector->funcs->save(connector); - } - mutex_unlock(&dev->mode_config.mutex); - - /* Interrupt state */ - /* - * Handled in psb_irq.c - */ + mutex_unlock(&dev->mode_config.mutex); return 0; } -/* - * restore_display_registers +/** + * restore_display_registers - restore lost register state + * @dev: our DRM device * - * Description: We are going to resume so restore display register state. + * Restore register state that was lost during suspend and resume. */ static int restore_display_registers(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_crtc * crtc; - struct drm_connector * connector; + struct drm_crtc *crtc; + struct drm_connector *connector; /* Display arbitration + watermarks */ PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); @@ -158,39 +142,57 @@ static int restore_display_registers(struct drm_device *dev) PSB_WVDC32(0x80000000, VGACNTRL); mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if(drm_helper_crtc_in_use(crtc)) + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + if (drm_helper_crtc_in_use(crtc)) crtc->funcs->restore(crtc); - } - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - connector->funcs->restore(connector); - } - mutex_unlock(&dev->mode_config.mutex); - /*Interrupt state*/ - /* - * Handled in psb_irq.c - */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + connector->funcs->restore(connector); + mutex_unlock(&dev->mode_config.mutex); return 0; } -/* - * powermgmt_suspend_display + +/** + * power_down - power down the display island + * @dev: our DRM device * - * Description: Suspend the display hardware saving state and disabling - * as necessary. + * Power down the display interface of our device */ -void ospm_suspend_display(struct drm_device *dev) +static void power_down(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; - int pp_stat, ret=0; + u32 pwr_mask ; + u32 pwr_sts; - printk(KERN_ALERT "%s \n", __func__); + if (IS_MRST(dev)) { + pwr_mask = PSB_PWRGT_DISPLAY_MASK; + outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC); -#ifdef OSPM_GFX_DPK - printk(KERN_ALERT "%s \n", __func__); -#endif - if (!(g_hw_power_status_mask & OSPM_DISPLAY_ISLAND)) + while (true) { + pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); + if ((pwr_sts & pwr_mask) == pwr_mask) + break; + else + udelay(10); + } + dev_priv->display_power = false; + } +} + + +/** + * gma_suspend_display - suspend the display logic + * @dev: our DRM device + * + * Suspend the display logic of the graphics interface + */ +static void gma_suspend_display(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + int pp_stat; + + if (dev_priv->suspended) return; save_display_registers(dev); @@ -225,37 +227,58 @@ void ospm_suspend_display(struct drm_device *dev) != DPI_FIFO_EMPTY); PSB_WVDC32(0, DEVICE_READY_REG); /* turn off panel power */ - ret = 0; } - ospm_power_island_down(OSPM_DISPLAY_ISLAND); + power_down(dev); } /* - * ospm_resume_display + * power_up * - * Description: Resume the display hardware restoring state and enabling - * as necessary. + * Description: Restore power to the specified island(s) (powergating) */ -void ospm_resume_display(struct pci_dev *pdev) +static void power_up(struct drm_device *dev) { - struct drm_device *dev = pci_get_drvdata(pdev); struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_gtt *pg = dev_priv->pg; + u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK; + u32 pwr_sts, pwr_cnt; - printk(KERN_ALERT "%s \n", __func__); + if (IS_MRST(dev)) { + pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); + pwr_cnt &= ~pwr_mask; + outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC)); -#ifdef OSPM_GFX_DPK - printk(KERN_ALERT "%s \n", __func__); -#endif - if (g_hw_power_status_mask & OSPM_DISPLAY_ISLAND) + while (true) { + pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); + if ((pwr_sts & pwr_mask) == 0) + break; + else + udelay(10); + } + } + dev_priv->suspended = false; + dev_priv->display_power = true; +} + +/** + * gma_resume_display - resume display side logic + * + * Resume the display hardware restoring state and enabling + * as necessary. + */ +static void gma_resume_display(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct drm_psb_private *dev_priv = dev->dev_private; + + if (dev_priv->suspended == false) return; /* turn on the display power island */ - ospm_power_island_up(OSPM_DISPLAY_ISLAND); + power_up(dev); - PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); + PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); pci_write_config_word(pdev, PSB_GMCH_CTRL, - pg->gmch_ctrl | _PSB_GMCH_ENABLED); + dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); /* Don't reinitialize the GTT as it is unnecessary. The gtt is * stored in memory so it will automatically be restored. All @@ -267,26 +290,21 @@ void ospm_resume_display(struct pci_dev *pdev) restore_display_registers(dev); } -#if 1 -/* - * ospm_suspend_pci +/** + * gma_suspend_pci - suspend PCI side + * @pdev: PCI device * - * Description: Suspend the pci device saving state and disabling - * as necessary. + * Perform the suspend processing on our PCI device state */ -static void ospm_suspend_pci(struct pci_dev *pdev) +static void gma_suspend_pci(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); struct drm_psb_private *dev_priv = dev->dev_private; int bsm, vbt; - if (gbSuspended) + if (dev_priv->suspended) return; -#ifdef OSPM_GFX_DPK - printk(KERN_ALERT "ospm_suspend_pci\n"); -#endif - pci_save_state(pdev); pci_read_config_dword(pdev, 0x5C, &bsm); dev_priv->saveBSM = bsm; @@ -298,29 +316,25 @@ static void ospm_suspend_pci(struct pci_dev *pdev) pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); - gbSuspended = true; - gbgfxsuspended = true; + dev_priv->suspended = true; } -/* - * ospm_resume_pci +/** + * gma_resume_pci - resume helper + * @dev: our PCI device * - * Description: Resume the pci device restoring state and enabling - * as necessary. + * Perform the resume processing on our PCI device state - rewrite + * register state and re-enable the PCI device */ -static bool ospm_resume_pci(struct pci_dev *pdev) +static bool gma_resume_pci(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); struct drm_psb_private *dev_priv = dev->dev_private; - int ret = 0; + int ret; - if (!gbSuspended) + if (!dev_priv->suspended) return true; -#ifdef OSPM_GFX_DPK - printk(KERN_ALERT "ospm_resume_pci\n"); -#endif - pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM); @@ -331,448 +345,131 @@ static bool ospm_resume_pci(struct pci_dev *pdev) ret = pci_enable_device(pdev); if (ret != 0) - printk(KERN_ALERT "ospm_resume_pci: pci_enable_device failed: %d\n", ret); + dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); else - gbSuspended = false; - - return !gbSuspended; -} -#endif -/* - * ospm_power_suspend - * - * Description: OSPM is telling our driver to suspend so save state - * and power down all hardware. - */ -int ospm_power_suspend(struct pci_dev *pdev, pm_message_t state) -{ - int ret = 0; - int graphics_access_count; - int videoenc_access_count; - int videodec_access_count; - int display_access_count; - bool suspend_pci = true; - - if(gbSuspendInProgress || gbResumeInProgress) - { -#ifdef OSPM_GFX_DPK - printk(KERN_ALERT "OSPM_GFX_DPK: %s system BUSY \n", __func__); -#endif - return -EBUSY; - } - - mutex_lock(&power_mutex); - - if (!gbSuspended) { - graphics_access_count = atomic_read(&g_graphics_access_count); - videoenc_access_count = atomic_read(&g_videoenc_access_count); - videodec_access_count = atomic_read(&g_videodec_access_count); - display_access_count = atomic_read(&g_display_access_count); - - if (graphics_access_count || - videoenc_access_count || - videodec_access_count || - display_access_count) - ret = -EBUSY; - - if (!ret) { - gbSuspendInProgress = true; - - psb_irq_uninstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND); - ospm_suspend_display(gpDrmDevice); - if (suspend_pci == true) { - ospm_suspend_pci(pdev); - } - gbSuspendInProgress = false; - } else { - printk(KERN_ALERT "ospm_power_suspend: device busy: graphics %d videoenc %d videodec %d display %d\n", graphics_access_count, videoenc_access_count, videodec_access_count, display_access_count); - } - } - - - mutex_unlock(&power_mutex); - return ret; + dev_priv->suspended = false; + return !dev_priv->suspended; } -/* - * ospm_power_island_up +/** + * gma_power_suspend - bus callback for suspend + * @pdev: our PCI device + * @state: suspend type * - * Description: Restore power to the specified island(s) (powergating) + * Called back by the PCI layer during a suspend of the system. We + * perform the necessary shut down steps and save enough state that + * we can undo this when resume is called. */ -void ospm_power_island_up(int hw_islands) +int gma_power_suspend(struct pci_dev *pdev, pm_message_t state) { - u32 pwr_cnt = 0; - u32 pwr_sts = 0; - u32 pwr_mask = 0; - - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) gpDrmDevice->dev_private; - - - if (hw_islands & OSPM_DISPLAY_ISLAND) { - pwr_mask = PSB_PWRGT_DISPLAY_MASK; - - pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); - pwr_cnt &= ~pwr_mask; - outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC)); + struct drm_device *dev = pci_get_drvdata(pdev); + struct drm_psb_private *dev_priv = dev->dev_private; - while (true) { - pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); - if ((pwr_sts & pwr_mask) == 0) - break; - else - udelay(10); + mutex_lock(&power_mutex); + if (!dev_priv->suspended) { + if (dev_priv->display_count) { + mutex_unlock(&power_mutex); + return -EBUSY; } + psb_irq_uninstall(dev); + gma_suspend_display(dev); + gma_suspend_pci(pdev); } - - g_hw_power_status_mask |= hw_islands; -} - -/* - * ospm_power_resume - */ -int ospm_power_resume(struct pci_dev *pdev) -{ - if(gbSuspendInProgress || gbResumeInProgress) - { -#ifdef OSPM_GFX_DPK - printk(KERN_ALERT "OSPM_GFX_DPK: %s hw_island: Suspend || gbResumeInProgress!!!! \n", __func__); -#endif - return 0; - } - - mutex_lock(&power_mutex); - -#ifdef OSPM_GFX_DPK - printk(KERN_ALERT "OSPM_GFX_DPK: ospm_power_resume \n"); -#endif - - gbResumeInProgress = true; - - ospm_resume_pci(pdev); - - ospm_resume_display(gpDrmDevice->pdev); - psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND); - psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND); - - gbResumeInProgress = false; - - mutex_unlock(&power_mutex); - + mutex_unlock(&power_mutex); return 0; } -/* - * ospm_power_island_down +/** + * gma_power_resume - resume power + * @pdev: PCI device * - * Description: Cut power to the specified island(s) (powergating) + * Resume the PCI side of the graphics and then the displays */ -void ospm_power_island_down(int islands) +int gma_power_resume(struct pci_dev *pdev) { -#if 0 - u32 pwr_cnt = 0; - u32 pwr_mask = 0; - u32 pwr_sts = 0; - - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) gpDrmDevice->dev_private; - - g_hw_power_status_mask &= ~islands; - - if (islands & OSPM_GRAPHICS_ISLAND) { - pwr_cnt |= PSB_PWRGT_GFX_MASK; - pwr_mask |= PSB_PWRGT_GFX_MASK; - if (dev_priv->graphics_state == PSB_PWR_STATE_ON) { - dev_priv->gfx_on_time += (jiffies - dev_priv->gfx_last_mode_change) * 1000 / HZ; - dev_priv->gfx_last_mode_change = jiffies; - dev_priv->graphics_state = PSB_PWR_STATE_OFF; - dev_priv->gfx_off_cnt++; - } - } - if (islands & OSPM_VIDEO_ENC_ISLAND) { - pwr_cnt |= PSB_PWRGT_VID_ENC_MASK; - pwr_mask |= PSB_PWRGT_VID_ENC_MASK; - } - if (islands & OSPM_VIDEO_DEC_ISLAND) { - pwr_cnt |= PSB_PWRGT_VID_DEC_MASK; - pwr_mask |= PSB_PWRGT_VID_DEC_MASK; - } - if (pwr_cnt) { - pwr_cnt |= inl(dev_priv->apm_base); - outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); - while (true) { - pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); - - if ((pwr_sts & pwr_mask) == pwr_mask) - break; - else - udelay(10); - } - } - - if (islands & OSPM_DISPLAY_ISLAND) { - pwr_mask = PSB_PWRGT_DISPLAY_MASK; - - outl(pwr_mask, (dev_priv->ospm_base + PSB_PM_SSC)); + struct drm_device *dev = pci_get_drvdata(pdev); - while (true) { - pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); - if ((pwr_sts & pwr_mask) == pwr_mask) - break; - else - udelay(10); - } - } -#endif + mutex_lock(&power_mutex); + gma_resume_pci(pdev); + gma_resume_display(pdev); + psb_irq_preinstall(dev); + psb_irq_postinstall(dev); + mutex_unlock(&power_mutex); + return 0; } -/* - * ospm_power_is_hw_on + +/** + * gma_power_is_on - returne true if power is on + * @dev: our DRM device * - * Description: do an instantaneous check for if the specified islands - * are on. Only use this in cases where you know the g_state_change_mutex - * is already held such as in irq install/uninstall. Otherwise, use - * ospm_power_using_hw_begin(). + * Returns true if the display island power is on at this moment */ -bool ospm_power_is_hw_on(int hw_islands) +bool gma_power_is_on(struct drm_device *dev) { - return ((g_hw_power_status_mask & hw_islands) == hw_islands) ? true:false; + struct drm_psb_private *dev_priv = dev->dev_private; + return dev_priv->display_power; } -/* - * ospm_power_using_hw_begin + +/** + * gma_power_begin - begin requiring power + * @dev: our DRM device + * @force_on: true to force power on * - * Description: Notify PowerMgmt module that you will be accessing the - * specified island's hw so don't power it off. If force_on is true, - * this will power on the specified island if it is off. - * Otherwise, this will return false and the caller is expected to not - * access the hw. + * Begin an action that requires the display power island is enabled. + * We refcount the islands. * - * NOTE *** If this is called from and interrupt handler or other atomic - * context, then it will return false if we are in the middle of a - * power state transition and the caller will be expected to handle that - * even if force_on is set to true. + * FIXME: locking */ -bool ospm_power_using_hw_begin(int hw_island, UHBUsage usage) +bool gma_power_begin(struct drm_device *dev, bool force_on) { - return 1; /*FIXMEAC */ -#if 0 - bool ret = true; - bool island_is_off = false; - bool b_atomic = (in_interrupt() || in_atomic()); - bool locked = true; - struct pci_dev *pdev = gpDrmDevice->pdev; - u32 deviceID = 0; - bool force_on = usage ? true: false; - /*quick path, not 100% race safe, but should be enough comapre to current other code in this file */ - if (!force_on) { - if (hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask)) - return false; - else { - locked = false; -#ifdef CONFIG_PM_RUNTIME - /* increment pm_runtime_refcount */ - pm_runtime_get(&pdev->dev); -#endif - goto increase_count; - } - } - - - if (!b_atomic) - mutex_lock(&power_mutex); - - island_is_off = hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask); - - if (b_atomic && (gbSuspendInProgress || gbResumeInProgress || gbSuspended) && force_on && island_is_off) - ret = false; - - if (ret && island_is_off && !force_on) - ret = false; - - if (ret && island_is_off && force_on) { - gbResumeInProgress = true; - - ret = ospm_resume_pci(pdev); - - if (ret) { - switch(hw_island) - { - case OSPM_DISPLAY_ISLAND: - deviceID = gui32MRSTDisplayDeviceID; - ospm_resume_display(pdev); - psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND); - psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND); - break; - case OSPM_GRAPHICS_ISLAND: - deviceID = gui32SGXDeviceID; - ospm_power_island_up(OSPM_GRAPHICS_ISLAND); - psb_irq_preinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND); - psb_irq_postinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND); - break; -#if 1 - case OSPM_VIDEO_DEC_ISLAND: - if(!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) { - //printk(KERN_ALERT "%s power on display for video decode use\n", __func__); - deviceID = gui32MRSTDisplayDeviceID; - ospm_resume_display(pdev); - psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND); - psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND); - } - else{ - //printk(KERN_ALERT "%s display is already on for video decode use\n", __func__); - } - - if(!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) { - //printk(KERN_ALERT "%s power on video decode\n", __func__); - deviceID = gui32MRSTMSVDXDeviceID; - ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND); - psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND); - psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND); - } - else{ - //printk(KERN_ALERT "%s video decode is already on\n", __func__); - } - - break; - case OSPM_VIDEO_ENC_ISLAND: - if(!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) { - //printk(KERN_ALERT "%s power on display for video encode\n", __func__); - deviceID = gui32MRSTDisplayDeviceID; - ospm_resume_display(pdev); - psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND); - psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND); - } - else{ - //printk(KERN_ALERT "%s display is already on for video encode use\n", __func__); - } - - if(!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) { - //printk(KERN_ALERT "%s power on video encode\n", __func__); - deviceID = gui32MRSTTOPAZDeviceID; - ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND); - psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND); - psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND); - } - else{ - //printk(KERN_ALERT "%s video decode is already on\n", __func__); - } -#endif - break; - - default: - printk(KERN_ALERT "%s unknown island !!!! \n", __func__); - break; - } - - } - - if (!ret) - printk(KERN_ALERT "ospm_power_using_hw_begin: forcing on %d failed\n", hw_island); + struct drm_psb_private *dev_priv = dev->dev_private; + int ret; - gbResumeInProgress = false; + /* Power already on ? */ + if (dev_priv->display_power) { + dev_priv->display_count++; + pm_runtime_get(&dev->pdev->dev); + return true; } -increase_count: - if (ret) { - switch(hw_island) - { - case OSPM_GRAPHICS_ISLAND: - atomic_inc(&g_graphics_access_count); - break; - case OSPM_VIDEO_ENC_ISLAND: - atomic_inc(&g_videoenc_access_count); - break; - case OSPM_VIDEO_DEC_ISLAND: - atomic_inc(&g_videodec_access_count); - break; - case OSPM_DISPLAY_ISLAND: - atomic_inc(&g_display_access_count); - break; - } + if (force_on == false) + return false; + + /* Ok power up needed */ + ret = gma_resume_pci(dev->pdev); + if (ret == 0) { + psb_irq_preinstall(dev); + psb_irq_postinstall(dev); + pm_runtime_get(&dev->pdev->dev); + dev_priv->display_count++; + return true; } - - if (!b_atomic && locked) - mutex_unlock(&power_mutex); - - return ret; -#endif + return false; } -/* - * ospm_power_using_hw_end +/** + * gma_power_end - end use of power + * @dev: Our DRM device * - * Description: Notify PowerMgmt module that you are done accessing the - * specified island's hw so feel free to power it off. Note that this - * function doesn't actually power off the islands. + * Indicate that one of our gma_power_begin() requested periods when + * the diplay island power is needed has completed. */ -void ospm_power_using_hw_end(int hw_island) -{ -#if 0 /* FIXMEAC */ - switch(hw_island) - { - case OSPM_GRAPHICS_ISLAND: - atomic_dec(&g_graphics_access_count); - break; - case OSPM_VIDEO_ENC_ISLAND: - atomic_dec(&g_videoenc_access_count); - break; - case OSPM_VIDEO_DEC_ISLAND: - atomic_dec(&g_videodec_access_count); - break; - case OSPM_DISPLAY_ISLAND: - atomic_dec(&g_display_access_count); - break; - } - - //decrement runtime pm ref count - pm_runtime_put(&gpDrmDevice->pdev->dev); - - WARN_ON(atomic_read(&g_graphics_access_count) < 0); - WARN_ON(atomic_read(&g_videoenc_access_count) < 0); - WARN_ON(atomic_read(&g_videodec_access_count) < 0); - WARN_ON(atomic_read(&g_display_access_count) < 0); -#endif -} - -int ospm_runtime_pm_allow(struct drm_device * dev) +void gma_power_end(struct drm_device *dev) { - return 0; -} - -void ospm_runtime_pm_forbid(struct drm_device * dev) -{ - struct drm_psb_private * dev_priv = dev->dev_private; - - DRM_INFO("%s\n", __FUNCTION__); - - pm_runtime_forbid(&dev->pdev->dev); - dev_priv->rpm_enabled = 0; + struct drm_psb_private *dev_priv = dev->dev_private; + dev_priv->display_count--; + WARN_ON(dev_priv->display_count < 0); + pm_runtime_put(&dev->pdev->dev); } int psb_runtime_suspend(struct device *dev) { - pm_message_t state; - int ret = 0; - state.event = 0; - -#ifdef OSPM_GFX_DPK - printk(KERN_ALERT "OSPM_GFX_DPK: %s \n", __func__); -#endif - if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count) - || atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count)){ -#ifdef OSPM_GFX_DPK - printk(KERN_ALERT "OSPM_GFX_DPK: GFX: %d VEC: %d VED: %d DC: %d DSR: %d \n", atomic_read(&g_graphics_access_count), - atomic_read(&g_videoenc_access_count), atomic_read(&g_videodec_access_count), atomic_read(&g_display_access_count)); -#endif - return -EBUSY; - } - else - ret = ospm_power_suspend(gpDrmDevice->pdev, state); - - return ret; + static pm_message_t dummy; + return gma_power_suspend(to_pci_dev(dev), dummy); } int psb_runtime_resume(struct device *dev) @@ -782,11 +479,11 @@ int psb_runtime_resume(struct device *dev) int psb_runtime_idle(struct device *dev) { - /*printk (KERN_ALERT "lvds:%d,mipi:%d\n", dev_priv->is_lvds_on, dev_priv->is_mipi_on);*/ - if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count) - || atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count)) - return 1; - else + struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_psb_private *dev_priv = drmdev->dev_private; + if (dev_priv->display_count) return 0; + else + return 1; } diff --git a/drivers/staging/gma500/psb_powermgmt.h b/drivers/staging/gma500/psb_powermgmt.h index bf6f27af03a8..e005229af798 100644 --- a/drivers/staging/gma500/psb_powermgmt.h +++ b/drivers/staging/gma500/psb_powermgmt.h @@ -24,7 +24,8 @@ * Authors: * Benjamin Defnet <benjamin.r.defnet@intel.com> * Rajesh Poornachandran <rajesh.poornachandran@intel.com> - * + * Massively reworked + * Alan Cox <alan@linux.intel.com> */ #ifndef _PSB_POWERMGMT_H_ #define _PSB_POWERMGMT_H_ @@ -32,65 +33,35 @@ #include <linux/pci.h> #include <drm/drmP.h> -#define OSPM_GRAPHICS_ISLAND 0x1 -#define OSPM_VIDEO_ENC_ISLAND 0x2 -#define OSPM_VIDEO_DEC_ISLAND 0x4 -#define OSPM_DISPLAY_ISLAND 0x8 -#define OSPM_GL3_CACHE_ISLAND 0x10 -#define OSPM_ALL_ISLANDS 0x1f - -/* IPC message and command defines used to enable/disable mipi panel voltages */ -#define IPC_MSG_PANEL_ON_OFF 0xE9 -#define IPC_CMD_PANEL_ON 1 -#define IPC_CMD_PANEL_OFF 0 - -typedef enum _UHBUsage -{ - OSPM_UHB_ONLY_IF_ON = 0, - OSPM_UHB_FORCE_POWER_ON, -} UHBUsage; - -/* Use these functions to power down video HW for D0i3 purpose */ - -void ospm_power_init(struct drm_device *dev); -void ospm_power_uninit(void); - +void gma_power_init(struct drm_device *dev); +void gma_power_uninit(struct drm_device *dev); /* - * OSPM will call these functions + * The kernel bus power management will call these functions */ -int ospm_power_suspend(struct pci_dev *pdev, pm_message_t state); -int ospm_power_resume(struct pci_dev *pdev); +int gma_power_suspend(struct pci_dev *pdev, pm_message_t state); +int gma_power_resume(struct pci_dev *pdev); /* * These are the functions the driver should use to wrap all hw access * (i.e. register reads and writes) */ -bool ospm_power_using_hw_begin(int hw_island, UHBUsage usage); -void ospm_power_using_hw_end(int hw_island); +bool gma_power_begin(struct drm_device *dev, bool force); +void gma_power_end(struct drm_device *dev); /* * Use this function to do an instantaneous check for if the hw is on. - * Only use this in cases where you know the g_state_change_mutex - * is already held such as in irq install/uninstall and you need to - * prevent a deadlock situation. Otherwise use ospm_power_using_hw_begin(). + * Only use this in cases where you know the mutex is already held such + * as in irq install/uninstall and you need to + * prevent a deadlock situation. Otherwise use gma_power_begin(). */ -bool ospm_power_is_hw_on(int hw_islands); +bool gma_power_is_on(struct drm_device *dev); /* - * Power up/down different hw component rails/islands - */ -void ospm_power_island_down(int hw_islands); -void ospm_power_island_up(int hw_islands); -void ospm_suspend_graphics(void); -/* * GFX-Runtime PM callbacks */ int psb_runtime_suspend(struct device *dev); int psb_runtime_resume(struct device *dev); int psb_runtime_idle(struct device *dev); -int ospm_runtime_pm_allow(struct drm_device * dev); -void ospm_runtime_pm_forbid(struct drm_device * dev); - #endif /*_PSB_POWERMGMT_H_*/ diff --git a/drivers/staging/gma500/psb_pvr_glue.c b/drivers/staging/gma500/psb_pvr_glue.c deleted file mode 100644 index da78946b57ad..000000000000 --- a/drivers/staging/gma500/psb_pvr_glue.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2009, Intel Corporation. - * - * 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. - * - */ - -#include "psb_pvr_glue.h" - -/** - * FIXME: should NOT use these file under env/linux directly - */ - -int psb_get_meminfo_by_handle(void *hKernelMemInfo, - void **ppsKernelMemInfo) -{ - return -EINVAL; -#if 0 - void *psKernelMemInfo = IMG_NULL; - PVRSRV_PER_PROCESS_DATA *psPerProc = IMG_NULL; - PVRSRV_ERROR eError; - - psPerProc = PVRSRVPerProcessData(task_tgid_nr(current)); - eError = PVRSRVLookupHandle(psPerProc->psHandleBase, - (IMG_VOID *)&psKernelMemInfo, - hKernelMemInfo, - PVRSRV_HANDLE_TYPE_MEM_INFO); - if (eError != PVRSRV_OK) { - DRM_ERROR("Cannot find kernel meminfo for handle 0x%x\n", - (u32)hKernelMemInfo); - return -EINVAL; - } - - *ppsKernelMemInfo = psKernelMemInfo; - - DRM_DEBUG("Got Kernel MemInfo for handle %lx\n", - (u32)hKernelMemInfo); - return 0; -#endif -} - -int psb_get_pages_by_mem_handle(void *hOSMemHandle, struct page ***pages) -{ - return -EINVAL; -#if 0 - LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - struct page **page_list; - if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES) { - DRM_ERROR("MemArea type is not LINUX_MEM_AREA_ALLOC_PAGES\n"); - return -EINVAL; - } - - page_list = psLinuxMemArea->uData.sPageList.pvPageList; - if (!page_list) { - DRM_DEBUG("Page List is NULL\n"); - return -ENOMEM; - } - - *pages = page_list; - return 0; -#endif -} diff --git a/drivers/staging/gma500/psb_pvr_glue.h b/drivers/staging/gma500/psb_pvr_glue.h deleted file mode 100644 index dee8cb2cadc0..000000000000 --- a/drivers/staging/gma500/psb_pvr_glue.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2009, Intel Corporation. - * - * 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. - * - */ - -#include "psb_drv.h" - -extern int psb_get_meminfo_by_handle(void * hKernelMemInfo, - void **ppsKernelMemInfo); -extern u32 psb_get_tgid(void); -extern int psb_get_pages_by_mem_handle(void * hOSMemHandle, - struct page ***pages); diff --git a/drivers/staging/gma500/psb_sgx.c b/drivers/staging/gma500/psb_sgx.c deleted file mode 100644 index 973134bc2345..000000000000 --- a/drivers/staging/gma500/psb_sgx.c +++ /dev/null @@ -1,238 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007, Intel Corporation. - * All Rights Reserved. - * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX. USA. - * 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. - * - **************************************************************************/ - -#include <drm/drmP.h> -#include "psb_drv.h" -#include "psb_drm.h" -#include "psb_reg.h" -#include "ttm/ttm_bo_api.h" -#include "ttm/ttm_execbuf_util.h" -#include "psb_ttm_userobj_api.h" -#include "ttm/ttm_placement.h" -#include "psb_sgx.h" -#include "psb_intel_reg.h" -#include "psb_powermgmt.h" - - -static inline int psb_same_page(unsigned long offset, - unsigned long offset2) -{ - return (offset & PAGE_MASK) == (offset2 & PAGE_MASK); -} - -static inline unsigned long psb_offset_end(unsigned long offset, - unsigned long end) -{ - offset = (offset + PAGE_SIZE) & PAGE_MASK; - return (end < offset) ? end : offset; -} - -struct psb_dstbuf_cache { - unsigned int dst; - struct ttm_buffer_object *dst_buf; - unsigned long dst_offset; - uint32_t *dst_page; - unsigned int dst_page_offset; - struct ttm_bo_kmap_obj dst_kmap; - bool dst_is_iomem; -}; - -struct psb_validate_buffer { - struct ttm_validate_buffer base; - struct psb_validate_req req; - int ret; - struct psb_validate_arg __user *user_val_arg; - uint32_t flags; - uint32_t offset; - int po_correct; -}; -static int -psb_placement_fence_type(struct ttm_buffer_object *bo, - uint64_t set_val_flags, - uint64_t clr_val_flags, - uint32_t new_fence_class, - uint32_t *new_fence_type) -{ - int ret; - uint32_t n_fence_type; - /* - uint32_t set_flags = set_val_flags & 0xFFFFFFFF; - uint32_t clr_flags = clr_val_flags & 0xFFFFFFFF; - */ - struct ttm_fence_object *old_fence; - uint32_t old_fence_type; - struct ttm_placement placement; - - if (unlikely - (!(set_val_flags & - (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)))) { - DRM_ERROR - ("GPU access type (read / write) is not indicated.\n"); - return -EINVAL; - } - - /* User space driver doesn't set any TTM placement flags in - set_val_flags or clr_val_flags */ - placement.num_placement = 0;/* FIXME */ - placement.num_busy_placement = 0; - placement.fpfn = 0; - placement.lpfn = 0; - ret = psb_ttm_bo_check_placement(bo, &placement); - if (unlikely(ret != 0)) - return ret; - - switch (new_fence_class) { - default: - n_fence_type = _PSB_FENCE_TYPE_EXE; - } - - *new_fence_type = n_fence_type; - old_fence = (struct ttm_fence_object *) bo->sync_obj; - old_fence_type = (uint32_t) (unsigned long) bo->sync_obj_arg; - - if (old_fence && ((new_fence_class != old_fence->fence_class) || - ((n_fence_type ^ old_fence_type) & - old_fence_type))) { - ret = ttm_bo_wait(bo, 0, 1, 0); - if (unlikely(ret != 0)) - return ret; - } - /* - bo->proposed_flags = (bo->proposed_flags | set_flags) - & ~clr_flags & TTM_PL_MASK_MEMTYPE; - */ - return 0; -} - -int psb_validate_kernel_buffer(struct psb_context *context, - struct ttm_buffer_object *bo, - uint32_t fence_class, - uint64_t set_flags, uint64_t clr_flags) -{ - struct psb_validate_buffer *item; - uint32_t cur_fence_type; - int ret; - - if (unlikely(context->used_buffers >= PSB_NUM_VALIDATE_BUFFERS)) { - DRM_ERROR("Out of free validation buffer entries for " - "kernel buffer validation.\n"); - return -ENOMEM; - } - - item = &context->buffers[context->used_buffers]; - item->user_val_arg = NULL; - item->base.reserved = 0; - - ret = ttm_bo_reserve(bo, 1, 0, 1, context->val_seq); - if (unlikely(ret != 0)) - return ret; - - ret = psb_placement_fence_type(bo, set_flags, clr_flags, fence_class, - &cur_fence_type); - if (unlikely(ret != 0)) { - ttm_bo_unreserve(bo); - return ret; - } - - item->base.bo = ttm_bo_reference(bo); - item->base.new_sync_obj_arg = (void *) (unsigned long) cur_fence_type; - item->base.reserved = 1; - - /* Internal locking ??? FIXMEAC */ - list_add_tail(&item->base.head, &context->kern_validate_list); - context->used_buffers++; - /* - ret = ttm_bo_validate(bo, 1, 0, 0); - if (unlikely(ret != 0)) - goto out_unlock; - */ - item->offset = bo->offset; - item->flags = bo->mem.placement; - context->fence_types |= cur_fence_type; - - return ret; -} - -void psb_fence_or_sync(struct drm_file *file_priv, - uint32_t engine, - uint32_t fence_types, - uint32_t fence_flags, - struct list_head *list, - struct psb_ttm_fence_rep *fence_arg, - struct ttm_fence_object **fence_p) -{ - struct drm_device *dev = file_priv->minor->dev; - struct drm_psb_private *dev_priv = psb_priv(dev); - struct ttm_fence_device *fdev = &dev_priv->fdev; - int ret; - struct ttm_fence_object *fence; - struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile; - uint32_t handle; - - ret = ttm_fence_user_create(fdev, tfile, - engine, fence_types, - TTM_FENCE_FLAG_EMIT, &fence, &handle); - if (ret) { - - /* - * Fence creation failed. - * Fall back to synchronous operation and idle the engine. - */ - - if (!(fence_flags & DRM_PSB_FENCE_NO_USER)) { - - /* - * Communicate to user-space that - * fence creation has failed and that - * the engine is idle. - */ - - fence_arg->handle = ~0; - fence_arg->error = ret; - } - - ttm_eu_backoff_reservation(list); - if (fence_p) - *fence_p = NULL; - return; - } - - ttm_eu_fence_buffer_objects(list, fence); - if (!(fence_flags & DRM_PSB_FENCE_NO_USER)) { - struct ttm_fence_info info = ttm_fence_get_info(fence); - fence_arg->handle = handle; - fence_arg->fence_class = ttm_fence_class(fence); - fence_arg->fence_type = ttm_fence_types(fence); - fence_arg->signaled_types = info.signaled_types; - fence_arg->error = 0; - } else { - ret = - ttm_ref_object_base_unref(tfile, handle, - ttm_fence_type); - BUG_ON(ret); - } - - if (fence_p) - *fence_p = fence; - else if (fence) - ttm_fence_object_unref(&fence); -} - diff --git a/drivers/staging/gma500/psb_sgx.h b/drivers/staging/gma500/psb_sgx.h deleted file mode 100644 index 9300e2da993a..000000000000 --- a/drivers/staging/gma500/psb_sgx.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2008, Intel Corporation - * - * 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. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * - **/ -#ifndef _PSB_SGX_H_ -#define _PSB_SGX_H_ - -extern int psb_submit_video_cmdbuf(struct drm_device *dev, - struct ttm_buffer_object *cmd_buffer, - unsigned long cmd_offset, - unsigned long cmd_size, - struct ttm_fence_object *fence); - -extern int drm_idle_check_interval; - -#endif diff --git a/drivers/staging/gma500/psb_ttm_fence.c b/drivers/staging/gma500/psb_ttm_fence.c deleted file mode 100644 index d1c359018cba..000000000000 --- a/drivers/staging/gma500/psb_ttm_fence.c +++ /dev/null @@ -1,605 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA - * 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. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - */ - -#include "psb_ttm_fence_api.h" -#include "psb_ttm_fence_driver.h" -#include <linux/wait.h> -#include <linux/sched.h> - -#include <drm/drmP.h> - -/* - * Simple implementation for now. - */ - -static void ttm_fence_lockup(struct ttm_fence_object *fence, uint32_t mask) -{ - struct ttm_fence_class_manager *fc = ttm_fence_fc(fence); - - printk(KERN_ERR "GPU lockup dectected on engine %u " - "fence type 0x%08x\n", - (unsigned int)fence->fence_class, (unsigned int)mask); - /* - * Give engines some time to idle? - */ - - write_lock(&fc->lock); - ttm_fence_handler(fence->fdev, fence->fence_class, - fence->sequence, mask, -EBUSY); - write_unlock(&fc->lock); -} - -/* - * Convenience function to be called by fence::wait methods that - * need polling. - */ - -int ttm_fence_wait_polling(struct ttm_fence_object *fence, bool lazy, - bool interruptible, uint32_t mask) -{ - struct ttm_fence_class_manager *fc = ttm_fence_fc(fence); - const struct ttm_fence_driver *driver = ttm_fence_driver(fence); - uint32_t count = 0; - int ret; - unsigned long end_jiffies = fence->timeout_jiffies; - - DECLARE_WAITQUEUE(entry, current); - add_wait_queue(&fc->fence_queue, &entry); - - ret = 0; - - for (;;) { - __set_current_state((interruptible) ? - TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); - if (ttm_fence_object_signaled(fence, mask)) - break; - if (time_after_eq(jiffies, end_jiffies)) { - if (driver->lockup) - driver->lockup(fence, mask); - else - ttm_fence_lockup(fence, mask); - continue; - } - if (lazy) - schedule_timeout(1); - else if ((++count & 0x0F) == 0) { - __set_current_state(TASK_RUNNING); - schedule(); - __set_current_state((interruptible) ? - TASK_INTERRUPTIBLE : - TASK_UNINTERRUPTIBLE); - } - if (interruptible && signal_pending(current)) { - ret = -ERESTART; - break; - } - } - __set_current_state(TASK_RUNNING); - remove_wait_queue(&fc->fence_queue, &entry); - return ret; -} - -/* - * Typically called by the IRQ handler. - */ - -void ttm_fence_handler(struct ttm_fence_device *fdev, uint32_t fence_class, - uint32_t sequence, uint32_t type, uint32_t error) -{ - int wake = 0; - uint32_t diff; - uint32_t relevant_type; - uint32_t new_type; - struct ttm_fence_class_manager *fc = &fdev->fence_class[fence_class]; - const struct ttm_fence_driver *driver = ttm_fence_driver_from_dev(fdev); - struct list_head *head; - struct ttm_fence_object *fence, *next; - bool found = false; - - if (list_empty(&fc->ring)) - return; - - list_for_each_entry(fence, &fc->ring, ring) { - diff = (sequence - fence->sequence) & fc->sequence_mask; - if (diff > fc->wrap_diff) { - found = true; - break; - } - } - - fc->waiting_types &= ~type; - head = (found) ? &fence->ring : &fc->ring; - - list_for_each_entry_safe_reverse(fence, next, head, ring) { - if (&fence->ring == &fc->ring) - break; - - DRM_DEBUG("Fence 0x%08lx, sequence 0x%08x, type 0x%08x\n", - (unsigned long)fence, fence->sequence, - fence->fence_type); - - if (error) { - fence->info.error = error; - fence->info.signaled_types = fence->fence_type; - list_del_init(&fence->ring); - wake = 1; - break; - } - - relevant_type = type & fence->fence_type; - new_type = (fence->info.signaled_types | relevant_type) ^ - fence->info.signaled_types; - - if (new_type) { - fence->info.signaled_types |= new_type; - DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n", - (unsigned long)fence, - fence->info.signaled_types); - - if (unlikely(driver->signaled)) - driver->signaled(fence); - - if (driver->needed_flush) - fc->pending_flush |= - driver->needed_flush(fence); - - if (new_type & fence->waiting_types) - wake = 1; - } - - fc->waiting_types |= - fence->waiting_types & ~fence->info.signaled_types; - - if (!(fence->fence_type & ~fence->info.signaled_types)) { - DRM_DEBUG("Fence completely signaled 0x%08lx\n", - (unsigned long)fence); - list_del_init(&fence->ring); - } - } - - /* - * Reinstate lost waiting types. - */ - - if ((fc->waiting_types & type) != type) { - head = head->prev; - list_for_each_entry(fence, head, ring) { - if (&fence->ring == &fc->ring) - break; - diff = - (fc->highest_waiting_sequence - - fence->sequence) & fc->sequence_mask; - if (diff > fc->wrap_diff) - break; - - fc->waiting_types |= - fence->waiting_types & ~fence->info.signaled_types; - } - } - - if (wake) - wake_up_all(&fc->fence_queue); -} - -static void ttm_fence_unring(struct ttm_fence_object *fence) -{ - struct ttm_fence_class_manager *fc = ttm_fence_fc(fence); - unsigned long irq_flags; - - write_lock_irqsave(&fc->lock, irq_flags); - list_del_init(&fence->ring); - write_unlock_irqrestore(&fc->lock, irq_flags); -} - -bool ttm_fence_object_signaled(struct ttm_fence_object *fence, uint32_t mask) -{ - unsigned long flags; - bool signaled; - const struct ttm_fence_driver *driver = ttm_fence_driver(fence); - struct ttm_fence_class_manager *fc = ttm_fence_fc(fence); - - mask &= fence->fence_type; - read_lock_irqsave(&fc->lock, flags); - signaled = (mask & fence->info.signaled_types) == mask; - read_unlock_irqrestore(&fc->lock, flags); - if (!signaled && driver->poll) { - write_lock_irqsave(&fc->lock, flags); - driver->poll(fence->fdev, fence->fence_class, mask); - signaled = (mask & fence->info.signaled_types) == mask; - write_unlock_irqrestore(&fc->lock, flags); - } - return signaled; -} - -int ttm_fence_object_flush(struct ttm_fence_object *fence, uint32_t type) -{ - const struct ttm_fence_driver *driver = ttm_fence_driver(fence); - struct ttm_fence_class_manager *fc = ttm_fence_fc(fence); - unsigned long irq_flags; - uint32_t saved_pending_flush; - uint32_t diff; - bool call_flush; - - if (type & ~fence->fence_type) { - DRM_ERROR("Flush trying to extend fence type, " - "0x%x, 0x%x\n", type, fence->fence_type); - return -EINVAL; - } - - write_lock_irqsave(&fc->lock, irq_flags); - fence->waiting_types |= type; - fc->waiting_types |= fence->waiting_types; - diff = (fence->sequence - fc->highest_waiting_sequence) & - fc->sequence_mask; - - if (diff < fc->wrap_diff) - fc->highest_waiting_sequence = fence->sequence; - - /* - * fence->waiting_types has changed. Determine whether - * we need to initiate some kind of flush as a result of this. - */ - - saved_pending_flush = fc->pending_flush; - if (driver->needed_flush) - fc->pending_flush |= driver->needed_flush(fence); - - if (driver->poll) - driver->poll(fence->fdev, fence->fence_class, - fence->waiting_types); - - call_flush = (fc->pending_flush != 0); - write_unlock_irqrestore(&fc->lock, irq_flags); - - if (call_flush && driver->flush) - driver->flush(fence->fdev, fence->fence_class); - - return 0; -} - -/* - * Make sure old fence objects are signaled before their fence sequences are - * wrapped around and reused. - */ - -void ttm_fence_flush_old(struct ttm_fence_device *fdev, - uint32_t fence_class, uint32_t sequence) -{ - struct ttm_fence_class_manager *fc = &fdev->fence_class[fence_class]; - struct ttm_fence_object *fence; - unsigned long irq_flags; - const struct ttm_fence_driver *driver = fdev->driver; - bool call_flush; - - uint32_t diff; - - write_lock_irqsave(&fc->lock, irq_flags); - - list_for_each_entry_reverse(fence, &fc->ring, ring) { - diff = (sequence - fence->sequence) & fc->sequence_mask; - if (diff <= fc->flush_diff) - break; - - fence->waiting_types = fence->fence_type; - fc->waiting_types |= fence->fence_type; - - if (driver->needed_flush) - fc->pending_flush |= driver->needed_flush(fence); - } - - if (driver->poll) - driver->poll(fdev, fence_class, fc->waiting_types); - - call_flush = (fc->pending_flush != 0); - write_unlock_irqrestore(&fc->lock, irq_flags); - - if (call_flush && driver->flush) - driver->flush(fdev, fence->fence_class); - - /* - * FIXME: Shold we implement a wait here for really old fences? - */ - -} - -int ttm_fence_object_wait(struct ttm_fence_object *fence, - bool lazy, bool interruptible, uint32_t mask) -{ - const struct ttm_fence_driver *driver = ttm_fence_driver(fence); - struct ttm_fence_class_manager *fc = ttm_fence_fc(fence); - int ret = 0; - unsigned long timeout; - unsigned long cur_jiffies; - unsigned long to_jiffies; - - if (mask & ~fence->fence_type) { - DRM_ERROR("Wait trying to extend fence type" - " 0x%08x 0x%08x\n", mask, fence->fence_type); - BUG(); - return -EINVAL; - } - - if (driver->wait) - return driver->wait(fence, lazy, interruptible, mask); - - ttm_fence_object_flush(fence, mask); -retry: - if (!driver->has_irq || - driver->has_irq(fence->fdev, fence->fence_class, mask)) { - - cur_jiffies = jiffies; - to_jiffies = fence->timeout_jiffies; - - timeout = (time_after(to_jiffies, cur_jiffies)) ? - to_jiffies - cur_jiffies : 1; - - if (interruptible) - ret = wait_event_interruptible_timeout - (fc->fence_queue, - ttm_fence_object_signaled(fence, mask), timeout); - else - ret = wait_event_timeout - (fc->fence_queue, - ttm_fence_object_signaled(fence, mask), timeout); - - if (unlikely(ret == -ERESTARTSYS)) - return -ERESTART; - - if (unlikely(ret == 0)) { - if (driver->lockup) - driver->lockup(fence, mask); - else - ttm_fence_lockup(fence, mask); - goto retry; - } - - return 0; - } - - return ttm_fence_wait_polling(fence, lazy, interruptible, mask); -} - -int ttm_fence_object_emit(struct ttm_fence_object *fence, uint32_t fence_flags, - uint32_t fence_class, uint32_t type) -{ - const struct ttm_fence_driver *driver = ttm_fence_driver(fence); - struct ttm_fence_class_manager *fc = ttm_fence_fc(fence); - unsigned long flags; - uint32_t sequence; - unsigned long timeout; - int ret; - - ttm_fence_unring(fence); - ret = driver->emit(fence->fdev, - fence_class, fence_flags, &sequence, &timeout); - if (ret) - return ret; - - write_lock_irqsave(&fc->lock, flags); - fence->fence_class = fence_class; - fence->fence_type = type; - fence->waiting_types = 0; - fence->info.signaled_types = 0; - fence->info.error = 0; - fence->sequence = sequence; - fence->timeout_jiffies = timeout; - if (list_empty(&fc->ring)) - fc->highest_waiting_sequence = sequence - 1; - list_add_tail(&fence->ring, &fc->ring); - fc->latest_queued_sequence = sequence; - write_unlock_irqrestore(&fc->lock, flags); - return 0; -} - -int ttm_fence_object_init(struct ttm_fence_device *fdev, - uint32_t fence_class, - uint32_t type, - uint32_t create_flags, - void (*destroy) (struct ttm_fence_object *), - struct ttm_fence_object *fence) -{ - int ret = 0; - - kref_init(&fence->kref); - fence->fence_class = fence_class; - fence->fence_type = type; - fence->info.signaled_types = 0; - fence->waiting_types = 0; - fence->sequence = 0; - fence->info.error = 0; - fence->fdev = fdev; - fence->destroy = destroy; - INIT_LIST_HEAD(&fence->ring); - atomic_inc(&fdev->count); - - if (create_flags & TTM_FENCE_FLAG_EMIT) { - ret = ttm_fence_object_emit(fence, create_flags, - fence->fence_class, type); - } - - return ret; -} - -int ttm_fence_object_create(struct ttm_fence_device *fdev, - uint32_t fence_class, - uint32_t type, - uint32_t create_flags, - struct ttm_fence_object **c_fence) -{ - struct ttm_fence_object *fence; - int ret; - - ret = ttm_mem_global_alloc(fdev->mem_glob, - sizeof(*fence), - false, - false); - if (unlikely(ret != 0)) { - printk(KERN_ERR "Out of memory creating fence object\n"); - return ret; - } - - fence = kmalloc(sizeof(*fence), GFP_KERNEL); - if (!fence) { - printk(KERN_ERR "Out of memory creating fence object\n"); - ttm_mem_global_free(fdev->mem_glob, sizeof(*fence)); - return -ENOMEM; - } - - ret = ttm_fence_object_init(fdev, fence_class, type, - create_flags, NULL, fence); - if (ret) { - ttm_fence_object_unref(&fence); - return ret; - } - *c_fence = fence; - - return 0; -} - -static void ttm_fence_object_destroy(struct kref *kref) -{ - struct ttm_fence_object *fence = - container_of(kref, struct ttm_fence_object, kref); - struct ttm_fence_class_manager *fc = ttm_fence_fc(fence); - unsigned long irq_flags; - - write_lock_irqsave(&fc->lock, irq_flags); - list_del_init(&fence->ring); - write_unlock_irqrestore(&fc->lock, irq_flags); - - atomic_dec(&fence->fdev->count); - if (fence->destroy) - fence->destroy(fence); - else { - ttm_mem_global_free(fence->fdev->mem_glob, - sizeof(*fence)); - kfree(fence); - } -} - -void ttm_fence_device_release(struct ttm_fence_device *fdev) -{ - kfree(fdev->fence_class); -} - -int -ttm_fence_device_init(int num_classes, - struct ttm_mem_global *mem_glob, - struct ttm_fence_device *fdev, - const struct ttm_fence_class_init *init, - bool replicate_init, - const struct ttm_fence_driver *driver) -{ - struct ttm_fence_class_manager *fc; - const struct ttm_fence_class_init *fci; - int i; - - fdev->mem_glob = mem_glob; - fdev->fence_class = kzalloc(num_classes * - sizeof(*fdev->fence_class), GFP_KERNEL); - - if (unlikely(!fdev->fence_class)) - return -ENOMEM; - - fdev->num_classes = num_classes; - atomic_set(&fdev->count, 0); - fdev->driver = driver; - - for (i = 0; i < fdev->num_classes; ++i) { - fc = &fdev->fence_class[i]; - fci = &init[(replicate_init) ? 0 : i]; - - fc->wrap_diff = fci->wrap_diff; - fc->flush_diff = fci->flush_diff; - fc->sequence_mask = fci->sequence_mask; - - rwlock_init(&fc->lock); - INIT_LIST_HEAD(&fc->ring); - init_waitqueue_head(&fc->fence_queue); - } - - return 0; -} - -struct ttm_fence_info ttm_fence_get_info(struct ttm_fence_object *fence) -{ - struct ttm_fence_class_manager *fc = ttm_fence_fc(fence); - struct ttm_fence_info tmp; - unsigned long irq_flags; - - read_lock_irqsave(&fc->lock, irq_flags); - tmp = fence->info; - read_unlock_irqrestore(&fc->lock, irq_flags); - - return tmp; -} - -void ttm_fence_object_unref(struct ttm_fence_object **p_fence) -{ - struct ttm_fence_object *fence = *p_fence; - - *p_fence = NULL; - (void)kref_put(&fence->kref, &ttm_fence_object_destroy); -} - -/* - * Placement / BO sync object glue. - */ - -bool ttm_fence_sync_obj_signaled(void *sync_obj, void *sync_arg) -{ - struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj; - uint32_t fence_types = (uint32_t) (unsigned long)sync_arg; - - return ttm_fence_object_signaled(fence, fence_types); -} - -int ttm_fence_sync_obj_wait(void *sync_obj, void *sync_arg, - bool lazy, bool interruptible) -{ - struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj; - uint32_t fence_types = (uint32_t) (unsigned long)sync_arg; - - return ttm_fence_object_wait(fence, lazy, interruptible, fence_types); -} - -int ttm_fence_sync_obj_flush(void *sync_obj, void *sync_arg) -{ - struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj; - uint32_t fence_types = (uint32_t) (unsigned long)sync_arg; - - return ttm_fence_object_flush(fence, fence_types); -} - -void ttm_fence_sync_obj_unref(void **sync_obj) -{ - ttm_fence_object_unref((struct ttm_fence_object **)sync_obj); -} - -void *ttm_fence_sync_obj_ref(void *sync_obj) -{ - return (void *) - ttm_fence_object_ref((struct ttm_fence_object *)sync_obj); -} diff --git a/drivers/staging/gma500/psb_ttm_fence_api.h b/drivers/staging/gma500/psb_ttm_fence_api.h deleted file mode 100644 index b14a42711d03..000000000000 --- a/drivers/staging/gma500/psb_ttm_fence_api.h +++ /dev/null @@ -1,272 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA - * 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. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - */ -#ifndef _TTM_FENCE_API_H_ -#define _TTM_FENCE_API_H_ - -#include <linux/list.h> -#include <linux/kref.h> - -#define TTM_FENCE_FLAG_EMIT (1 << 0) -#define TTM_FENCE_TYPE_EXE (1 << 0) - -struct ttm_fence_device; - -/** - * struct ttm_fence_info - * - * @fence_class: The fence class. - * @fence_type: Bitfield indicating types for this fence. - * @signaled_types: Bitfield indicating which types are signaled. - * @error: Last error reported from the device. - * - * Used as output from the ttm_fence_get_info - */ - -struct ttm_fence_info { - uint32_t signaled_types; - uint32_t error; -}; - -/** - * struct ttm_fence_object - * - * @fdev: Pointer to the fence device struct. - * @kref: Holds the reference count of this fence object. - * @ring: List head used for the circular list of not-completely - * signaled fences. - * @info: Data for fast retrieval using the ttm_fence_get_info() - * function. - * @timeout_jiffies: Absolute jiffies value indicating when this fence - * object times out and, if waited on, calls ttm_fence_lockup - * to check for and resolve a GPU lockup. - * @sequence: Fence sequence number. - * @waiting_types: Types currently waited on. - * @destroy: Called to free the fence object, when its refcount has - * reached zero. If NULL, kfree is used. - * - * This struct is provided in the driver interface so that drivers can - * derive from it and create their own fence implementation. All members - * are private to the fence implementation and the fence driver callbacks. - * Otherwise a driver may access the derived object using container_of(). - */ - -struct ttm_fence_object { - struct ttm_fence_device *fdev; - struct kref kref; - uint32_t fence_class; - uint32_t fence_type; - - /* - * The below fields are protected by the fence class - * manager spinlock. - */ - - struct list_head ring; - struct ttm_fence_info info; - unsigned long timeout_jiffies; - uint32_t sequence; - uint32_t waiting_types; - void (*destroy) (struct ttm_fence_object *); -}; - -/** - * ttm_fence_object_init - * - * @fdev: Pointer to a struct ttm_fence_device. - * @fence_class: Fence class for this fence. - * @type: Fence type for this fence. - * @create_flags: Flags indicating varios actions at init time. At this point - * there's only TTM_FENCE_FLAG_EMIT, which triggers a sequence emission to - * the command stream. - * @destroy: Destroy function. If NULL, kfree() is used. - * @fence: The struct ttm_fence_object to initialize. - * - * Initialize a pre-allocated fence object. This function, together with the - * destroy function makes it possible to derive driver-specific fence objects. - */ - -extern int -ttm_fence_object_init(struct ttm_fence_device *fdev, - uint32_t fence_class, - uint32_t type, - uint32_t create_flags, - void (*destroy) (struct ttm_fence_object *fence), - struct ttm_fence_object *fence); - -/** - * ttm_fence_object_create - * - * @fdev: Pointer to a struct ttm_fence_device. - * @fence_class: Fence class for this fence. - * @type: Fence type for this fence. - * @create_flags: Flags indicating varios actions at init time. At this point - * there's only TTM_FENCE_FLAG_EMIT, which triggers a sequence emission to - * the command stream. - * @c_fence: On successful termination, *(@c_fence) will point to the created - * fence object. - * - * Create and initialize a struct ttm_fence_object. The destroy function will - * be set to kfree(). - */ - -extern int -ttm_fence_object_create(struct ttm_fence_device *fdev, - uint32_t fence_class, - uint32_t type, - uint32_t create_flags, - struct ttm_fence_object **c_fence); - -/** - * ttm_fence_object_wait - * - * @fence: The fence object to wait on. - * @lazy: Allow sleeps to reduce the cpu-usage if polling. - * @interruptible: Sleep interruptible when waiting. - * @type_mask: Wait for the given type_mask to signal. - * - * Wait for a fence to signal the given type_mask. The function will - * perform a fence_flush using type_mask. (See ttm_fence_object_flush). - * - * Returns - * -ERESTART if interrupted by a signal. - * May return driver-specific error codes if timed-out. - */ - -extern int -ttm_fence_object_wait(struct ttm_fence_object *fence, - bool lazy, bool interruptible, uint32_t type_mask); - -/** - * ttm_fence_object_flush - * - * @fence: The fence object to flush. - * @flush_mask: Fence types to flush. - * - * Make sure that the given fence eventually signals the - * types indicated by @flush_mask. Note that this may or may not - * map to a CPU or GPU flush. - */ - -extern int -ttm_fence_object_flush(struct ttm_fence_object *fence, uint32_t flush_mask); - -/** - * ttm_fence_get_info - * - * @fence: The fence object. - * - * Copy the info block from the fence while holding relevant locks. - */ - -struct ttm_fence_info ttm_fence_get_info(struct ttm_fence_object *fence); - -/** - * ttm_fence_object_ref - * - * @fence: The fence object. - * - * Return a ref-counted pointer to the fence object indicated by @fence. - */ - -static inline struct ttm_fence_object *ttm_fence_object_ref(struct - ttm_fence_object - *fence) -{ - kref_get(&fence->kref); - return fence; -} - -/** - * ttm_fence_object_unref - * - * @p_fence: Pointer to a ref-counted pinter to a struct ttm_fence_object. - * - * Unreference the fence object pointed to by *(@p_fence), clearing - * *(p_fence). - */ - -extern void ttm_fence_object_unref(struct ttm_fence_object **p_fence); - -/** - * ttm_fence_object_signaled - * - * @fence: Pointer to the struct ttm_fence_object. - * @mask: Type mask to check whether signaled. - * - * This function checks (without waiting) whether the fence object - * pointed to by @fence has signaled the types indicated by @mask, - * and returns 1 if true, 0 if false. This function does NOT perform - * an implicit fence flush. - */ - -extern bool -ttm_fence_object_signaled(struct ttm_fence_object *fence, uint32_t mask); - -/** - * ttm_fence_class - * - * @fence: Pointer to the struct ttm_fence_object. - * - * Convenience function that returns the fence class of a - * struct ttm_fence_object. - */ - -static inline uint32_t ttm_fence_class(const struct ttm_fence_object *fence) -{ - return fence->fence_class; -} - -/** - * ttm_fence_types - * - * @fence: Pointer to the struct ttm_fence_object. - * - * Convenience function that returns the fence types of a - * struct ttm_fence_object. - */ - -static inline uint32_t ttm_fence_types(const struct ttm_fence_object *fence) -{ - return fence->fence_type; -} - -/* - * The functions below are wrappers to the above functions, with - * similar names but with sync_obj omitted. These wrappers are intended - * to be plugged directly into the buffer object driver's sync object - * API, if the driver chooses to use ttm_fence_objects as buffer object - * sync objects. In the prototypes below, a sync_obj is cast to a - * struct ttm_fence_object, whereas a sync_arg is cast to an - * uint32_t representing a fence_type argument. - */ - -extern bool ttm_fence_sync_obj_signaled(void *sync_obj, void *sync_arg); -extern int ttm_fence_sync_obj_wait(void *sync_obj, void *sync_arg, - bool lazy, bool interruptible); -extern int ttm_fence_sync_obj_flush(void *sync_obj, void *sync_arg); -extern void ttm_fence_sync_obj_unref(void **sync_obj); -extern void *ttm_fence_sync_obj_ref(void *sync_obj); - -#endif diff --git a/drivers/staging/gma500/psb_ttm_fence_driver.h b/drivers/staging/gma500/psb_ttm_fence_driver.h deleted file mode 100644 index c35c569fa3f0..000000000000 --- a/drivers/staging/gma500/psb_ttm_fence_driver.h +++ /dev/null @@ -1,302 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA - * 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. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - */ -#ifndef _TTM_FENCE_DRIVER_H_ -#define _TTM_FENCE_DRIVER_H_ - -#include <linux/kref.h> -#include <linux/spinlock.h> -#include <linux/wait.h> -#include "psb_ttm_fence_api.h" -#include "ttm/ttm_memory.h" - -/** @file ttm_fence_driver.h - * - * Definitions needed for a driver implementing the - * ttm_fence subsystem. - */ - -/** - * struct ttm_fence_class_manager: - * - * @wrap_diff: Sequence difference to catch 32-bit wrapping. - * if (seqa - seqb) > @wrap_diff, then seqa < seqb. - * @flush_diff: Sequence difference to trigger fence flush. - * if (cur_seq - seqa) > @flush_diff, then consider fence object with - * seqa as old an needing a flush. - * @sequence_mask: Mask of valid bits in a fence sequence. - * @lock: Lock protecting this struct as well as fence objects - * associated with this struct. - * @ring: Circular sequence-ordered list of fence objects. - * @pending_flush: Fence types currently needing a flush. - * @waiting_types: Fence types that are currently waited for. - * @fence_queue: Queue of waiters on fences belonging to this fence class. - * @highest_waiting_sequence: Sequence number of the fence with highest - * sequence number and that is waited for. - * @latest_queued_sequence: Sequence number of the fence latest queued - * on the ring. - */ - -struct ttm_fence_class_manager { - - /* - * Unprotected constant members. - */ - - uint32_t wrap_diff; - uint32_t flush_diff; - uint32_t sequence_mask; - - /* - * The rwlock protects this structure as well as - * the data in all fence objects belonging to this - * class. This should be OK as most fence objects are - * only read from once they're created. - */ - - rwlock_t lock; - struct list_head ring; - uint32_t pending_flush; - uint32_t waiting_types; - wait_queue_head_t fence_queue; - uint32_t highest_waiting_sequence; - uint32_t latest_queued_sequence; -}; - -/** - * struct ttm_fence_device - * - * @fence_class: Array of fence class managers. - * @num_classes: Array dimension of @fence_class. - * @count: Current number of fence objects for statistics. - * @driver: Driver struct. - * - * Provided in the driver interface so that the driver can derive - * from this struct for its driver_private, and accordingly - * access the driver_private from the fence driver callbacks. - * - * All members except "count" are initialized at creation and - * never touched after that. No protection needed. - * - * This struct is private to the fence implementation and to the fence - * driver callbacks, and may otherwise be used by drivers only to - * obtain the derived device_private object using container_of(). - */ - -struct ttm_fence_device { - struct ttm_mem_global *mem_glob; - struct ttm_fence_class_manager *fence_class; - uint32_t num_classes; - atomic_t count; - const struct ttm_fence_driver *driver; -}; - -/** - * struct ttm_fence_class_init - * - * @wrap_diff: Fence sequence number wrap indicator. If - * (sequence1 - sequence2) > @wrap_diff, then sequence1 is - * considered to be older than sequence2. - * @flush_diff: Fence sequence number flush indicator. - * If a non-completely-signaled fence has a fence sequence number - * sequence1 and (sequence1 - current_emit_sequence) > @flush_diff, - * the fence is considered too old and it will be flushed upon the - * next call of ttm_fence_flush_old(), to make sure no fences with - * stale sequence numbers remains unsignaled. @flush_diff should - * be sufficiently less than @wrap_diff. - * @sequence_mask: Mask with valid bits of the fence sequence - * number set to 1. - * - * This struct is used as input to ttm_fence_device_init. - */ - -struct ttm_fence_class_init { - uint32_t wrap_diff; - uint32_t flush_diff; - uint32_t sequence_mask; -}; - -/** - * struct ttm_fence_driver - * - * @has_irq: Called by a potential waiter. Should return 1 if a - * fence object with indicated parameters is expected to signal - * automatically, and 0 if the fence implementation needs to - * repeatedly call @poll to make it signal. - * @emit: Make sure a fence with the given parameters is - * present in the indicated command stream. Return its sequence number - * in "breadcrumb". - * @poll: Check and report sequences of the given "fence_class" - * that have signaled "types" - * @flush: Make sure that the types indicated by the bitfield - * ttm_fence_class_manager::pending_flush will eventually - * signal. These bits have been put together using the - * result from the needed_flush function described below. - * @needed_flush: Given the fence_class and fence_types indicated by - * "fence", and the last received fence sequence of this - * fence class, indicate what types need a fence flush to - * signal. Return as a bitfield. - * @wait: Set to non-NULL if the driver wants to override the fence - * wait implementation. Return 0 on success, -EBUSY on failure, - * and -ERESTART if interruptible and a signal is pending. - * @signaled: Driver callback that is called whenever a - * ttm_fence_object::signaled_types has changed status. - * This function is called from atomic context, - * with the ttm_fence_class_manager::lock held in write mode. - * @lockup: Driver callback that is called whenever a wait has exceeded - * the lifetime of a fence object. - * If there is a GPU lockup, - * this function should, if possible, reset the GPU, - * call the ttm_fence_handler with an error status, and - * return. If no lockup was detected, simply extend the - * fence timeout_jiffies and return. The driver might - * want to protect the lockup check with a mutex and cache a - * non-locked-up status for a while to avoid an excessive - * amount of lockup checks from every waiting thread. - */ - -struct ttm_fence_driver { - bool (*has_irq) (struct ttm_fence_device *fdev, - uint32_t fence_class, uint32_t flags); - int (*emit) (struct ttm_fence_device *fdev, - uint32_t fence_class, - uint32_t flags, - uint32_t *breadcrumb, unsigned long *timeout_jiffies); - void (*flush) (struct ttm_fence_device *fdev, uint32_t fence_class); - void (*poll) (struct ttm_fence_device *fdev, - uint32_t fence_class, uint32_t types); - uint32_t(*needed_flush) - (struct ttm_fence_object *fence); - int (*wait) (struct ttm_fence_object *fence, bool lazy, - bool interruptible, uint32_t mask); - void (*signaled) (struct ttm_fence_object *fence); - void (*lockup) (struct ttm_fence_object *fence, uint32_t fence_types); -}; - -/** - * function ttm_fence_device_init - * - * @num_classes: Number of fence classes for this fence implementation. - * @mem_global: Pointer to the global memory accounting info. - * @fdev: Pointer to an uninitialised struct ttm_fence_device. - * @init: Array of initialization info for each fence class. - * @replicate_init: Use the first @init initialization info for all classes. - * @driver: Driver callbacks. - * - * Initialize a struct ttm_fence_driver structure. Returns -ENOMEM if - * out-of-memory. Otherwise returns 0. - */ -extern int -ttm_fence_device_init(int num_classes, - struct ttm_mem_global *mem_glob, - struct ttm_fence_device *fdev, - const struct ttm_fence_class_init *init, - bool replicate_init, - const struct ttm_fence_driver *driver); - -/** - * function ttm_fence_device_release - * - * @fdev: Pointer to the fence device. - * - * Release all resources held by a fence device. Note that before - * this function is called, the caller must have made sure all fence - * objects belonging to this fence device are completely signaled. - */ - -extern void ttm_fence_device_release(struct ttm_fence_device *fdev); - -/** - * ttm_fence_handler - the fence handler. - * - * @fdev: Pointer to the fence device. - * @fence_class: Fence class that signals. - * @sequence: Signaled sequence. - * @type: Types that signal. - * @error: Error from the engine. - * - * This function signals all fences with a sequence previous to the - * @sequence argument, and belonging to @fence_class. The signaled fence - * types are provided in @type. If error is non-zero, the error member - * of the fence with sequence = @sequence is set to @error. This value - * may be reported back to user-space, indicating, for example an illegal - * 3D command or illegal mpeg data. - * - * This function is typically called from the driver::poll method when the - * command sequence preceding the fence marker has executed. It should be - * called with the ttm_fence_class_manager::lock held in write mode and - * may be called from interrupt context. - */ - -extern void -ttm_fence_handler(struct ttm_fence_device *fdev, - uint32_t fence_class, - uint32_t sequence, uint32_t type, uint32_t error); - -/** - * ttm_fence_driver_from_dev - * - * @fdev: The ttm fence device. - * - * Returns a pointer to the fence driver struct. - */ - -static inline const struct ttm_fence_driver *ttm_fence_driver_from_dev( - struct ttm_fence_device *fdev) -{ - return fdev->driver; -} - -/** - * ttm_fence_driver - * - * @fence: Pointer to a ttm fence object. - * - * Returns a pointer to the fence driver struct. - */ - -static inline const struct ttm_fence_driver *ttm_fence_driver(struct - ttm_fence_object - *fence) -{ - return ttm_fence_driver_from_dev(fence->fdev); -} - -/** - * ttm_fence_fc - * - * @fence: Pointer to a ttm fence object. - * - * Returns a pointer to the struct ttm_fence_class_manager for the - * fence class of @fence. - */ - -static inline struct ttm_fence_class_manager *ttm_fence_fc(struct - ttm_fence_object - *fence) -{ - return &fence->fdev->fence_class[fence->fence_class]; -} - -#endif diff --git a/drivers/staging/gma500/psb_ttm_fence_user.c b/drivers/staging/gma500/psb_ttm_fence_user.c deleted file mode 100644 index 36f974fc607d..000000000000 --- a/drivers/staging/gma500/psb_ttm_fence_user.c +++ /dev/null @@ -1,237 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA - * 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. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - */ - -#include <drm/drmP.h> -#include "psb_ttm_fence_user.h" -#include "ttm/ttm_object.h" -#include "psb_ttm_fence_driver.h" -#include "psb_ttm_userobj_api.h" - -/** - * struct ttm_fence_user_object - * - * @base: The base object used for user-space visibility and refcounting. - * - * @fence: The fence object itself. - * - */ - -struct ttm_fence_user_object { - struct ttm_base_object base; - struct ttm_fence_object fence; -}; - -static struct ttm_fence_user_object *ttm_fence_user_object_lookup( - struct ttm_object_file *tfile, - uint32_t handle) -{ - struct ttm_base_object *base; - - base = ttm_base_object_lookup(tfile, handle); - if (unlikely(base == NULL)) { - printk(KERN_ERR "Invalid fence handle 0x%08lx\n", - (unsigned long)handle); - return NULL; - } - - if (unlikely(base->object_type != ttm_fence_type)) { - ttm_base_object_unref(&base); - printk(KERN_ERR "Invalid fence handle 0x%08lx\n", - (unsigned long)handle); - return NULL; - } - - return container_of(base, struct ttm_fence_user_object, base); -} - -/* - * The fence object destructor. - */ - -static void ttm_fence_user_destroy(struct ttm_fence_object *fence) -{ - struct ttm_fence_user_object *ufence = - container_of(fence, struct ttm_fence_user_object, fence); - - ttm_mem_global_free(fence->fdev->mem_glob, sizeof(*ufence)); - kfree(ufence); -} - -/* - * The base object destructor. We basically unly unreference the - * attached fence object. - */ - -static void ttm_fence_user_release(struct ttm_base_object **p_base) -{ - struct ttm_fence_user_object *ufence; - struct ttm_base_object *base = *p_base; - struct ttm_fence_object *fence; - - *p_base = NULL; - - if (unlikely(base == NULL)) - return; - - ufence = container_of(base, struct ttm_fence_user_object, base); - fence = &ufence->fence; - ttm_fence_object_unref(&fence); -} - -int -ttm_fence_user_create(struct ttm_fence_device *fdev, - struct ttm_object_file *tfile, - uint32_t fence_class, - uint32_t fence_types, - uint32_t create_flags, - struct ttm_fence_object **fence, - uint32_t *user_handle) -{ - int ret; - struct ttm_fence_object *tmp; - struct ttm_fence_user_object *ufence; - - ret = ttm_mem_global_alloc(fdev->mem_glob, - sizeof(*ufence), - false, - false); - if (unlikely(ret != 0)) - return -ENOMEM; - - ufence = kmalloc(sizeof(*ufence), GFP_KERNEL); - if (unlikely(ufence == NULL)) { - ttm_mem_global_free(fdev->mem_glob, sizeof(*ufence)); - return -ENOMEM; - } - - ret = ttm_fence_object_init(fdev, - fence_class, - fence_types, create_flags, - &ttm_fence_user_destroy, &ufence->fence); - - if (unlikely(ret != 0)) - goto out_err0; - - /* - * One fence ref is held by the fence ptr we return. - * The other one by the base object. Need to up the - * fence refcount before we publish this object to - * user-space. - */ - - tmp = ttm_fence_object_ref(&ufence->fence); - ret = ttm_base_object_init(tfile, &ufence->base, - false, ttm_fence_type, - &ttm_fence_user_release, NULL); - - if (unlikely(ret != 0)) - goto out_err1; - - *fence = &ufence->fence; - *user_handle = ufence->base.hash.key; - - return 0; -out_err1: - ttm_fence_object_unref(&tmp); - tmp = &ufence->fence; - ttm_fence_object_unref(&tmp); - return ret; -out_err0: - ttm_mem_global_free(fdev->mem_glob, sizeof(*ufence)); - kfree(ufence); - return ret; -} - -int ttm_fence_signaled_ioctl(struct ttm_object_file *tfile, void *data) -{ - int ret; - union ttm_fence_signaled_arg *arg = data; - struct ttm_fence_object *fence; - struct ttm_fence_info info; - struct ttm_fence_user_object *ufence; - struct ttm_base_object *base; - ret = 0; - - ufence = ttm_fence_user_object_lookup(tfile, arg->req.handle); - if (unlikely(ufence == NULL)) - return -EINVAL; - - fence = &ufence->fence; - - if (arg->req.flush) { - ret = ttm_fence_object_flush(fence, arg->req.fence_type); - if (unlikely(ret != 0)) - goto out; - } - - info = ttm_fence_get_info(fence); - arg->rep.signaled_types = info.signaled_types; - arg->rep.fence_error = info.error; - -out: - base = &ufence->base; - ttm_base_object_unref(&base); - return ret; -} - -int ttm_fence_finish_ioctl(struct ttm_object_file *tfile, void *data) -{ - int ret; - union ttm_fence_finish_arg *arg = data; - struct ttm_fence_user_object *ufence; - struct ttm_base_object *base; - struct ttm_fence_object *fence; - ret = 0; - - ufence = ttm_fence_user_object_lookup(tfile, arg->req.handle); - if (unlikely(ufence == NULL)) - return -EINVAL; - - fence = &ufence->fence; - - ret = ttm_fence_object_wait(fence, - arg->req.mode & TTM_FENCE_FINISH_MODE_LAZY, - true, arg->req.fence_type); - if (likely(ret == 0)) { - struct ttm_fence_info info = ttm_fence_get_info(fence); - - arg->rep.signaled_types = info.signaled_types; - arg->rep.fence_error = info.error; - } - - base = &ufence->base; - ttm_base_object_unref(&base); - - return ret; -} - -int ttm_fence_unref_ioctl(struct ttm_object_file *tfile, void *data) -{ - struct ttm_fence_unref_arg *arg = data; - int ret = 0; - - ret = ttm_ref_object_base_unref(tfile, arg->handle, ttm_fence_type); - return ret; -} diff --git a/drivers/staging/gma500/psb_ttm_fence_user.h b/drivers/staging/gma500/psb_ttm_fence_user.h deleted file mode 100644 index 762a05728632..000000000000 --- a/drivers/staging/gma500/psb_ttm_fence_user.h +++ /dev/null @@ -1,140 +0,0 @@ -/************************************************************************** - * - * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA - * 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. - * - **************************************************************************/ -/* - * Authors - * Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#ifndef TTM_FENCE_USER_H -#define TTM_FENCE_USER_H - -#if !defined(__KERNEL__) && !defined(_KERNEL) -#include <stdint.h> -#endif - -#define TTM_FENCE_MAJOR 0 -#define TTM_FENCE_MINOR 1 -#define TTM_FENCE_PL 0 -#define TTM_FENCE_DATE "080819" - -/** - * struct ttm_fence_signaled_req - * - * @handle: Handle to the fence object. Input. - * - * @fence_type: Fence types we want to flush. Input. - * - * @flush: Boolean. Flush the indicated fence_types. Input. - * - * Argument to the TTM_FENCE_SIGNALED ioctl. - */ - -struct ttm_fence_signaled_req { - uint32_t handle; - uint32_t fence_type; - int32_t flush; - uint32_t pad64; -}; - -/** - * struct ttm_fence_rep - * - * @signaled_types: Fence type that has signaled. - * - * @fence_error: Command execution error. - * Hardware errors that are consequences of the execution - * of the command stream preceding the fence are reported - * here. - * - * Output argument to the TTM_FENCE_SIGNALED and - * TTM_FENCE_FINISH ioctls. - */ - -struct ttm_fence_rep { - uint32_t signaled_types; - uint32_t fence_error; -}; - -union ttm_fence_signaled_arg { - struct ttm_fence_signaled_req req; - struct ttm_fence_rep rep; -}; - -/* - * Waiting mode flags for the TTM_FENCE_FINISH ioctl. - * - * TTM_FENCE_FINISH_MODE_LAZY: Allow for sleeps during polling - * wait. - * - * TTM_FENCE_FINISH_MODE_NO_BLOCK: Don't block waiting for GPU, - * but return -EBUSY if the buffer is busy. - */ - -#define TTM_FENCE_FINISH_MODE_LAZY (1 << 0) -#define TTM_FENCE_FINISH_MODE_NO_BLOCK (1 << 1) - -/** - * struct ttm_fence_finish_req - * - * @handle: Handle to the fence object. Input. - * - * @fence_type: Fence types we want to finish. - * - * @mode: Wait mode. - * - * Input to the TTM_FENCE_FINISH ioctl. - */ - -struct ttm_fence_finish_req { - uint32_t handle; - uint32_t fence_type; - uint32_t mode; - uint32_t pad64; -}; - -union ttm_fence_finish_arg { - struct ttm_fence_finish_req req; - struct ttm_fence_rep rep; -}; - -/** - * struct ttm_fence_unref_arg - * - * @handle: Handle to the fence object. - * - * Argument to the TTM_FENCE_UNREF ioctl. - */ - -struct ttm_fence_unref_arg { - uint32_t handle; - uint32_t pad64; -}; - -/* - * Ioctl offsets from extenstion start. - */ - -#define TTM_FENCE_SIGNALED 0x01 -#define TTM_FENCE_FINISH 0x02 -#define TTM_FENCE_UNREF 0x03 - -#endif diff --git a/drivers/staging/gma500/psb_ttm_glue.c b/drivers/staging/gma500/psb_ttm_glue.c deleted file mode 100644 index d1d965e69ecd..000000000000 --- a/drivers/staging/gma500/psb_ttm_glue.c +++ /dev/null @@ -1,349 +0,0 @@ -/************************************************************************** - * Copyright (c) 2008, Intel Corporation. - * All Rights Reserved. - * Copyright (c) 2008, Tungsten Graphics Inc. Cedar Park, TX., USA. - * 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. - * - **************************************************************************/ - - -#include <drm/drmP.h> -#include "psb_drv.h" -#include "psb_ttm_userobj_api.h" -#include <linux/io.h> - - -static struct vm_operations_struct psb_ttm_vm_ops; - -/** - * NOTE: driver_private of drm_file is now a struct psb_file_data struct - * pPriv in struct psb_file_data contains the original psb_fpriv; - */ -int psb_open(struct inode *inode, struct file *filp) -{ - struct drm_file *file_priv; - struct drm_psb_private *dev_priv; - struct psb_fpriv *psb_fp; - struct psb_file_data *pvr_file_priv; - int ret; - - DRM_DEBUG("\n"); - - ret = drm_open(inode, filp); - if (unlikely(ret)) - return ret; - - psb_fp = kzalloc(sizeof(*psb_fp), GFP_KERNEL); - - if (unlikely(psb_fp == NULL)) - goto out_err0; - - file_priv = (struct drm_file *) filp->private_data; - dev_priv = psb_priv(file_priv->minor->dev); - - DRM_DEBUG("is_master %d\n", file_priv->is_master ? 1 : 0); - - psb_fp->tfile = ttm_object_file_init(dev_priv->tdev, - PSB_FILE_OBJECT_HASH_ORDER); - if (unlikely(psb_fp->tfile == NULL)) - goto out_err1; - - pvr_file_priv = (struct psb_file_data *)file_priv->driver_priv; - if (!pvr_file_priv) { - DRM_ERROR("drm file private is NULL\n"); - goto out_err1; - } - - pvr_file_priv->priv = psb_fp; - if (unlikely(dev_priv->bdev.dev_mapping == NULL)) - dev_priv->bdev.dev_mapping = dev_priv->dev->dev_mapping; - - return 0; - -out_err1: - kfree(psb_fp); -out_err0: - (void) drm_release(inode, filp); - return ret; -} - -int psb_release(struct inode *inode, struct file *filp) -{ - struct drm_file *file_priv; - struct psb_fpriv *psb_fp; - struct drm_psb_private *dev_priv; - int ret; - file_priv = (struct drm_file *) filp->private_data; - psb_fp = psb_fpriv(file_priv); - dev_priv = psb_priv(file_priv->minor->dev); - - ttm_object_file_release(&psb_fp->tfile); - kfree(psb_fp); - - ret = drm_release(inode, filp); - - return ret; -} - -int psb_fence_signaled_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - - return ttm_fence_signaled_ioctl(psb_fpriv(file_priv)->tfile, data); -} - -int psb_fence_finish_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return ttm_fence_finish_ioctl(psb_fpriv(file_priv)->tfile, data); -} - -int psb_fence_unref_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return ttm_fence_unref_ioctl(psb_fpriv(file_priv)->tfile, data); -} - -int psb_pl_waitidle_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return ttm_pl_waitidle_ioctl(psb_fpriv(file_priv)->tfile, data); -} - -int psb_pl_setstatus_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return ttm_pl_setstatus_ioctl(psb_fpriv(file_priv)->tfile, - &psb_priv(dev)->ttm_lock, data); - -} - -int psb_pl_synccpu_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return ttm_pl_synccpu_ioctl(psb_fpriv(file_priv)->tfile, data); -} - -int psb_pl_unref_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return ttm_pl_unref_ioctl(psb_fpriv(file_priv)->tfile, data); - -} - -int psb_pl_reference_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return ttm_pl_reference_ioctl(psb_fpriv(file_priv)->tfile, data); - -} - -int psb_pl_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_private *dev_priv = psb_priv(dev); - - return ttm_pl_create_ioctl(psb_fpriv(file_priv)->tfile, - &dev_priv->bdev, &dev_priv->ttm_lock, data); - -} - -int psb_pl_ub_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_private *dev_priv = psb_priv(dev); - - return ttm_pl_ub_create_ioctl(psb_fpriv(file_priv)->tfile, - &dev_priv->bdev, &dev_priv->ttm_lock, data); - -} -/** - * psb_ttm_fault - Wrapper around the ttm fault method. - * - * @vma: The struct vm_area_struct as in the vm fault() method. - * @vmf: The struct vm_fault as in the vm fault() method. - * - * Since ttm_fault() will reserve buffers while faulting, - * we need to take the ttm read lock around it, as this driver - * relies on the ttm_lock in write mode to exclude all threads from - * reserving and thus validating buffers in aperture- and memory shortage - * situations. - */ - -static int psb_ttm_fault(struct vm_area_struct *vma, - struct vm_fault *vmf) -{ - struct ttm_buffer_object *bo = (struct ttm_buffer_object *) - vma->vm_private_data; - struct drm_psb_private *dev_priv = - container_of(bo->bdev, struct drm_psb_private, bdev); - int ret; - - ret = ttm_read_lock(&dev_priv->ttm_lock, true); - if (unlikely(ret != 0)) - return VM_FAULT_NOPAGE; - - ret = dev_priv->ttm_vm_ops->fault(vma, vmf); - - ttm_read_unlock(&dev_priv->ttm_lock); - return ret; -} - -/** - * if vm_pgoff < DRM_PSB_FILE_PAGE_OFFSET call directly to - * PVRMMap - */ -int psb_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv; - struct drm_psb_private *dev_priv; - int ret; - - if (vma->vm_pgoff < DRM_PSB_FILE_PAGE_OFFSET || - vma->vm_pgoff > 2 * DRM_PSB_FILE_PAGE_OFFSET) -#if 0 /* FIXMEAC */ - return PVRMMap(filp, vma); -#else - return -EINVAL; -#endif - - file_priv = (struct drm_file *) filp->private_data; - dev_priv = psb_priv(file_priv->minor->dev); - - ret = ttm_bo_mmap(filp, vma, &dev_priv->bdev); - if (unlikely(ret != 0)) - return ret; - - if (unlikely(dev_priv->ttm_vm_ops == NULL)) { - dev_priv->ttm_vm_ops = (struct vm_operations_struct *) - vma->vm_ops; - psb_ttm_vm_ops = *vma->vm_ops; - psb_ttm_vm_ops.fault = &psb_ttm_fault; - } - - vma->vm_ops = &psb_ttm_vm_ops; - - return 0; -} -/* -ssize_t psb_ttm_write(struct file *filp, const char __user *buf, - size_t count, loff_t *f_pos) -{ - struct drm_file *file_priv = (struct drm_file *)filp->private_data; - struct drm_psb_private *dev_priv = psb_priv(file_priv->minor->dev); - - return ttm_bo_io(&dev_priv->bdev, filp, buf, NULL, count, f_pos, 1); -} - -ssize_t psb_ttm_read(struct file *filp, char __user *buf, - size_t count, loff_t *f_pos) -{ - struct drm_file *file_priv = (struct drm_file *)filp->private_data; - struct drm_psb_private *dev_priv = psb_priv(file_priv->minor->dev); - - return ttm_bo_io(&dev_priv->bdev, filp, NULL, buf, count, f_pos, 1); -} -*/ -int psb_verify_access(struct ttm_buffer_object *bo, - struct file *filp) -{ - struct drm_file *file_priv = (struct drm_file *)filp->private_data; - - if (capable(CAP_SYS_ADMIN)) - return 0; - - if (unlikely(!file_priv->authenticated)) - return -EPERM; - - return ttm_pl_verify_access(bo, psb_fpriv(file_priv)->tfile); -} - -static int psb_ttm_mem_global_init(struct drm_global_reference *ref) -{ - return ttm_mem_global_init(ref->object); -} - -static void psb_ttm_mem_global_release(struct drm_global_reference *ref) -{ - ttm_mem_global_release(ref->object); -} - -int psb_ttm_global_init(struct drm_psb_private *dev_priv) -{ - struct drm_global_reference *global_ref; - int ret; - - global_ref = &dev_priv->mem_global_ref; - global_ref->global_type = DRM_GLOBAL_TTM_MEM; - global_ref->size = sizeof(struct ttm_mem_global); - global_ref->init = &psb_ttm_mem_global_init; - global_ref->release = &psb_ttm_mem_global_release; - - ret = drm_global_item_ref(global_ref); - if (unlikely(ret != 0)) { - DRM_ERROR("Failed referencing a global TTM memory object.\n"); - return ret; - } - - dev_priv->bo_global_ref.mem_glob = dev_priv->mem_global_ref.object; - global_ref = &dev_priv->bo_global_ref.ref; - global_ref->global_type = DRM_GLOBAL_TTM_BO; - global_ref->size = sizeof(struct ttm_bo_global); - global_ref->init = &ttm_bo_global_init; - global_ref->release = &ttm_bo_global_release; - ret = drm_global_item_ref(global_ref); - if (ret != 0) { - DRM_ERROR("Failed setting up TTM BO subsystem.\n"); - drm_global_item_unref(global_ref); - return ret; - } - return 0; -} - -void psb_ttm_global_release(struct drm_psb_private *dev_priv) -{ - drm_global_item_unref(&dev_priv->mem_global_ref); -} - -int psb_getpageaddrs_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_getpageaddrs_arg *arg = data; - struct ttm_buffer_object *bo; - struct ttm_tt *ttm; - struct page **tt_pages; - unsigned long i, num_pages; - unsigned long *p = arg->page_addrs; - int ret = 0; - - bo = ttm_buffer_object_lookup(psb_fpriv(file_priv)->tfile, - arg->handle); - if (unlikely(bo == NULL)) { - printk(KERN_ERR - "Could not find buffer object for getpageaddrs.\n"); - return -EINVAL; - } - - arg->gtt_offset = bo->offset; - ttm = bo->ttm; - num_pages = ttm->num_pages; - tt_pages = ttm->pages; - - for (i = 0; i < num_pages; i++) - p[i] = (unsigned long)page_to_phys(tt_pages[i]); - - return ret; -} diff --git a/drivers/staging/gma500/psb_ttm_placement_user.c b/drivers/staging/gma500/psb_ttm_placement_user.c deleted file mode 100644 index 272b397982ed..000000000000 --- a/drivers/staging/gma500/psb_ttm_placement_user.c +++ /dev/null @@ -1,628 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * 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. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - */ - -#include "psb_ttm_placement_user.h" -#include "ttm/ttm_bo_driver.h" -#include "ttm/ttm_object.h" -#include "psb_ttm_userobj_api.h" -#include "ttm/ttm_lock.h" -#include <linux/slab.h> -#include <linux/sched.h> - -struct ttm_bo_user_object { - struct ttm_base_object base; - struct ttm_buffer_object bo; -}; - -static size_t pl_bo_size; - -static uint32_t psb_busy_prios[] = { - TTM_PL_TT, - TTM_PL_PRIV0, /* CI */ - TTM_PL_PRIV2, /* RAR */ - TTM_PL_PRIV1, /* DRM_PSB_MEM_MMU */ - TTM_PL_SYSTEM -}; - -static const struct ttm_placement default_placement = { - 0, 0, 0, NULL, 5, psb_busy_prios -}; - -static size_t ttm_pl_size(struct ttm_bo_device *bdev, unsigned long num_pages) -{ - size_t page_array_size = - (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK; - - if (unlikely(pl_bo_size == 0)) { - pl_bo_size = bdev->glob->ttm_bo_extra_size + - ttm_round_pot(sizeof(struct ttm_bo_user_object)); - } - - return bdev->glob->ttm_bo_size + 2 * page_array_size; -} - -static struct ttm_bo_user_object *ttm_bo_user_lookup(struct ttm_object_file - *tfile, uint32_t handle) -{ - struct ttm_base_object *base; - - base = ttm_base_object_lookup(tfile, handle); - if (unlikely(base == NULL)) { - printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n", - (unsigned long)handle); - return NULL; - } - - if (unlikely(base->object_type != ttm_buffer_type)) { - ttm_base_object_unref(&base); - printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n", - (unsigned long)handle); - return NULL; - } - - return container_of(base, struct ttm_bo_user_object, base); -} - -struct ttm_buffer_object *ttm_buffer_object_lookup(struct ttm_object_file - *tfile, uint32_t handle) -{ - struct ttm_bo_user_object *user_bo; - struct ttm_base_object *base; - - user_bo = ttm_bo_user_lookup(tfile, handle); - if (unlikely(user_bo == NULL)) - return NULL; - - (void)ttm_bo_reference(&user_bo->bo); - base = &user_bo->base; - ttm_base_object_unref(&base); - return &user_bo->bo; -} - -static void ttm_bo_user_destroy(struct ttm_buffer_object *bo) -{ - struct ttm_bo_user_object *user_bo = - container_of(bo, struct ttm_bo_user_object, bo); - - ttm_mem_global_free(bo->glob->mem_glob, bo->acc_size); - kfree(user_bo); -} - -static void ttm_bo_user_release(struct ttm_base_object **p_base) -{ - struct ttm_bo_user_object *user_bo; - struct ttm_base_object *base = *p_base; - struct ttm_buffer_object *bo; - - *p_base = NULL; - - if (unlikely(base == NULL)) - return; - - user_bo = container_of(base, struct ttm_bo_user_object, base); - bo = &user_bo->bo; - ttm_bo_unref(&bo); -} - -static void ttm_bo_user_ref_release(struct ttm_base_object *base, - enum ttm_ref_type ref_type) -{ - struct ttm_bo_user_object *user_bo = - container_of(base, struct ttm_bo_user_object, base); - struct ttm_buffer_object *bo = &user_bo->bo; - - switch (ref_type) { - case TTM_REF_SYNCCPU_WRITE: - ttm_bo_synccpu_write_release(bo); - break; - default: - BUG(); - } -} - -static void ttm_pl_fill_rep(struct ttm_buffer_object *bo, - struct ttm_pl_rep *rep) -{ - struct ttm_bo_user_object *user_bo = - container_of(bo, struct ttm_bo_user_object, bo); - - rep->gpu_offset = bo->offset; - rep->bo_size = bo->num_pages << PAGE_SHIFT; - rep->map_handle = bo->addr_space_offset; - rep->placement = bo->mem.placement; - rep->handle = user_bo->base.hash.key; - rep->sync_object_arg = (uint32_t) (unsigned long)bo->sync_obj_arg; -} - -/* FIXME Copy from upstream TTM */ -static inline size_t ttm_bo_size(struct ttm_bo_global *glob, - unsigned long num_pages) -{ - size_t page_array_size = (num_pages * sizeof(void *) + PAGE_SIZE - 1) & - PAGE_MASK; - - return glob->ttm_bo_size + 2 * page_array_size; -} - -/* FIXME Copy from upstream TTM "ttm_bo_create", upstream TTM does not - export this, so copy it here */ -static int ttm_bo_create_private(struct ttm_bo_device *bdev, - unsigned long size, - enum ttm_bo_type type, - struct ttm_placement *placement, - uint32_t page_alignment, - unsigned long buffer_start, - bool interruptible, - struct file *persistant_swap_storage, - struct ttm_buffer_object **p_bo) -{ - struct ttm_buffer_object *bo; - struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; - int ret; - - size_t acc_size = - ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT); - ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); - if (unlikely(ret != 0)) - return ret; - - bo = kzalloc(sizeof(*bo), GFP_KERNEL); - - if (unlikely(bo == NULL)) { - ttm_mem_global_free(mem_glob, acc_size); - return -ENOMEM; - } - - ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment, - buffer_start, interruptible, - persistant_swap_storage, acc_size, NULL); - if (likely(ret == 0)) - *p_bo = bo; - - return ret; -} - -int psb_ttm_bo_check_placement(struct ttm_buffer_object *bo, - struct ttm_placement *placement) -{ - int i; - - for (i = 0; i < placement->num_placement; i++) { - if (!capable(CAP_SYS_ADMIN)) { - if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) { - printk(KERN_ERR TTM_PFX "Need to be root to " - "modify NO_EVICT status.\n"); - return -EINVAL; - } - } - } - for (i = 0; i < placement->num_busy_placement; i++) { - if (!capable(CAP_SYS_ADMIN)) { - if (placement->busy_placement[i] - & TTM_PL_FLAG_NO_EVICT) { - printk(KERN_ERR TTM_PFX "Need to be root to modify NO_EVICT status.\n"); - return -EINVAL; - } - } - } - return 0; -} - -int ttm_buffer_object_create(struct ttm_bo_device *bdev, - unsigned long size, - enum ttm_bo_type type, - uint32_t flags, - uint32_t page_alignment, - unsigned long buffer_start, - bool interruptible, - struct file *persistant_swap_storage, - struct ttm_buffer_object **p_bo) -{ - struct ttm_placement placement = default_placement; - int ret; - - if ((flags & TTM_PL_MASK_CACHING) == 0) - flags |= TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED; - - placement.num_placement = 1; - placement.placement = &flags; - - ret = ttm_bo_create_private(bdev, - size, - type, - &placement, - page_alignment, - buffer_start, - interruptible, - persistant_swap_storage, - p_bo); - - return ret; -} - - -int ttm_pl_create_ioctl(struct ttm_object_file *tfile, - struct ttm_bo_device *bdev, - struct ttm_lock *lock, void *data) -{ - union ttm_pl_create_arg *arg = data; - struct ttm_pl_create_req *req = &arg->req; - struct ttm_pl_rep *rep = &arg->rep; - struct ttm_buffer_object *bo; - struct ttm_buffer_object *tmp; - struct ttm_bo_user_object *user_bo; - uint32_t flags; - int ret = 0; - struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; - struct ttm_placement placement = default_placement; - size_t acc_size = - ttm_pl_size(bdev, (req->size + PAGE_SIZE - 1) >> PAGE_SHIFT); - ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); - if (unlikely(ret != 0)) - return ret; - - flags = req->placement; - user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL); - if (unlikely(user_bo == NULL)) { - ttm_mem_global_free(mem_glob, acc_size); - return -ENOMEM; - } - - bo = &user_bo->bo; - ret = ttm_read_lock(lock, true); - if (unlikely(ret != 0)) { - ttm_mem_global_free(mem_glob, acc_size); - kfree(user_bo); - return ret; - } - - placement.num_placement = 1; - placement.placement = &flags; - - if ((flags & TTM_PL_MASK_CACHING) == 0) - flags |= TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED; - - ret = ttm_bo_init(bdev, bo, req->size, - ttm_bo_type_device, &placement, - req->page_alignment, 0, true, - NULL, acc_size, &ttm_bo_user_destroy); - ttm_read_unlock(lock); - - /* - * Note that the ttm_buffer_object_init function - * would've called the destroy function on failure!! - */ - - if (unlikely(ret != 0)) - goto out; - - tmp = ttm_bo_reference(bo); - ret = ttm_base_object_init(tfile, &user_bo->base, - flags & TTM_PL_FLAG_SHARED, - ttm_buffer_type, - &ttm_bo_user_release, - &ttm_bo_user_ref_release); - if (unlikely(ret != 0)) - goto out_err; - - ttm_pl_fill_rep(bo, rep); - ttm_bo_unref(&bo); -out: - return 0; -out_err: - ttm_bo_unref(&tmp); - ttm_bo_unref(&bo); - return ret; -} - -int ttm_pl_ub_create_ioctl(struct ttm_object_file *tfile, - struct ttm_bo_device *bdev, - struct ttm_lock *lock, void *data) -{ - union ttm_pl_create_ub_arg *arg = data; - struct ttm_pl_create_ub_req *req = &arg->req; - struct ttm_pl_rep *rep = &arg->rep; - struct ttm_buffer_object *bo; - struct ttm_buffer_object *tmp; - struct ttm_bo_user_object *user_bo; - uint32_t flags; - int ret = 0; - struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; - struct ttm_placement placement = default_placement; - size_t acc_size = - ttm_pl_size(bdev, (req->size + PAGE_SIZE - 1) >> PAGE_SHIFT); - ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); - if (unlikely(ret != 0)) - return ret; - - flags = req->placement; - user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL); - if (unlikely(user_bo == NULL)) { - ttm_mem_global_free(mem_glob, acc_size); - return -ENOMEM; - } - ret = ttm_read_lock(lock, true); - if (unlikely(ret != 0)) { - ttm_mem_global_free(mem_glob, acc_size); - kfree(user_bo); - return ret; - } - bo = &user_bo->bo; - - placement.num_placement = 1; - placement.placement = &flags; - - ret = ttm_bo_init(bdev, - bo, - req->size, - ttm_bo_type_user, - &placement, - req->page_alignment, - req->user_address, - true, - NULL, - acc_size, - &ttm_bo_user_destroy); - - /* - * Note that the ttm_buffer_object_init function - * would've called the destroy function on failure!! - */ - ttm_read_unlock(lock); - if (unlikely(ret != 0)) - goto out; - - tmp = ttm_bo_reference(bo); - ret = ttm_base_object_init(tfile, &user_bo->base, - flags & TTM_PL_FLAG_SHARED, - ttm_buffer_type, - &ttm_bo_user_release, - &ttm_bo_user_ref_release); - if (unlikely(ret != 0)) - goto out_err; - - ttm_pl_fill_rep(bo, rep); - ttm_bo_unref(&bo); -out: - return 0; -out_err: - ttm_bo_unref(&tmp); - ttm_bo_unref(&bo); - return ret; -} - -int ttm_pl_reference_ioctl(struct ttm_object_file *tfile, void *data) -{ - union ttm_pl_reference_arg *arg = data; - struct ttm_pl_rep *rep = &arg->rep; - struct ttm_bo_user_object *user_bo; - struct ttm_buffer_object *bo; - struct ttm_base_object *base; - int ret; - - user_bo = ttm_bo_user_lookup(tfile, arg->req.handle); - if (unlikely(user_bo == NULL)) { - printk(KERN_ERR "Could not reference buffer object.\n"); - return -EINVAL; - } - - bo = &user_bo->bo; - ret = ttm_ref_object_add(tfile, &user_bo->base, TTM_REF_USAGE, NULL); - if (unlikely(ret != 0)) { - printk(KERN_ERR - "Could not add a reference to buffer object.\n"); - goto out; - } - - ttm_pl_fill_rep(bo, rep); - -out: - base = &user_bo->base; - ttm_base_object_unref(&base); - return ret; -} - -int ttm_pl_unref_ioctl(struct ttm_object_file *tfile, void *data) -{ - struct ttm_pl_reference_req *arg = data; - - return ttm_ref_object_base_unref(tfile, arg->handle, TTM_REF_USAGE); -} - -int ttm_pl_synccpu_ioctl(struct ttm_object_file *tfile, void *data) -{ - struct ttm_pl_synccpu_arg *arg = data; - struct ttm_bo_user_object *user_bo; - struct ttm_buffer_object *bo; - struct ttm_base_object *base; - bool existed; - int ret; - - switch (arg->op) { - case TTM_PL_SYNCCPU_OP_GRAB: - user_bo = ttm_bo_user_lookup(tfile, arg->handle); - if (unlikely(user_bo == NULL)) { - printk(KERN_ERR - "Could not find buffer object for synccpu.\n"); - return -EINVAL; - } - bo = &user_bo->bo; - base = &user_bo->base; - ret = ttm_bo_synccpu_write_grab(bo, - arg->access_mode & - TTM_PL_SYNCCPU_MODE_NO_BLOCK); - if (unlikely(ret != 0)) { - ttm_base_object_unref(&base); - goto out; - } - ret = ttm_ref_object_add(tfile, &user_bo->base, - TTM_REF_SYNCCPU_WRITE, &existed); - if (existed || ret != 0) - ttm_bo_synccpu_write_release(bo); - ttm_base_object_unref(&base); - break; - case TTM_PL_SYNCCPU_OP_RELEASE: - ret = ttm_ref_object_base_unref(tfile, arg->handle, - TTM_REF_SYNCCPU_WRITE); - break; - default: - ret = -EINVAL; - break; - } -out: - return ret; -} - -int ttm_pl_setstatus_ioctl(struct ttm_object_file *tfile, - struct ttm_lock *lock, void *data) -{ - union ttm_pl_setstatus_arg *arg = data; - struct ttm_pl_setstatus_req *req = &arg->req; - struct ttm_pl_rep *rep = &arg->rep; - struct ttm_buffer_object *bo; - struct ttm_bo_device *bdev; - struct ttm_placement placement = default_placement; - uint32_t flags[2]; - int ret; - - bo = ttm_buffer_object_lookup(tfile, req->handle); - if (unlikely(bo == NULL)) { - printk(KERN_ERR - "Could not find buffer object for setstatus.\n"); - return -EINVAL; - } - - bdev = bo->bdev; - - ret = ttm_read_lock(lock, true); - if (unlikely(ret != 0)) - goto out_err0; - - ret = ttm_bo_reserve(bo, true, false, false, 0); - if (unlikely(ret != 0)) - goto out_err1; - - ret = ttm_bo_wait_cpu(bo, false); - if (unlikely(ret != 0)) - goto out_err2; - - flags[0] = req->set_placement; - flags[1] = req->clr_placement; - - placement.num_placement = 2; - placement.placement = flags; - - /* Review internal locking ? FIXMEAC */ - ret = psb_ttm_bo_check_placement(bo, &placement); - if (unlikely(ret != 0)) - goto out_err2; - - placement.num_placement = 1; - flags[0] = (req->set_placement | bo->mem.placement) - & ~req->clr_placement; - - ret = ttm_bo_validate(bo, &placement, true, false, false); - if (unlikely(ret != 0)) - goto out_err2; - - ttm_pl_fill_rep(bo, rep); -out_err2: - ttm_bo_unreserve(bo); -out_err1: - ttm_read_unlock(lock); -out_err0: - ttm_bo_unref(&bo); - return ret; -} - -static int psb_ttm_bo_block_reservation(struct ttm_buffer_object *bo, - bool interruptible, bool no_wait) -{ - int ret; - - while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) { - if (no_wait) - return -EBUSY; - else if (interruptible) { - ret = wait_event_interruptible(bo->event_queue, - atomic_read(&bo->reserved) == 0); - if (unlikely(ret != 0)) - return -ERESTART; - } else { - wait_event(bo->event_queue, - atomic_read(&bo->reserved) == 0); - } - } - return 0; -} - -static void psb_ttm_bo_unblock_reservation(struct ttm_buffer_object *bo) -{ - atomic_set(&bo->reserved, 0); - wake_up_all(&bo->event_queue); -} - -int ttm_pl_waitidle_ioctl(struct ttm_object_file *tfile, void *data) -{ - struct ttm_pl_waitidle_arg *arg = data; - struct ttm_buffer_object *bo; - int ret; - - bo = ttm_buffer_object_lookup(tfile, arg->handle); - if (unlikely(bo == NULL)) { - printk(KERN_ERR "Could not find buffer object for waitidle.\n"); - return -EINVAL; - } - - ret = - psb_ttm_bo_block_reservation(bo, true, - arg->mode & TTM_PL_WAITIDLE_MODE_NO_BLOCK); - if (unlikely(ret != 0)) - goto out; - ret = ttm_bo_wait(bo, - arg->mode & TTM_PL_WAITIDLE_MODE_LAZY, - true, arg->mode & TTM_PL_WAITIDLE_MODE_NO_BLOCK); - psb_ttm_bo_unblock_reservation(bo); -out: - ttm_bo_unref(&bo); - return ret; -} - -int ttm_pl_verify_access(struct ttm_buffer_object *bo, - struct ttm_object_file *tfile) -{ - struct ttm_bo_user_object *ubo; - - /* - * Check bo subclass. - */ - - if (unlikely(bo->destroy != &ttm_bo_user_destroy)) - return -EPERM; - - ubo = container_of(bo, struct ttm_bo_user_object, bo); - if (likely(ubo->base.shareable || ubo->base.tfile == tfile)) - return 0; - - return -EPERM; -} diff --git a/drivers/staging/gma500/psb_ttm_placement_user.h b/drivers/staging/gma500/psb_ttm_placement_user.h deleted file mode 100644 index 8b7068b54441..000000000000 --- a/drivers/staging/gma500/psb_ttm_placement_user.h +++ /dev/null @@ -1,252 +0,0 @@ -/************************************************************************** - * - * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA - * 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. - * - **************************************************************************/ -/* - * Authors - * Thomas Hellström <thomas-at-tungstengraphics-dot-com> - */ - -#ifndef _TTM_PLACEMENT_USER_H_ -#define _TTM_PLACEMENT_USER_H_ - -#if !defined(__KERNEL__) && !defined(_KERNEL) -#include <stdint.h> -#else -#include <linux/kernel.h> -#endif - -#include "ttm/ttm_placement.h" - -#define TTM_PLACEMENT_MAJOR 0 -#define TTM_PLACEMENT_MINOR 1 -#define TTM_PLACEMENT_PL 0 -#define TTM_PLACEMENT_DATE "080819" - -/** - * struct ttm_pl_create_req - * - * @size: The buffer object size. - * @placement: Flags that indicate initial acceptable - * placement. - * @page_alignment: Required alignment in pages. - * - * Input to the TTM_BO_CREATE ioctl. - */ - -struct ttm_pl_create_req { - uint64_t size; - uint32_t placement; - uint32_t page_alignment; -}; - -/** - * struct ttm_pl_create_ub_req - * - * @size: The buffer object size. - * @user_address: User-space address of the memory area that - * should be used to back the buffer object cast to 64-bit. - * @placement: Flags that indicate initial acceptable - * placement. - * @page_alignment: Required alignment in pages. - * - * Input to the TTM_BO_CREATE_UB ioctl. - */ - -struct ttm_pl_create_ub_req { - uint64_t size; - uint64_t user_address; - uint32_t placement; - uint32_t page_alignment; -}; - -/** - * struct ttm_pl_rep - * - * @gpu_offset: The current offset into the memory region used. - * This can be used directly by the GPU if there are no - * additional GPU mapping procedures used by the driver. - * - * @bo_size: Actual buffer object size. - * - * @map_handle: Offset into the device address space. - * Used for map, seek, read, write. This will never change - * during the lifetime of an object. - * - * @placement: Flag indicating the placement status of - * the buffer object using the TTM_PL flags above. - * - * @sync_object_arg: Used for user-space synchronization and - * depends on the synchronization model used. If fences are - * used, this is the buffer_object::fence_type_mask - * - * Output from the TTM_PL_CREATE and TTM_PL_REFERENCE, and - * TTM_PL_SETSTATUS ioctls. - */ - -struct ttm_pl_rep { - uint64_t gpu_offset; - uint64_t bo_size; - uint64_t map_handle; - uint32_t placement; - uint32_t handle; - uint32_t sync_object_arg; - uint32_t pad64; -}; - -/** - * struct ttm_pl_setstatus_req - * - * @set_placement: Placement flags to set. - * - * @clr_placement: Placement flags to clear. - * - * @handle: The object handle - * - * Input to the TTM_PL_SETSTATUS ioctl. - */ - -struct ttm_pl_setstatus_req { - uint32_t set_placement; - uint32_t clr_placement; - uint32_t handle; - uint32_t pad64; -}; - -/** - * struct ttm_pl_reference_req - * - * @handle: The object to put a reference on. - * - * Input to the TTM_PL_REFERENCE and the TTM_PL_UNREFERENCE ioctls. - */ - -struct ttm_pl_reference_req { - uint32_t handle; - uint32_t pad64; -}; - -/* - * ACCESS mode flags for SYNCCPU. - * - * TTM_SYNCCPU_MODE_READ will guarantee that the GPU is not - * writing to the buffer. - * - * TTM_SYNCCPU_MODE_WRITE will guarantee that the GPU is not - * accessing the buffer. - * - * TTM_SYNCCPU_MODE_NO_BLOCK makes sure the call does not wait - * for GPU accesses to finish but return -EBUSY. - * - * TTM_SYNCCPU_MODE_TRYCACHED Try to place the buffer in cacheable - * memory while synchronized for CPU. - */ - -#define TTM_PL_SYNCCPU_MODE_READ TTM_ACCESS_READ -#define TTM_PL_SYNCCPU_MODE_WRITE TTM_ACCESS_WRITE -#define TTM_PL_SYNCCPU_MODE_NO_BLOCK (1 << 2) -#define TTM_PL_SYNCCPU_MODE_TRYCACHED (1 << 3) - -/** - * struct ttm_pl_synccpu_arg - * - * @handle: The object to synchronize. - * - * @access_mode: access mode indicated by the - * TTM_SYNCCPU_MODE flags. - * - * @op: indicates whether to grab or release the - * buffer for cpu usage. - * - * Input to the TTM_PL_SYNCCPU ioctl. - */ - -struct ttm_pl_synccpu_arg { - uint32_t handle; - uint32_t access_mode; - enum { - TTM_PL_SYNCCPU_OP_GRAB, - TTM_PL_SYNCCPU_OP_RELEASE - } op; - uint32_t pad64; -}; - -/* - * Waiting mode flags for the TTM_BO_WAITIDLE ioctl. - * - * TTM_WAITIDLE_MODE_LAZY: Allow for sleeps during polling - * wait. - * - * TTM_WAITIDLE_MODE_NO_BLOCK: Don't block waiting for GPU, - * but return -EBUSY if the buffer is busy. - */ - -#define TTM_PL_WAITIDLE_MODE_LAZY (1 << 0) -#define TTM_PL_WAITIDLE_MODE_NO_BLOCK (1 << 1) - -/** - * struct ttm_waitidle_arg - * - * @handle: The object to synchronize. - * - * @mode: wait mode indicated by the - * TTM_SYNCCPU_MODE flags. - * - * Argument to the TTM_BO_WAITIDLE ioctl. - */ - -struct ttm_pl_waitidle_arg { - uint32_t handle; - uint32_t mode; -}; - -union ttm_pl_create_arg { - struct ttm_pl_create_req req; - struct ttm_pl_rep rep; -}; - -union ttm_pl_reference_arg { - struct ttm_pl_reference_req req; - struct ttm_pl_rep rep; -}; - -union ttm_pl_setstatus_arg { - struct ttm_pl_setstatus_req req; - struct ttm_pl_rep rep; -}; - -union ttm_pl_create_ub_arg { - struct ttm_pl_create_ub_req req; - struct ttm_pl_rep rep; -}; - -/* - * Ioctl offsets. - */ - -#define TTM_PL_CREATE 0x00 -#define TTM_PL_REFERENCE 0x01 -#define TTM_PL_UNREF 0x02 -#define TTM_PL_SYNCCPU 0x03 -#define TTM_PL_WAITIDLE 0x04 -#define TTM_PL_SETSTATUS 0x05 -#define TTM_PL_CREATE_UB 0x06 - -#endif diff --git a/drivers/staging/gma500/psb_ttm_userobj_api.h b/drivers/staging/gma500/psb_ttm_userobj_api.h deleted file mode 100644 index 6a8f7c4ddc78..000000000000 --- a/drivers/staging/gma500/psb_ttm_userobj_api.h +++ /dev/null @@ -1,85 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA - * All Rights Reserved. - * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA - * 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. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - */ - -#ifndef _TTM_USEROBJ_API_H_ -#define _TTM_USEROBJ_API_H_ - -#include "psb_ttm_placement_user.h" -#include "psb_ttm_fence_user.h" -#include "ttm/ttm_object.h" -#include "psb_ttm_fence_api.h" -#include "ttm/ttm_bo_api.h" - -struct ttm_lock; - -/* - * User ioctls. - */ - -extern int ttm_pl_create_ioctl(struct ttm_object_file *tfile, - struct ttm_bo_device *bdev, - struct ttm_lock *lock, void *data); -extern int ttm_pl_ub_create_ioctl(struct ttm_object_file *tfile, - struct ttm_bo_device *bdev, - struct ttm_lock *lock, void *data); -extern int ttm_pl_reference_ioctl(struct ttm_object_file *tfile, void *data); -extern int ttm_pl_unref_ioctl(struct ttm_object_file *tfile, void *data); -extern int ttm_pl_synccpu_ioctl(struct ttm_object_file *tfile, void *data); -extern int ttm_pl_setstatus_ioctl(struct ttm_object_file *tfile, - struct ttm_lock *lock, void *data); -extern int ttm_pl_waitidle_ioctl(struct ttm_object_file *tfile, void *data); -extern int ttm_fence_signaled_ioctl(struct ttm_object_file *tfile, void *data); -extern int ttm_fence_finish_ioctl(struct ttm_object_file *tfile, void *data); -extern int ttm_fence_unref_ioctl(struct ttm_object_file *tfile, void *data); - -extern int -ttm_fence_user_create(struct ttm_fence_device *fdev, - struct ttm_object_file *tfile, - uint32_t fence_class, - uint32_t fence_types, - uint32_t create_flags, - struct ttm_fence_object **fence, uint32_t * user_handle); - -extern struct ttm_buffer_object *ttm_buffer_object_lookup(struct ttm_object_file - *tfile, - uint32_t handle); - -extern int -ttm_pl_verify_access(struct ttm_buffer_object *bo, - struct ttm_object_file *tfile); - -extern int ttm_buffer_object_create(struct ttm_bo_device *bdev, - unsigned long size, - enum ttm_bo_type type, - uint32_t flags, - uint32_t page_alignment, - unsigned long buffer_start, - bool interruptible, - struct file *persistant_swap_storage, - struct ttm_buffer_object **p_bo); - -extern int psb_ttm_bo_check_placement(struct ttm_buffer_object *bo, - struct ttm_placement *placement); -#endif |