aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/gma500
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/gma500')
-rw-r--r--drivers/staging/gma500/accel_2d.c24
-rw-r--r--drivers/staging/gma500/cdv_device.c1
-rw-r--r--drivers/staging/gma500/framebuffer.c92
-rw-r--r--drivers/staging/gma500/gem.c5
-rw-r--r--drivers/staging/gma500/gtt.c81
-rw-r--r--drivers/staging/gma500/gtt.h3
-rw-r--r--drivers/staging/gma500/intel_i2c.c1
-rw-r--r--drivers/staging/gma500/intel_opregion.c1
-rw-r--r--drivers/staging/gma500/mdfld_dsi_output.c1
-rw-r--r--drivers/staging/gma500/mdfld_intel_display.c12
-rw-r--r--drivers/staging/gma500/mdfld_output.c3
-rw-r--r--drivers/staging/gma500/mid_bios.c1
-rw-r--r--drivers/staging/gma500/mrst_crtc.c16
-rw-r--r--drivers/staging/gma500/mrst_hdmi_i2c.c1
-rw-r--r--drivers/staging/gma500/power.c8
-rw-r--r--drivers/staging/gma500/psb_device.c32
-rw-r--r--drivers/staging/gma500/psb_drv.c50
-rw-r--r--drivers/staging/gma500/psb_drv.h6
-rw-r--r--drivers/staging/gma500/psb_intel_display.c4
-rw-r--r--drivers/staging/gma500/psb_intel_lvds.c61
-rw-r--r--drivers/staging/gma500/psb_irq.c71
-rw-r--r--drivers/staging/gma500/psb_lid.c2
22 files changed, 288 insertions, 188 deletions
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c
index 14400fcfe8a7..114b99a1ce19 100644
--- a/drivers/staging/gma500/accel_2d.c
+++ b/drivers/staging/gma500/accel_2d.c
@@ -111,14 +111,15 @@ static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
int ret = 0;
int i;
unsigned submit_size;
+ unsigned long flags;
- mutex_lock(&dev_priv->mutex_2d);
+ spin_lock_irqsave(&dev_priv->lock_2d, flags);
while (size > 0) {
submit_size = (size < 0x60) ? size : 0x60;
size -= submit_size;
ret = psb_2d_wait_available(dev_priv, submit_size);
if (ret)
- break;
+ break;
submit_size <<= 2;
@@ -127,7 +128,7 @@ static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
}
- mutex_unlock(&dev_priv->mutex_2d);
+ spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
return ret;
}
@@ -327,8 +328,9 @@ int psbfb_sync(struct fb_info *info)
struct drm_psb_private *dev_priv = dev->dev_private;
unsigned long _end = jiffies + DRM_HZ;
int busy = 0;
+ unsigned long flags;
- mutex_lock(&dev_priv->mutex_2d);
+ spin_lock_irqsave(&dev_priv->lock_2d, flags);
/*
* First idle the 2D engine.
*/
@@ -357,7 +359,7 @@ int psbfb_sync(struct fb_info *info)
_PSB_C2B_STATUS_BUSY) != 0);
out:
- mutex_unlock(&dev_priv->mutex_2d);
+ spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
return (busy) ? -EBUSY : 0;
}
@@ -388,19 +390,19 @@ int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
for (i = 0; i < op->size; i++, op_ptr++) {
u32 r = *op_ptr & 0xF0000000;
/* Fill in the GTT offsets for the command buffer */
- if (r == PSB_2D_SRC_SURF_BH ||
- r == PSB_2D_DST_SURF_BH ||
+ if (r == PSB_2D_SRC_SURF_BH ||
+ r == PSB_2D_DST_SURF_BH ||
r == PSB_2D_MASK_SURF_BH ||
r == PSB_2D_PAT_SURF_BH) {
i++;
op_ptr++;
if (i == op->size)
goto bad;
- if (*op_ptr)
+ if (*op_ptr)
goto bad;
- *op_ptr = gtt->offset;
- continue;
- }
+ *op_ptr = gtt->offset;
+ continue;
+ }
}
psbfb_2d_submit(dev_priv, op->cmd, op->size);
err = 0;
diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c
index 87614e0d396a..8ec10caab13e 100644
--- a/drivers/staging/gma500/cdv_device.c
+++ b/drivers/staging/gma500/cdv_device.c
@@ -30,7 +30,6 @@
#define VGA_SR_INDEX 0x3c4
#define VGA_SR_DATA 0x3c5
-/* FIXME: should check if we are the active VGA device ?? */
static void cdv_disable_vga(struct drm_device *dev)
{
u8 sr1;
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
index ebfde13ec18f..3f39a37456fc 100644
--- a/drivers/staging/gma500/framebuffer.c
+++ b/drivers/staging/gma500/framebuffer.c
@@ -37,6 +37,7 @@
#include "psb_intel_reg.h"
#include "psb_intel_drv.h"
#include "framebuffer.h"
+#include "gtt.h"
#include "mdfld_output.h"
@@ -91,6 +92,21 @@ static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
return 0;
}
+static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct psb_fbdev *fbdev = info->par;
+ struct psb_framebuffer *psbfb = &fbdev->pfb;
+ struct drm_device *dev = psbfb->base.dev;
+
+ /*
+ * We have to poke our nose in here. The core fb code assumes
+ * panning is part of the hardware that can be invoked before
+ * the actual fb is mapped. In our case that isn't quite true.
+ */
+ if (psbfb->gtt->npage)
+ psb_gtt_roll(dev, psbfb->gtt, var->yoffset);
+ return 0;
+}
void psbfb_suspend(struct drm_device *dev)
{
@@ -217,6 +233,21 @@ static struct fb_ops psbfb_ops = {
.fb_ioctl = psbfb_ioctl,
};
+static struct fb_ops psbfb_roll_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = drm_fb_helper_check_var,
+ .fb_set_par = drm_fb_helper_set_par,
+ .fb_blank = drm_fb_helper_blank,
+ .fb_setcolreg = psbfb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_pan_display = psbfb_pan,
+ .fb_mmap = psbfb_mmap,
+ .fb_sync = psbfb_sync,
+ .fb_ioctl = psbfb_ioctl,
+};
+
static struct fb_ops psbfb_unaccel_ops = {
.owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var,
@@ -304,6 +335,7 @@ static struct drm_framebuffer *psb_framebuffer_create
* psbfb_alloc - allocate frame buffer memory
* @dev: the DRM device
* @aligned_size: space needed
+ * @force: fall back to GEM buffers if need be
*
* 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
@@ -311,11 +343,9 @@ static struct drm_framebuffer *psb_framebuffer_create
* and back it with a GEM object.
*
* In this case the GEM object has no handle.
- *
- * FIXME: console speed up - allocate twice the space if room and use
- * hardware scrolling for acceleration.
*/
-static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
+static struct gtt_range *psbfb_alloc(struct drm_device *dev,
+ int aligned_size, int force)
{
struct gtt_range *backing;
/* Begin by trying to use stolen memory backing */
@@ -326,6 +356,9 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
return backing;
psb_gtt_free_range(dev, backing);
}
+ if (!force)
+ return NULL;
+
/* Next try using GEM host memory */
backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
if (backing == NULL)
@@ -359,6 +392,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
int size;
int ret;
struct gtt_range *backing;
+ int gtt_roll = 1;
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
@@ -368,17 +402,37 @@ static int psbfb_create(struct psb_fbdev *fbdev,
if (mode_cmd.bpp == 24)
mode_cmd.bpp = 32;
- /* HW requires pitch to be 64 byte aligned */
- mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
+ /* Acceleration via the GTT requires pitch to be 4096 byte aligned
+ (ie 1024 or 2048 pixels in normal use) */
+ mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 4096);
mode_cmd.depth = sizes->surface_depth;
size = mode_cmd.pitch * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);
/* Allocate the framebuffer in the GTT with stolen page backing */
- backing = psbfb_alloc(dev, size);
- if (backing == NULL)
- return -ENOMEM;
+ backing = psbfb_alloc(dev, size, 0);
+ if (backing == NULL) {
+ /*
+ * We couldn't get the space we wanted, fall back to the
+ * display engine requirement instead. The HW requires
+ * the pitch to be 64 byte aligned
+ */
+
+ gtt_roll = 0; /* Don't use GTT accelerated scrolling */
+
+ mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
+ mode_cmd.depth = sizes->surface_depth;
+
+ size = mode_cmd.pitch * mode_cmd.height;
+ size = ALIGN(size, PAGE_SIZE);
+
+ /* Allocate the framebuffer in the GTT with stolen page
+ backing when there is room */
+ backing = psbfb_alloc(dev, size, 1);
+ if (backing == NULL)
+ return -ENOMEM;
+ }
mutex_lock(&dev->struct_mutex);
@@ -402,11 +456,14 @@ static int psbfb_create(struct psb_fbdev *fbdev,
strcpy(info->fix.id, "psbfb");
info->flags = FBINFO_DEFAULT;
- /* No 2D engine */
- if (!dev_priv->ops->accel_2d)
- info->fbops = &psbfb_unaccel_ops;
- else
+ if (gtt_roll) { /* GTT rolling seems best */
+ info->fbops = &psbfb_roll_ops;
+ info->flags |= FBINFO_HWACCEL_YPAN;
+ }
+ else if (dev_priv->ops->accel_2d) /* 2D engine */
info->fbops = &psbfb_ops;
+ else /* Software */
+ info->fbops = &psbfb_unaccel_ops;
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
@@ -416,6 +473,8 @@ static int psbfb_create(struct psb_fbdev *fbdev,
info->fix.smem_start = dev->mode_config.fb_base;
info->fix.smem_len = size;
+ info->fix.ywrapstep = gtt_roll;
+ info->fix.ypanstep = gtt_roll;
if (backing->stolen) {
/* Accessed stolen memory directly */
@@ -733,9 +792,12 @@ static void psb_setup_outputs(struct drm_device *dev)
clone_mask = (1 << INTEL_OUTPUT_MIPI2);
break;
case INTEL_OUTPUT_HDMI:
- if (IS_MFLD(dev))
+ /* HDMI on crtc 1 for SoC devices and crtc 0 for
+ Cedarview. HDMI on Poulsbo is only via external
+ logic */
+ if (IS_MFLD(dev) || IS_MRST(dev))
crtc_mask = (1 << 1);
- else /* FIXME: review Oaktrail */
+ else
crtc_mask = (1 << 0); /* Cedarview */
clone_mask = (1 << INTEL_OUTPUT_HDMI);
break;
diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c
index 65fdd6b8ab16..f6433c037d24 100644
--- a/drivers/staging/gma500/gem.c
+++ b/drivers/staging/gma500/gem.c
@@ -120,8 +120,7 @@ static int psb_gem_create(struct drm_file *file,
/* 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 */
+ /* GEM doesn't give an error code so use -ENOMEM */
dev_err(dev->dev, "GEM init failed for %lld\n", size);
return -ENOMEM;
}
@@ -191,8 +190,6 @@ int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
* 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.
- *
- * FIXME
*/
int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c
index 461ead251bbd..e770bd190a5c 100644
--- a/drivers/staging/gma500/gtt.c
+++ b/drivers/staging/gma500/gtt.c
@@ -72,9 +72,8 @@ u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
* @r: our GTT range
*
* Take our preallocated GTT range and insert the GEM object into
- * the GTT.
- *
- * FIXME: gtt lock ?
+ * the GTT. This is protected via the gtt mutex which the caller
+ * must hold.
*/
static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
{
@@ -96,12 +95,17 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
set_pages_array_uc(pages, r->npage);
/* Write our page entries into the GTT itself */
- for (i = 0; i < r->npage; i++) {
- pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/);
+ for (i = r->roll; i < r->npage; i++) {
+ pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+ iowrite32(pte, gtt_slot++);
+ }
+ for (i = 0; i < r->roll; i++) {
+ pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
iowrite32(pte, gtt_slot++);
}
/* Make sure all the entries are set before we return */
ioread32(gtt_slot - 1);
+
return 0;
}
@@ -111,9 +115,9 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
* @r: our GTT range
*
* Remove a preallocated GTT range from the GTT. Overwrite all the
- * page table entries with the dummy page
+ * page table entries with the dummy page. This is protected via the gtt
+ * mutex which the caller must hold.
*/
-
static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
{
struct drm_psb_private *dev_priv = dev->dev_private;
@@ -132,11 +136,52 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
}
/**
+ * psb_gtt_roll - set scrolling position
+ * @dev: our DRM device
+ * @r: the gtt mapping we are using
+ * @roll: roll offset
+ *
+ * Roll an existing pinned mapping by moving the pages through the GTT.
+ * This allows us to implement hardware scrolling on the consoles without
+ * a 2D engine
+ */
+void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
+{
+ u32 *gtt_slot, pte;
+ int i;
+
+ if (roll >= r->npage) {
+ WARN_ON(1);
+ return;
+ }
+
+ r->roll = roll;
+
+ /* Not currently in the GTT - no worry we will write the mapping at
+ the right position when it gets pinned */
+ if (!r->stolen && !r->in_gart)
+ return;
+
+ gtt_slot = psb_gtt_entry(dev, r);
+
+ for (i = r->roll; i < r->npage; i++) {
+ pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+ iowrite32(pte, gtt_slot++);
+ }
+ for (i = 0; i < r->roll; i++) {
+ pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+ 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
+ * While we hold this the pages cannot be swapped out. This is protected
+ * via the gtt mutex which the caller must hold.
*/
static int psb_gtt_attach_pages(struct gtt_range *gt)
{
@@ -158,7 +203,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
gt->npage = pages;
for (i = 0; i < pages; i++) {
- /* FIXME: review flags later */
+ /* FIXME: needs updating as per mail from Hugh Dickins */
p = read_cache_page_gfp(mapping, i,
__GFP_COLD | GFP_KERNEL);
if (IS_ERR(p))
@@ -181,7 +226,8 @@ err:
*
* Undo the effect of psb_gtt_attach_pages. At this point the pages
* must have been removed from the GTT as they could now be paged out
- * and move bus address.
+ * and move bus address. This is protected via the gtt mutex which the
+ * caller must hold.
*/
static void psb_gtt_detach_pages(struct gtt_range *gt)
{
@@ -300,6 +346,7 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
gt->resource.name = name;
gt->stolen = backed;
gt->in_gart = backed;
+ gt->roll = 0;
/* Ensure this is set for non GEM objects */
gt->gem.dev = dev;
ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
@@ -390,15 +437,18 @@ int psb_gtt_init(struct drm_device *dev, int resume)
pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
/*
- * FIXME: video mmu has hw bug to access 0x0D0000000,
- * then make gatt start at 0x0e000,0000
+ * The video mmu has a hw bug when accessing 0x0D0000000.
+ * Make gatt start at 0x0e000,0000. This doesn't actually
+ * matter for us but may do if the video acceleration ever
+ * gets opened up.
*/
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;
- /* CDV workaround */
+ /* Some CDV firmware doesn't report this currently. In which case the
+ system has 64 gtt pages */
if (pg->gtt_start == 0 || gtt_pages == 0) {
dev_err(dev->dev, "GTT PCI BAR not initialized.\n");
gtt_pages = 64;
@@ -412,13 +462,16 @@ int psb_gtt_init(struct drm_device *dev, int resume)
if (pg->gatt_pages == 0 || pg->gatt_start == 0) {
static struct resource fudge; /* Preferably peppermint */
-
/* This can occur on CDV SDV systems. Fudge it in this case.
We really don't care what imaginary space is being allocated
at this point */
dev_err(dev->dev, "GATT PCI BAR not initialized.\n");
pg->gatt_start = 0x40000000;
pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
+ /* This is a little confusing but in fact the GTT is providing
+ a view from the GPU into memory and not vice versa. As such
+ this is really allocating space that is not the same as the
+ CPU address space on CDV */
fudge.start = 0x40000000;
fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1;
fudge.name = "fudge";
diff --git a/drivers/staging/gma500/gtt.h b/drivers/staging/gma500/gtt.h
index e0e1cb6f9bd6..aa1742387f5a 100644
--- a/drivers/staging/gma500/gtt.h
+++ b/drivers/staging/gma500/gtt.h
@@ -49,6 +49,7 @@ struct gtt_range {
bool mmapping; /* Is mmappable */
struct page **pages; /* Backing pages if present */
int npage; /* Number of backing pages */
+ int roll; /* Roll applied to the GTT entries */
};
extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
@@ -57,5 +58,7 @@ 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);
+extern void psb_gtt_roll(struct drm_device *dev,
+ struct gtt_range *gt, int roll);
#endif
diff --git a/drivers/staging/gma500/intel_i2c.c b/drivers/staging/gma500/intel_i2c.c
index e33432df510c..51cbf65268e6 100644
--- a/drivers/staging/gma500/intel_i2c.c
+++ b/drivers/staging/gma500/intel_i2c.c
@@ -20,6 +20,7 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
+#include <linux/export.h>
#include "psb_drv.h"
#include "psb_intel_reg.h"
diff --git a/drivers/staging/gma500/intel_opregion.c b/drivers/staging/gma500/intel_opregion.c
index d2e60376982f..d946bc1b17bf 100644
--- a/drivers/staging/gma500/intel_opregion.c
+++ b/drivers/staging/gma500/intel_opregion.c
@@ -20,6 +20,7 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
+ * FIXME: resolve with the i915 version
*/
#include "psb_drv.h"
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
index 9050c0f78b15..3f979db2c3a5 100644
--- a/drivers/staging/gma500/mdfld_dsi_output.c
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -32,6 +32,7 @@
#include <asm/intel_scu_ipc.h>
#include "mdfld_dsi_pkg_sender.h"
#include <linux/pm_runtime.h>
+#include <linux/moduleparam.h>
#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
index aa2ff559383d..8eb827ecc3d3 100644
--- a/drivers/staging/gma500/mdfld_intel_display.c
+++ b/drivers/staging/gma500/mdfld_intel_display.c
@@ -282,7 +282,7 @@ static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
return -EINVAL;
}
-#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
+#if 1 /* FIXME_JLIU7 can't enable cursorB/C HW issue. need to remove after HW fix */
if (pipe != 0)
return 0;
#endif
@@ -484,7 +484,7 @@ void mdfld_disable_crtc (struct drm_device *dev, int pipe)
/* FIXME_JLIU7 MDFLD_PO revisit */
/* Wait for vblank for the disable to take effect */
-// MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev);
+/* MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev); */
/* Next, disable display pipes */
temp = REG_READ(pipeconf_reg);
@@ -561,7 +561,6 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
//gbdispstatus = true;
}
-
/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
@@ -1150,8 +1149,11 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
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*/
+ /*
+ * Medfield doesn't have register support for centering so
+ * we need to mess with the h/vblank and h/vsync start and
+ * ends to get central
+ */
int offsetX = 0, offsetY = 0;
offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c
index ee55f87ba1fd..eabf53d58f92 100644
--- a/drivers/staging/gma500/mdfld_output.c
+++ b/drivers/staging/gma500/mdfld_output.c
@@ -26,6 +26,7 @@
*/
#include <linux/init.h>
+#include <linux/moduleparam.h>
#include "mdfld_dsi_dbi.h"
#include "mdfld_dsi_dpi.h"
#include "mdfld_dsi_output.h"
@@ -167,4 +168,4 @@ void mdfld_output_setup(struct drm_device *dev)
else
mdfld_dbi_dsr_init(dev);
}
-} \ No newline at end of file
+}
diff --git a/drivers/staging/gma500/mid_bios.c b/drivers/staging/gma500/mid_bios.c
index 8cfe301f8fb2..ee3c0368e320 100644
--- a/drivers/staging/gma500/mid_bios.c
+++ b/drivers/staging/gma500/mid_bios.c
@@ -23,6 +23,7 @@
* - Check ioremap failures
*/
+#include <linux/moduleparam.h>
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
index 72464dd0f23d..c9311a573c28 100644
--- a/drivers/staging/gma500/mrst_crtc.c
+++ b/drivers/staging/gma500/mrst_crtc.c
@@ -521,12 +521,11 @@ 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;
@@ -572,15 +571,10 @@ int mrst_pipe_set_base(struct drm_crtc *crtc,
}
REG_WRITE(dspcntr_reg, dspcntr);
- 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);
- }
+ REG_WRITE(dspbase, offset);
+ REG_READ(dspbase);
+ REG_WRITE(dspsurf, start);
+ REG_READ(dspsurf);
pipe_set_base_exit:
gma_power_end(dev);
diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c
index 351b9d897b9f..36e7edc4d14c 100644
--- a/drivers/staging/gma500/mrst_hdmi_i2c.c
+++ b/drivers/staging/gma500/mrst_hdmi_i2c.c
@@ -29,6 +29,7 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include "psb_drv.h"
#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
index 972bea7c1af2..436fe9733b16 100644
--- a/drivers/staging/gma500/power.c
+++ b/drivers/staging/gma500/power.c
@@ -83,7 +83,7 @@ static void gma_suspend_display(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
- if (dev_priv->suspended)
+ if (!dev_priv->display_power)
return;
dev_priv->ops->save_regs(dev);
dev_priv->ops->power_down(dev);
@@ -101,7 +101,7 @@ 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)
+ if (dev_priv->display_power)
return;
/* turn on the display power island */
@@ -265,6 +265,8 @@ bool gma_power_begin(struct drm_device *dev, bool force_on)
/* Ok power up needed */
ret = gma_resume_pci(dev->pdev);
if (ret == 0) {
+ /* FIXME: we want to defer this for Medfield/Oaktrail */
+ gma_resume_display(dev);
psb_irq_preinstall(dev);
psb_irq_postinstall(dev);
pm_runtime_get(&dev->pdev->dev);
@@ -302,7 +304,7 @@ int psb_runtime_suspend(struct device *dev)
int psb_runtime_resume(struct device *dev)
{
- return 0;
+ return gma_power_resume(dev);;
}
int psb_runtime_idle(struct device *dev)
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
index 46591323595a..b97aa78519f2 100644
--- a/drivers/staging/gma500/psb_device.c
+++ b/drivers/staging/gma500/psb_device.c
@@ -213,7 +213,6 @@ static int psb_restore_display_registers(struct drm_device *dev)
struct drm_psb_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
struct drm_connector *connector;
- int pp_stat;
/* Display arbitration + watermarks */
PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
@@ -237,37 +236,6 @@ static int psb_restore_display_registers(struct drm_device *dev)
connector->funcs->restore(connector);
mutex_unlock(&dev->mode_config.mutex);
-
- if (dev_priv->iLVDS_enable) {
- /*shutdown the panel*/
- PSB_WVDC32(0, PP_CONTROL);
- do {
- pp_stat = PSB_RVDC32(PP_STATUS);
- } while (pp_stat & 0x80000000);
-
- /* Turn off the plane */
- PSB_WVDC32(0x58000000, DSPACNTR);
- PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
- /* Wait ~4 ticks */
- msleep(4);
- /* Turn off pipe */
- PSB_WVDC32(0x0, PIPEACONF);
- /* Wait ~8 ticks */
- msleep(8);
-
- /* Turn off PLLs */
- PSB_WVDC32(0, MRST_DPLL_A);
- } else {
- PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
- PSB_WVDC32(0x0, PIPEACONF);
- PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
- while (REG_READ(0x70008) & 0x40000000)
- cpu_relax();
- while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
- != DPI_FIFO_EMPTY)
- cpu_relax();
- PSB_WVDC32(0, DEVICE_READY_REG);
- }
return 0;
}
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index b2cdce7b97ef..986a04d16ba8 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -35,6 +35,7 @@
#include <linux/notifier.h>
#include <linux/spinlock.h>
#include <linux/pm_runtime.h>
+#include <linux/module.h>
#include <acpi/video.h>
static int drm_psb_trap_pagefaults;
@@ -183,7 +184,6 @@ static void psb_lastclose(struct drm_device *dev)
static void psb_do_takedown(struct drm_device *dev)
{
- /* FIXME: do we need to clean up the gtt here ? */
}
static int psb_do_init(struct drm_device *dev)
@@ -229,7 +229,7 @@ static int psb_do_init(struct drm_device *dev)
spin_lock_init(&dev_priv->irqmask_lock);
- mutex_init(&dev_priv->mutex_2d);
+ spin_lock_init(&dev_priv->lock_2d);
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
@@ -329,6 +329,11 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->dev = dev;
dev->dev_private = (void *) dev_priv;
+ if (!IS_PSB(dev)) {
+ if (pci_enable_msi(dev->pdev))
+ dev_warn(dev->dev, "Enabling MSI failed!\n");
+ }
+
dev_priv->num_pipe = dev_priv->ops->pipes;
resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
@@ -410,7 +415,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
- if (drm_core_check_feature(dev, DRIVER_MODESET))
+ if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET))
drm_irq_install(dev);
dev->vblank_disable_allowed = 1;
@@ -444,12 +449,9 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
if (ret)
return ret;
-#if 0
- /*enable runtime pm at last*/
- pm_runtime_enable(&dev->pdev->dev);
+
+ /* Enable runtime pm at last */
pm_runtime_set_active(&dev->pdev->dev);
-#endif
- /*Intel drm driver load is done, continue doing pvr load*/
return 0;
out_err:
psb_driver_unload(dev);
@@ -466,14 +468,13 @@ static int psb_sizes_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_psb_private *dev_priv = psb_priv(dev);
- struct drm_psb_sizes_arg *arg =
- (struct drm_psb_sizes_arg *) data;
+ struct drm_psb_sizes_arg *arg = data;
*arg = dev_priv->sizes;
return 0;
}
-static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
+static int psb_dc_state_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
uint32_t flags;
@@ -481,8 +482,7 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
struct drm_mode_object *obj;
struct drm_connector *connector;
struct drm_crtc *crtc;
- struct drm_psb_dc_state_arg *arg =
- (struct drm_psb_dc_state_arg *)data;
+ struct drm_psb_dc_state_arg *arg = data;
/* Double check MRST case */
@@ -1110,15 +1110,12 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
{
struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- static unsigned int runtime_allowed;
-
- if (runtime_allowed == 1 && dev_priv->is_lvds_on) {
- runtime_allowed++;
- pm_runtime_allow(&dev->pdev->dev);
- dev_priv->rpm_enabled = 1;
- }
- return drm_ioctl(filp, cmd, arg);
+ int ret;
+
+ pm_runtime_forbid(dev->dev);
+ ret = drm_ioctl(filp, cmd, arg);
+ pm_runtime_allow(dev->dev);
+ return ret;
/* FIXME: do we need to wrap the other side of this */
}
@@ -1137,8 +1134,12 @@ static void psb_remove(struct pci_dev *pdev)
}
static const struct dev_pm_ops psb_pm_ops = {
- .resume = gma_power_resume,
.suspend = gma_power_suspend,
+ .resume = gma_power_resume,
+ .freeze = gma_power_suspend,
+ .thaw = gma_power_resume,
+ .poweroff = gma_power_suspend,
+ .restore = gma_power_resume,
.runtime_suspend = psb_runtime_suspend,
.runtime_resume = psb_runtime_resume,
.runtime_idle = psb_runtime_idle,
@@ -1207,9 +1208,6 @@ static struct pci_driver psb_pci_driver = {
static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- /* MLD Added this from Inaky's patch */
- if (pci_enable_msi(pdev))
- dev_warn(&pdev->dev, "Enable MSI failed!\n");
return drm_get_pci_dev(pdev, ent, &driver);
}
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index fd4732dd783a..11d963a055be 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -43,6 +43,7 @@ enum {
CHIP_MFLD_0130 = 3, /* Medfield */
};
+#define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108)
#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100)
#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130)
@@ -134,6 +135,9 @@ enum {
#define _PSB_IRQ_MSVDX_FLAG (1<<19)
#define _LNC_IRQ_TOPAZ_FLAG (1<<20)
+#define _PSB_PIPE_EVENT_FLAG (_PSB_VSYNC_PIPEA_FLAG | \
+ _PSB_VSYNC_PIPEB_FLAG)
+
/* This flag includes all the display IRQ bits excepts the vblank irqs. */
#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \
_MDFLD_PIPEB_EVENT_FLAG | \
@@ -608,7 +612,7 @@ struct drm_psb_private {
void (*exit_idle)(struct drm_device *dev, u32 update_src);
/* 2D acceleration */
- struct mutex mutex_2d;
+ spinlock_t lock_2d;
/* FIXME: Arrays anyone ? */
struct mdfld_dsi_encoder *encoder0;
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 4afa671f9747..caa9d86f26d8 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -1102,10 +1102,6 @@ static int psb_crtc_set_config(struct drm_mode_set *set)
{
int ret;
struct drm_device *dev = set->crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->rpm_enabled)
- return drm_crtc_helper_set_config(set);
pm_runtime_forbid(&dev->pdev->dev);
ret = drm_crtc_helper_set_config(set);
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index c6436da60732..21022e1a977a 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -68,20 +68,23 @@ struct psb_intel_lvds_priv {
static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
- u32 retVal;
+ u32 ret;
if (gma_power_begin(dev, false)) {
- retVal = ((REG_READ(BLC_PWM_CTL) &
- BACKLIGHT_MODULATION_FREQ_MASK) >>
- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
+ ret = REG_READ(BLC_PWM_CTL);
gma_power_end(dev);
- } else
- retVal = ((dev_priv->saveBLC_PWM_CTL &
- BACKLIGHT_MODULATION_FREQ_MASK) >>
- BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
- return retVal;
+ } else /* Powered off, use the saved value */
+ ret = dev_priv->saveBLC_PWM_CTL;
+
+ /* Top 15bits hold the frequency mask */
+ ret = (ret & BACKLIGHT_MODULATION_FREQ_MASK) >>
+ BACKLIGHT_MODULATION_FREQ_SHIFT;
+
+ ret *= 2; /* Return a 16bit range as needed for setting */
+ if (ret == 0)
+ dev_err(dev->dev, "BL bug: Reg %08x save %08X\n",
+ REG_READ(BLC_PWM_CTL), dev_priv->saveBLC_PWM_CTL);
+ return ret;
}
/*
@@ -142,7 +145,7 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
max_pwm_blc = psb_intel_lvds_get_max_backlight(dev);
/*BLC_PWM_CTL Should be initiated while backlight device init*/
- BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
+ BUG_ON(max_pwm_blc == 0);
blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
@@ -154,6 +157,10 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
(max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
(blc_pwm_duty_cycle));
+ dev_info(dev->dev, "Backlight lvds set brightness %08x\n",
+ (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
+ (blc_pwm_duty_cycle));
+
return 0;
}
@@ -162,14 +169,12 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
*/
void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
{
- /*u32 blc_pwm_ctl;*/
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
+ struct drm_psb_private *dev_priv = dev->dev_private;
dev_dbg(dev->dev, "backlight level is %d\n", level);
if (!dev_priv->lvds_bl) {
- dev_err(dev->dev, "NO LVDS Backlight Info\n");
+ dev_err(dev->dev, "NO LVDS backlight info\n");
return;
}
@@ -190,11 +195,13 @@ static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
u32 blc_pwm_ctl;
if (gma_power_begin(dev, false)) {
- blc_pwm_ctl =
- REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+ blc_pwm_ctl = REG_READ(BLC_PWM_CTL);
+ blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
REG_WRITE(BLC_PWM_CTL,
(blc_pwm_ctl |
(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
+ dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
+ (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
gma_power_end(dev);
} else {
blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
@@ -212,9 +219,11 @@ static void psb_intel_lvds_set_power(struct drm_device *dev,
{
u32 pp_status;
- if (!gma_power_begin(dev, true))
+ if (!gma_power_begin(dev, true)) {
+ dev_err(dev->dev, "set power, chip off!\n");
return;
-
+ }
+
if (on) {
REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
POWER_TARGET_ON);
@@ -296,9 +305,6 @@ static void psb_intel_lvds_restore(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
u32 pp_status;
-
- /*struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;*/
struct psb_intel_output *psb_intel_output =
to_psb_intel_output(connector);
struct psb_intel_lvds_priv *lvds_priv =
@@ -382,7 +388,6 @@ 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;
- /* FIXME: review for Medfield */
/* 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");
@@ -622,7 +627,8 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
goto set_prop_error;
else {
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *devp = encoder->dev->dev_private;
+ struct drm_psb_private *devp =
+ encoder->dev->dev_private;
struct backlight_device *bd = devp->backlight_device;
if (bd) {
bd->props.brightness = value;
@@ -695,8 +701,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
struct drm_encoder *encoder;
struct drm_display_mode *scan; /* *modes, *bios_mode; */
struct drm_crtc *crtc;
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
+ struct drm_psb_private *dev_priv = dev->dev_private;
u32 lvds;
int pipe;
@@ -712,8 +717,8 @@ void psb_intel_lvds_init(struct drm_device *dev,
}
psb_intel_output->dev_priv = lvds_priv;
-
psb_intel_output->mode_dev = mode_dev;
+
connector = &psb_intel_output->base;
encoder = &psb_intel_output->enc;
drm_connector_init(dev, &psb_intel_output->base,
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c
index 4a0fa42893f9..36dd63044b06 100644
--- a/drivers/staging/gma500/psb_irq.c
+++ b/drivers/staging/gma500/psb_irq.c
@@ -139,21 +139,10 @@ void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
}
/**
- * Display controller interrupt handler for vsync/vblank.
- *
- */
-static void mid_vblank_handler(struct drm_device *dev, uint32_t pipe)
-{
- drm_handle_vblank(dev, pipe);
-}
-
-
-/**
* Display controller interrupt handler for pipe event.
*
*/
-#define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff
-static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
+static void mid_pipe_event_handler(struct drm_device *dev, int pipe)
{
struct drm_psb_private *dev_priv =
(struct drm_psb_private *) dev->dev_private;
@@ -162,6 +151,7 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
uint32_t pipe_stat_reg = psb_pipestat(pipe);
uint32_t pipe_enable = dev_priv->pipestat[pipe];
uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
+ uint32_t pipe_clear;
uint32_t i = 0;
spin_lock(&dev_priv->irqmask_lock);
@@ -172,27 +162,23 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
spin_unlock(&dev_priv->irqmask_lock);
- /* clear the 2nd level interrupt status bits */
- /**
- * FIXME: shouldn't use while loop here. However, the interrupt
- * status 'sticky' bits cannot be cleared by setting '1' to that
- * bit once...
- */
- for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i++) {
+ /* Clear the 2nd level interrupt status bits
+ * Sometimes the bits are very sticky so we repeat until they unstick */
+ for (i = 0; i < 0xffff; i++) {
PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
- (void) PSB_RVDC32(pipe_stat_reg);
+ pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status;
- if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0)
+ if (pipe_clear == 0)
break;
}
- if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
+ if (pipe_clear)
dev_err(dev->dev,
- "%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x.\n",
- __func__, PSB_RVDC32(pipe_stat_reg));
+ "%s, can't clear status bits for pipe %d, its value = 0x%x.\n",
+ __func__, pipe, PSB_RVDC32(pipe_stat_reg));
if (pipe_stat_val & PIPE_VBLANK_STATUS)
- mid_vblank_handler(dev, pipe);
+ drm_handle_vblank(dev, pipe);
if (pipe_stat_val & PIPE_TE_STATUS)
drm_handle_vblank(dev, pipe);
@@ -203,8 +189,11 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
*/
static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
{
- if (vdc_stat & _PSB_PIPEA_EVENT_FLAG)
+ if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
mid_pipe_event_handler(dev, 0);
+
+ if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG)
+ mid_pipe_event_handler(dev, 1);
}
irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
@@ -220,8 +209,13 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
+ if (vdc_stat & _PSB_PIPE_EVENT_FLAG)
+ dsp_int = 1;
+
+ /* FIXME: Handle Medfield
if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)
dsp_int = 1;
+ */
if (vdc_stat & _PSB_IRQ_SGX_FLAG)
sgx_int = 1;
@@ -267,13 +261,18 @@ void psb_irq_preinstall(struct drm_device *dev)
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;
+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
+ if (dev->vblank_enabled[1])
+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
+
+ /* FIXME: Handle Medfield irq mask
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*/
+ /* 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);
}
@@ -471,7 +470,13 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
- mid_enable_pipe_event(dev_priv, pipe);
+ if (pipe == 0)
+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
+ else if (pipe == 1)
+ dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
+
+ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
@@ -493,7 +498,13 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
#endif
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
- mid_disable_pipe_event(dev_priv, pipe);
+ if (pipe == 0)
+ dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG;
+ else if (pipe == 1)
+ dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG;
+
+ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
diff --git a/drivers/staging/gma500/psb_lid.c b/drivers/staging/gma500/psb_lid.c
index af328516561e..b867aabe6bf3 100644
--- a/drivers/staging/gma500/psb_lid.c
+++ b/drivers/staging/gma500/psb_lid.c
@@ -52,8 +52,6 @@ static void psb_lid_timer_func(unsigned long data)
pp_status = REG_READ(PP_STATUS);
} while ((pp_status & PP_ON) == 0);
}
- /* printk(KERN_INFO"%s: lid: closed\n", __FUNCTION__); */
-
dev_priv->lid_last_state = readl(lid_state);
lid_timer_schedule: