drm: Merge branch 'drm-gma500-alancox' into drm-core-next

This merges a topic branch containing patches from Alan for the GMA500 driver.

* drm-gma500-alancox:
  gma500: Oaktrail BIOS handling
  gma500: Fix oaktrail probing part 1
  gma500: Be smarter about layout
  gma500: gtt based hardware scrolling console
  gma500: frame buffer locking
  gma500: Fix backlight crash
  gma500: kill bogus code
  gma500: Convert spaces to tabs in accel_2d.c.
  gma500: do a pass over the FIXME tags
  gma500: Add VBLANK support for Poulsbo hardware
  gma500: Don't enable MSI on Poulsbo
  gma500: Only register interrupt handler for poulsbo hardware
  gma500: kill virtual mapping support
  gma500: Move the API
  gma500: kill off NUM_PIPE define
  gma500: Rename the ioctls to avoid clashing with the legacy drivers
  drm/gma500: begin pruning dead bits of API
This commit is contained in:
Dave Airlie 2011-12-06 09:59:52 +00:00
commit cee5ec4346
22 changed files with 435 additions and 935 deletions

View file

@ -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,6 +359,6 @@ 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;
}

View file

@ -20,7 +20,7 @@
#include <linux/backlight.h>
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
#include "gma_drm.h"
#include "psb_drv.h"
#include "psb_reg.h"
#include "psb_intel_reg.h"
@ -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;

View file

@ -38,6 +38,7 @@
#include "psb_intel_reg.h"
#include "psb_intel_drv.h"
#include "framebuffer.h"
#include "gtt.h"
static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
@ -90,6 +91,25 @@ 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) {
/* GTT roll shifts in 4K pages, we need to shift the right
number of pages */
int pages = info->fix.line_length >> 12;
psb_gtt_roll(dev, psbfb->gtt, var->yoffset * pages);
}
return 0;
}
void psbfb_suspend(struct drm_device *dev)
{
@ -216,6 +236,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,
@ -306,16 +341,14 @@ 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
* stolen memory or the system has no stolen memory we allocate a range
* and back it with a GEM object.
* we fail as we don't have the virtual mapping space to really vmap it
* and the kernel console code can't handle non linear framebuffers.
*
* 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.
* Re-address this as and if the framebuffer layer grows this ability.
*/
static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
{
@ -328,17 +361,7 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
return backing;
psb_gtt_free_range(dev, backing);
}
/* Next try using GEM host memory */
backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
if (backing == NULL)
return NULL;
/* 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;
}
return backing;
return NULL;
}
/**
@ -362,6 +385,8 @@ static int psbfb_create(struct psb_fbdev *fbdev,
int ret;
struct gtt_range *backing;
u32 bpp, depth;
int gtt_roll = 0;
int pitch_lines = 0;
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
@ -371,17 +396,51 @@ static int psbfb_create(struct psb_fbdev *fbdev,
if (bpp == 24)
bpp = 32;
/* HW requires pitch to be 64 byte aligned */
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
depth = sizes->surface_depth;
do {
/*
* Acceleration via the GTT requires pitch to be
* power of two aligned. Preferably page but less
* is ok with some fonts
*/
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines);
depth = sizes->surface_depth;
size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);
size = mode_cmd.pitches[0] * 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;
/* Allocate the fb in the GTT with stolen page backing */
backing = psbfb_alloc(dev, size);
if (pitch_lines)
pitch_lines *= 2;
else
pitch_lines = 1;
gtt_roll++;
} while (backing == NULL && pitch_lines <= 16);
/* The final pitch we accepted if we succeeded */
pitch_lines /= 2;
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 */
pitch_lines = 64;
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
size = mode_cmd.pitches[0] * 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;
}
mutex_lock(&dev->struct_mutex);
@ -407,11 +466,13 @@ 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 (dev_priv->ops->accel_2d && pitch_lines > 8) /* 2D engine */
info->fbops = &psbfb_ops;
else if (gtt_roll) { /* GTT rolling seems best */
info->fbops = &psbfb_roll_ops;
info->flags |= FBINFO_HWACCEL_YPAN;
} else /* Software */
info->fbops = &psbfb_unaccel_ops;
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
@ -421,23 +482,12 @@ 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 = 0;
if (backing->stolen) {
/* Accessed stolen memory directly */
info->screen_base = (char *)dev_priv->vram_addr +
/* Accessed stolen memory directly */
info->screen_base = (char *)dev_priv->vram_addr +
backing->offset;
} else {
/* Pin the pages into the GTT and create a mapping to them */
psb_gtt_pin(backing);
info->screen_base = vm_map_ram(backing->pages, backing->npage,
-1, PAGE_KERNEL);
if (info->screen_base == NULL) {
psb_gtt_unpin(backing);
ret = -ENOMEM;
goto out_unref;
}
psbfb->vm_map = 1;
}
info->screen_size = size;
if (dev_priv->gtt.stolen_size) {
@ -471,11 +521,8 @@ static int psbfb_create(struct psb_fbdev *fbdev,
out_unref:
if (backing->stolen)
psb_gtt_free_range(dev, backing);
else {
if (psbfb->vm_map)
vm_unmap_ram(info->screen_base, backing->npage);
else
drm_gem_object_unreference(&backing->gem);
}
out_err1:
mutex_unlock(&dev->struct_mutex);
psb_gtt_free_range(dev, backing);
@ -549,13 +596,6 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
if (fbdev->psb_fb_helper.fbdev) {
info = fbdev->psb_fb_helper.fbdev;
/* If this is our base framebuffer then kill any virtual map
for the framebuffer layer and unpin it */
if (psbfb->vm_map) {
vm_unmap_ram(info->screen_base, psbfb->gtt->npage);
psb_gtt_unpin(psbfb->gtt);
}
unregister_framebuffer(info);
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
@ -765,7 +805,7 @@ void psb_modeset_init(struct drm_device *dev)
dev->mode_config.funcs = (void *) &psb_mode_funcs;
/* set memory base */
/* MRST and PSB should use BAR 2*/
/* Oaktrail and Poulsbo should use BAR 2*/
pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
&(dev->mode_config.fb_base));

View file

@ -32,7 +32,6 @@ struct psb_framebuffer {
struct address_space *addr_space;
struct fb_info *fbdev;
struct gtt_range *gtt;
bool vm_map; /* True if we must undo a vm_map_ram */
};
struct psb_fbdev {

View file

@ -25,7 +25,7 @@
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
#include "gma_drm.h"
#include "psb_drv.h"
int psb_gem_init_object(struct drm_gem_object *obj)
@ -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)
{
@ -274,13 +271,13 @@ int psb_gem_create_ioctl(struct drm_device *dev, void *data,
{
struct drm_psb_gem_create *args = data;
int ret;
if (args->flags & PSB_GEM_CREATE_STOLEN) {
if (args->flags & GMA_GEM_CREATE_STOLEN) {
ret = psb_gem_create_stolen(file, dev, args->size,
&args->handle);
if (ret == 0)
return 0;
/* Fall throguh */
args->flags &= ~PSB_GEM_CREATE_STOLEN;
args->flags &= ~GMA_GEM_CREATE_STOLEN;
}
return psb_gem_create(file, dev, args->size, &args->handle);
}

View file

@ -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;
@ -131,12 +135,53 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
set_pages_array_wb(r->pages, r->npage);
}
/**
* 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 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
*
* 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";

View file

@ -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

View file

@ -20,7 +20,7 @@
*/
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
#include "gma_drm.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"

View file

@ -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"

View file

@ -25,7 +25,7 @@
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
#include "gma_drm.h"
#include "psb_drv.h"
#include "mid_bios.h"
@ -142,6 +142,12 @@ static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
memcpy(vbt, vbt_virtual, sizeof(*vbt));
iounmap(vbt_virtual); /* Free virtual address space */
/* No matching signature don't process the data */
if (memcmp(vbt->signature, "$GCT", 4)) {
vbt->size = 0;
return;
}
dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
switch (vbt->revision) {

View file

@ -521,12 +521,11 @@ int oaktrail_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 oaktrail_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);

View file

@ -22,13 +22,14 @@
#include <linux/dmi.h>
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
#include "gma_drm.h"
#include "psb_drv.h"
#include "psb_reg.h"
#include "psb_intel_reg.h"
#include <asm/mrst.h>
#include <asm/intel_scu_ipc.h>
#include "mid_bios.h"
#include "intel_bios.h"
static int oaktrail_output_init(struct drm_device *dev)
{
@ -456,9 +457,31 @@ static int oaktrail_power_up(struct drm_device *dev)
}
static int oaktrail_chip_setup(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
struct oaktrail_vbt *vbt = &dev_priv->vbt_data;
int ret;
ret = mid_chip_setup(dev);
if (ret < 0)
return ret;
if (vbt->size == 0) {
/* Now pull the BIOS data */
gma_intel_opregion_init(dev);
psb_intel_init_bios(dev);
}
return 0;
}
static void oaktrail_teardown(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
struct oaktrail_vbt *vbt = &dev_priv->vbt_data;
oaktrail_hdmi_teardown(dev);
if (vbt->size == 0)
psb_intel_destroy_bios(dev);
}
const struct psb_ops oaktrail_chip_ops = {
@ -468,7 +491,7 @@ const struct psb_ops oaktrail_chip_ops = {
.crtcs = 2,
.sgx_offset = MRST_SGX_OFFSET,
.chip_setup = mid_chip_setup,
.chip_setup = oaktrail_chip_setup,
.chip_teardown = oaktrail_teardown,
.crtc_helper = &oaktrail_helper_funcs,
.crtc_funcs = &psb_intel_crtc_funcs,

View file

@ -228,17 +228,20 @@ static struct drm_display_mode lvds_configuration_modes[] = {
/* Returns the panel fixed mode from configuration. */
static struct drm_display_mode *
oaktrail_lvds_get_configuration_mode(struct drm_device *dev)
static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev)
{
struct drm_display_mode *mode = NULL;
struct drm_psb_private *dev_priv = dev->dev_private;
struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
mode_dev->panel_fixed_mode = NULL;
/* Use the firmware provided data on Moorestown */
if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
if (!mode)
return NULL;
return;
mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
@ -270,13 +273,27 @@ oaktrail_lvds_get_configuration_mode(struct drm_device *dev)
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]);
mode_dev->panel_fixed_mode = mode;
}
drm_mode_set_name(mode);
drm_mode_set_crtcinfo(mode, 0);
/* Use the BIOS VBT mode if available */
if (mode_dev->panel_fixed_mode == NULL && mode_dev->vbt_mode)
mode_dev->panel_fixed_mode = drm_mode_duplicate(dev,
mode_dev->vbt_mode);
return mode;
/* Then try the LVDS VBT mode */
if (mode_dev->panel_fixed_mode == NULL)
if (dev_priv->lfp_lvds_vbt_mode)
mode_dev->panel_fixed_mode =
drm_mode_duplicate(dev,
dev_priv->lfp_lvds_vbt_mode);
/* Then guess */
if (mode_dev->panel_fixed_mode == NULL)
mode_dev->panel_fixed_mode
= drm_mode_duplicate(dev, &lvds_configuration_modes[2]);
drm_mode_set_name(mode_dev->panel_fixed_mode);
drm_mode_set_crtcinfo(mode_dev->panel_fixed_mode, 0);
}
/**
@ -375,7 +392,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
* If we didn't get EDID, try geting panel timing
* from configuration data
*/
mode_dev->panel_fixed_mode = oaktrail_lvds_get_configuration_mode(dev);
oaktrail_lvds_get_configuration_mode(dev, mode_dev);
if (mode_dev->panel_fixed_mode) {
mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;

View file

@ -302,7 +302,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)

View file

@ -20,7 +20,7 @@
#include <linux/backlight.h>
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
#include "gma_drm.h"
#include "psb_drv.h"
#include "psb_reg.h"
#include "psb_intel_reg.h"
@ -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;
}

View file

@ -1,207 +0,0 @@
/**************************************************************************
* Copyright (c) 2007-2011, 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.
*
**************************************************************************/
#ifndef _PSB_DRM_H_
#define _PSB_DRM_H_
#define PSB_NUM_PIPE 3
#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)
/*
* Feedback components:
*/
struct drm_psb_sizes_arg {
u32 ta_mem_size;
u32 mmu_size;
u32 pds_size;
u32 rastgeom_size;
u32 tt_size;
u32 vram_size;
};
struct drm_psb_dpst_lut_arg {
uint8_t lut[256];
int output_id;
};
#define PSB_DC_CRTC_SAVE 0x01
#define PSB_DC_CRTC_RESTORE 0x02
#define PSB_DC_OUTPUT_SAVE 0x04
#define PSB_DC_OUTPUT_RESTORE 0x08
#define PSB_DC_CRTC_MASK 0x03
#define PSB_DC_OUTPUT_MASK 0x0C
struct drm_psb_dc_state_arg {
u32 flags;
u32 obj_id;
};
struct drm_psb_mode_operation_arg {
u32 obj_id;
u16 operation;
struct drm_mode_modeinfo mode;
void *data;
};
struct drm_psb_stolen_memory_arg {
u32 base;
u32 size;
};
/*Display Register Bits*/
#define REGRWBITS_PFIT_CONTROLS (1 << 0)
#define REGRWBITS_PFIT_AUTOSCALE_RATIOS (1 << 1)
#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS (1 << 2)
#define REGRWBITS_PIPEASRC (1 << 3)
#define REGRWBITS_PIPEBSRC (1 << 4)
#define REGRWBITS_VTOTAL_A (1 << 5)
#define REGRWBITS_VTOTAL_B (1 << 6)
#define REGRWBITS_DSPACNTR (1 << 8)
#define REGRWBITS_DSPBCNTR (1 << 9)
#define REGRWBITS_DSPCCNTR (1 << 10)
/*Overlay Register Bits*/
#define OV_REGRWBITS_OVADD (1 << 0)
#define OV_REGRWBITS_OGAM_ALL (1 << 1)
#define OVC_REGRWBITS_OVADD (1 << 2)
#define OVC_REGRWBITS_OGAM_ALL (1 << 3)
struct drm_psb_register_rw_arg {
u32 b_force_hw_on;
u32 display_read_mask;
u32 display_write_mask;
struct {
u32 pfit_controls;
u32 pfit_autoscale_ratios;
u32 pfit_programmed_scale_ratios;
u32 pipeasrc;
u32 pipebsrc;
u32 vtotal_a;
u32 vtotal_b;
} display;
u32 overlay_read_mask;
u32 overlay_write_mask;
struct {
u32 OVADD;
u32 OGAMC0;
u32 OGAMC1;
u32 OGAMC2;
u32 OGAMC3;
u32 OGAMC4;
u32 OGAMC5;
u32 IEP_ENABLED;
u32 IEP_BLE_MINMAX;
u32 IEP_BSSCC_CONTROL;
u32 b_wait_vblank;
} overlay;
u32 sprite_enable_mask;
u32 sprite_disable_mask;
struct {
u32 dspa_control;
u32 dspa_key_value;
u32 dspa_key_mask;
u32 dspc_control;
u32 dspc_stride;
u32 dspc_position;
u32 dspc_linear_offset;
u32 dspc_size;
u32 dspc_surface;
} sprite;
u32 subpicture_enable_mask;
u32 subpicture_disable_mask;
};
/* Controlling the kernel modesetting buffers */
#define DRM_PSB_SIZES 0x07
#define DRM_PSB_FUSE_REG 0x08
#define DRM_PSB_DC_STATE 0x0A
#define DRM_PSB_ADB 0x0B
#define DRM_PSB_MODE_OPERATION 0x0C
#define DRM_PSB_STOLEN_MEMORY 0x0D
#define DRM_PSB_REGISTER_RW 0x0E
/*
* NOTE: Add new commands here, but increment
* the values below and increment their
* corresponding defines where they're
* defined elsewhere.
*/
#define DRM_PSB_GEM_CREATE 0x10
#define DRM_PSB_2D_OP 0x11 /* Will be merged later */
#define DRM_PSB_GEM_MMAP 0x12
#define DRM_PSB_DPST 0x1B
#define DRM_PSB_GAMMA 0x1C
#define DRM_PSB_DPST_BL 0x1D
#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F
#define PSB_MODE_OPERATION_MODE_VALID 0x01
#define PSB_MODE_OPERATION_SET_DC_BASE 0x02
struct drm_psb_get_pipe_from_crtc_id_arg {
/** ID of CRTC being requested **/
u32 crtc_id;
/** pipe of requested CRTC **/
u32 pipe;
};
/* FIXME: move this into a medfield header once we are sure it isn't needed for an
ioctl */
struct psb_drm_dpu_rect {
int x, y;
int width, height;
};
struct drm_psb_gem_create {
__u64 size;
__u32 handle;
__u32 flags;
#define PSB_GEM_CREATE_STOLEN 1 /* Stolen memory can be used */
};
struct drm_psb_gem_mmap {
__u32 handle;
__u32 pad;
/**
* Fake offset to use for subsequent mmap call
*
* This is a fixed-size type for 32/64 compatibility.
*/
__u64 offset;
};
#endif

View file

@ -21,7 +21,7 @@
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
#include "gma_drm.h"
#include "psb_drv.h"
#include "framebuffer.h"
#include "psb_reg.h"
@ -80,58 +80,36 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
* Standard IOCTLs.
*/
#define DRM_IOCTL_PSB_SIZES \
DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
struct drm_psb_sizes_arg)
#define DRM_IOCTL_PSB_FUSE_REG \
DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t)
#define DRM_IOCTL_PSB_DC_STATE \
DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \
struct drm_psb_dc_state_arg)
#define DRM_IOCTL_PSB_ADB \
DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t)
DRM_IOWR(DRM_GMA_ADB + DRM_COMMAND_BASE, uint32_t)
#define DRM_IOCTL_PSB_MODE_OPERATION \
DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \
DRM_IOWR(DRM_GMA_MODE_OPERATION + DRM_COMMAND_BASE, \
struct drm_psb_mode_operation_arg)
#define DRM_IOCTL_PSB_STOLEN_MEMORY \
DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \
DRM_IOWR(DRM_GMA_STOLEN_MEMORY + DRM_COMMAND_BASE, \
struct drm_psb_stolen_memory_arg)
#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_DPST \
DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \
uint32_t)
#define DRM_IOCTL_PSB_GAMMA \
DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \
DRM_IOWR(DRM_GMA_GAMMA + DRM_COMMAND_BASE, \
struct drm_psb_dpst_lut_arg)
#define DRM_IOCTL_PSB_DPST_BL \
DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \
DRM_IOWR(DRM_GMA_DPST_BL + DRM_COMMAND_BASE, \
uint32_t)
#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID \
DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
DRM_IOWR(DRM_GMA_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
struct drm_psb_get_pipe_from_crtc_id_arg)
#define DRM_IOCTL_PSB_GEM_CREATE \
DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \
DRM_IOWR(DRM_GMA_GEM_CREATE + DRM_COMMAND_BASE, \
struct drm_psb_gem_create)
#define DRM_IOCTL_PSB_GEM_MMAP \
DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \
DRM_IOWR(DRM_GMA_GEM_MMAP + DRM_COMMAND_BASE, \
struct drm_psb_gem_mmap)
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,
struct drm_file *file_priv);
static int psb_adb_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
static int psb_dpst_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
static int psb_gamma_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
@ -141,16 +119,11 @@ static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
[DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
static struct drm_ioctl_desc psb_ioctls[] = {
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),
PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
DRM_AUTH),
PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
DRM_AUTH),
PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_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,
@ -168,7 +141,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)
@ -214,7 +186,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);
@ -314,6 +286,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);
@ -395,7 +372,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;
@ -442,75 +419,6 @@ int psb_driver_device_is_agp(struct drm_device *dev)
return 0;
}
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;
*arg = dev_priv->sizes;
return 0;
}
static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
struct drm_file *file_priv)
{
uint32_t flags;
uint32_t obj_id;
struct drm_mode_object *obj;
struct drm_connector *connector;
struct drm_crtc *crtc;
struct drm_psb_dc_state_arg *arg = data;
/* Double check MRST case */
if (IS_MRST(dev) || IS_MFLD(dev))
return -EOPNOTSUPP;
flags = arg->flags;
obj_id = arg->obj_id;
if (flags & PSB_DC_CRTC_MASK) {
obj = drm_mode_object_find(dev, obj_id,
DRM_MODE_OBJECT_CRTC);
if (!obj) {
dev_dbg(dev->dev, "Invalid CRTC object.\n");
return -EINVAL;
}
crtc = obj_to_crtc(obj);
mutex_lock(&dev->mode_config.mutex);
if (drm_helper_crtc_in_use(crtc)) {
if (flags & PSB_DC_CRTC_SAVE)
crtc->funcs->save(crtc);
else
crtc->funcs->restore(crtc);
}
mutex_unlock(&dev->mode_config.mutex);
return 0;
} else if (flags & PSB_DC_OUTPUT_MASK) {
obj = drm_mode_object_find(dev, obj_id,
DRM_MODE_OBJECT_CONNECTOR);
if (!obj) {
dev_dbg(dev->dev, "Invalid connector id.\n");
return -EINVAL;
}
connector = obj_to_connector(obj);
if (flags & PSB_DC_OUTPUT_SAVE)
connector->funcs->save(connector);
else
connector->funcs->restore(connector);
return 0;
}
return -EINVAL;
}
static inline void get_brightness(struct backlight_device *bd)
{
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
@ -543,36 +451,6 @@ static int psb_adb_ioctl(struct drm_device *dev, void *data,
return 0;
}
/* return the current mode to the dpst module */
static int psb_dpst_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_psb_private *dev_priv = psb_priv(dev);
uint32_t *arg = data;
uint32_t x;
uint32_t y;
uint32_t reg;
if (!gma_power_begin(dev, 0))
return -EIO;
reg = PSB_RVDC32(PIPEASRC);
gma_power_end(dev);
/* horizontal is the left 16 bits */
x = reg >> 16;
/* vertical is the right 16 bits */
y = reg & 0x0000ffff;
/* the values are the image size minus one */
x++;
y++;
*arg = (x << 16) | y;
return 0;
}
static int psb_gamma_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
@ -613,37 +491,15 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
struct drm_psb_mode_operation_arg *arg;
struct drm_mode_object *obj;
struct drm_connector *connector;
struct drm_framebuffer *drm_fb;
struct psb_framebuffer *psb_fb;
struct drm_connector_helper_funcs *connector_funcs;
int ret = 0;
int resp = MODE_OK;
struct drm_psb_private *dev_priv = psb_priv(dev);
arg = (struct drm_psb_mode_operation_arg *)data;
obj_id = arg->obj_id;
op = arg->operation;
switch (op) {
case PSB_MODE_OPERATION_SET_DC_BASE:
obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
if (!obj) {
dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id);
return -EINVAL;
}
drm_fb = obj_to_fb(obj);
psb_fb = to_psb_fb(drm_fb);
if (gma_power_begin(dev, 0)) {
REG_WRITE(DSPASURF, psb_fb->gtt->offset);
REG_READ(DSPASURF);
gma_power_end(dev);
} else {
dev_priv->saveDSPASURF = psb_fb->gtt->offset;
}
return 0;
case PSB_MODE_OPERATION_MODE_VALID:
umode = &arg->mode;
@ -689,7 +545,7 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
if (connector_funcs->mode_valid) {
resp = connector_funcs->mode_valid(connector, mode);
arg->data = (void *)resp;
arg->data = resp;
}
/*do some clean up work*/
@ -719,363 +575,6 @@ static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
return 0;
}
/* FIXME: needs Medfield changes */
static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_psb_private *dev_priv = psb_priv(dev);
struct drm_psb_register_rw_arg *arg = data;
bool usage = arg->b_force_hw_on ? true : false;
if (arg->display_write_mask != 0) {
if (gma_power_begin(dev, usage)) {
if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
PSB_WVDC32(arg->display.pfit_controls,
PFIT_CONTROL);
if (arg->display_write_mask &
REGRWBITS_PFIT_AUTOSCALE_RATIOS)
PSB_WVDC32(arg->display.pfit_autoscale_ratios,
PFIT_AUTO_RATIOS);
if (arg->display_write_mask &
REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
PSB_WVDC32(
arg->display.pfit_programmed_scale_ratios,
PFIT_PGM_RATIOS);
if (arg->display_write_mask & REGRWBITS_PIPEASRC)
PSB_WVDC32(arg->display.pipeasrc,
PIPEASRC);
if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
PSB_WVDC32(arg->display.pipebsrc,
PIPEBSRC);
if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
PSB_WVDC32(arg->display.vtotal_a,
VTOTAL_A);
if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
PSB_WVDC32(arg->display.vtotal_b,
VTOTAL_B);
gma_power_end(dev);
} else {
if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
dev_priv->savePFIT_CONTROL =
arg->display.pfit_controls;
if (arg->display_write_mask &
REGRWBITS_PFIT_AUTOSCALE_RATIOS)
dev_priv->savePFIT_AUTO_RATIOS =
arg->display.pfit_autoscale_ratios;
if (arg->display_write_mask &
REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
dev_priv->savePFIT_PGM_RATIOS =
arg->display.pfit_programmed_scale_ratios;
if (arg->display_write_mask & REGRWBITS_PIPEASRC)
dev_priv->savePIPEASRC = arg->display.pipeasrc;
if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
dev_priv->savePIPEBSRC = arg->display.pipebsrc;
if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
dev_priv->saveVTOTAL_A = arg->display.vtotal_a;
if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
dev_priv->saveVTOTAL_B = arg->display.vtotal_b;
}
}
if (arg->display_read_mask != 0) {
if (gma_power_begin(dev, usage)) {
if (arg->display_read_mask &
REGRWBITS_PFIT_CONTROLS)
arg->display.pfit_controls =
PSB_RVDC32(PFIT_CONTROL);
if (arg->display_read_mask &
REGRWBITS_PFIT_AUTOSCALE_RATIOS)
arg->display.pfit_autoscale_ratios =
PSB_RVDC32(PFIT_AUTO_RATIOS);
if (arg->display_read_mask &
REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
arg->display.pfit_programmed_scale_ratios =
PSB_RVDC32(PFIT_PGM_RATIOS);
if (arg->display_read_mask & REGRWBITS_PIPEASRC)
arg->display.pipeasrc = PSB_RVDC32(PIPEASRC);
if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC);
if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A);
if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B);
gma_power_end(dev);
} else {
if (arg->display_read_mask &
REGRWBITS_PFIT_CONTROLS)
arg->display.pfit_controls =
dev_priv->savePFIT_CONTROL;
if (arg->display_read_mask &
REGRWBITS_PFIT_AUTOSCALE_RATIOS)
arg->display.pfit_autoscale_ratios =
dev_priv->savePFIT_AUTO_RATIOS;
if (arg->display_read_mask &
REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
arg->display.pfit_programmed_scale_ratios =
dev_priv->savePFIT_PGM_RATIOS;
if (arg->display_read_mask & REGRWBITS_PIPEASRC)
arg->display.pipeasrc = dev_priv->savePIPEASRC;
if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
arg->display.pipebsrc = dev_priv->savePIPEBSRC;
if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
arg->display.vtotal_a = dev_priv->saveVTOTAL_A;
if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
arg->display.vtotal_b = dev_priv->saveVTOTAL_B;
}
}
if (arg->overlay_write_mask != 0) {
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);
PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3);
PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2);
PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1);
PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0);
}
if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5);
PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4);
PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3);
PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2);
PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1);
PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0);
}
if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) {
PSB_WVDC32(arg->overlay.OVADD, OV_OVADD);
if (arg->overlay.b_wait_vblank) {
/* Wait for 20ms.*/
unsigned long vblank_timeout = jiffies
+ HZ/50;
uint32_t temp;
while (time_before_eq(jiffies,
vblank_timeout)) {
temp = PSB_RVDC32(OV_DOVASTA);
if ((temp & (0x1 << 31)) != 0)
break;
cpu_relax();
}
}
}
if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) {
PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD);
if (arg->overlay.b_wait_vblank) {
/* Wait for 20ms.*/
unsigned long vblank_timeout =
jiffies + HZ/50;
uint32_t temp;
while (time_before_eq(jiffies,
vblank_timeout)) {
temp = PSB_RVDC32(OVC_DOVCSTA);
if ((temp & (0x1 << 31)) != 0)
break;
cpu_relax();
}
}
}
gma_power_end(dev);
} else {
if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5;
dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4;
dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3;
dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2;
dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1;
dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0;
}
if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5;
dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4;
dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3;
dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2;
dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1;
dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0;
}
if (arg->overlay_write_mask & OV_REGRWBITS_OVADD)
dev_priv->saveOV_OVADD = arg->overlay.OVADD;
if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD)
dev_priv->saveOVC_OVADD = arg->overlay.OVADD;
}
}
if (arg->overlay_read_mask != 0) {
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);
arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3);
arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2);
arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1);
arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0);
}
if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5);
arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4);
arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3);
arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2);
arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1);
arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0);
}
if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
arg->overlay.OVADD = PSB_RVDC32(OV_OVADD);
if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD);
gma_power_end(dev);
} else {
if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5;
arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4;
arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3;
arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2;
arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1;
arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0;
}
if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5;
arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4;
arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3;
arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2;
arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1;
arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0;
}
if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
arg->overlay.OVADD = dev_priv->saveOV_OVADD;
if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
arg->overlay.OVADD = dev_priv->saveOVC_OVADD;
}
}
if (arg->sprite_enable_mask != 0) {
if (gma_power_begin(dev, usage)) {
PSB_WVDC32(0x1F3E, DSPARB);
PSB_WVDC32(arg->sprite.dspa_control
| PSB_RVDC32(DSPACNTR), DSPACNTR);
PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL);
PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK);
PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF);
PSB_RVDC32(DSPASURF);
PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR);
PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE);
PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS);
PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF);
PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE);
PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
PSB_RVDC32(DSPCSURF);
gma_power_end(dev);
}
}
if (arg->sprite_disable_mask != 0) {
if (gma_power_begin(dev, usage)) {
PSB_WVDC32(0x3F3E, DSPARB);
PSB_WVDC32(0x0, DSPCCNTR);
PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
PSB_RVDC32(DSPCSURF);
gma_power_end(dev);
}
}
if (arg->subpicture_enable_mask != 0) {
if (gma_power_begin(dev, usage)) {
uint32_t temp;
if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) {
temp = PSB_RVDC32(DSPACNTR);
temp &= ~DISPPLANE_PIXFORMAT_MASK;
temp &= ~DISPPLANE_BOTTOM;
temp |= DISPPLANE_32BPP;
PSB_WVDC32(temp, DSPACNTR);
temp = PSB_RVDC32(DSPABASE);
PSB_WVDC32(temp, DSPABASE);
PSB_RVDC32(DSPABASE);
temp = PSB_RVDC32(DSPASURF);
PSB_WVDC32(temp, DSPASURF);
PSB_RVDC32(DSPASURF);
}
if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) {
temp = PSB_RVDC32(DSPBCNTR);
temp &= ~DISPPLANE_PIXFORMAT_MASK;
temp &= ~DISPPLANE_BOTTOM;
temp |= DISPPLANE_32BPP;
PSB_WVDC32(temp, DSPBCNTR);
temp = PSB_RVDC32(DSPBBASE);
PSB_WVDC32(temp, DSPBBASE);
PSB_RVDC32(DSPBBASE);
temp = PSB_RVDC32(DSPBSURF);
PSB_WVDC32(temp, DSPBSURF);
PSB_RVDC32(DSPBSURF);
}
if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) {
temp = PSB_RVDC32(DSPCCNTR);
temp &= ~DISPPLANE_PIXFORMAT_MASK;
temp &= ~DISPPLANE_BOTTOM;
temp |= DISPPLANE_32BPP;
PSB_WVDC32(temp, DSPCCNTR);
temp = PSB_RVDC32(DSPCBASE);
PSB_WVDC32(temp, DSPCBASE);
PSB_RVDC32(DSPCBASE);
temp = PSB_RVDC32(DSPCSURF);
PSB_WVDC32(temp, DSPCSURF);
PSB_RVDC32(DSPCSURF);
}
gma_power_end(dev);
}
}
if (arg->subpicture_disable_mask != 0) {
if (gma_power_begin(dev, usage)) {
uint32_t temp;
if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) {
temp = PSB_RVDC32(DSPACNTR);
temp &= ~DISPPLANE_PIXFORMAT_MASK;
temp |= DISPPLANE_32BPP_NO_ALPHA;
PSB_WVDC32(temp, DSPACNTR);
temp = PSB_RVDC32(DSPABASE);
PSB_WVDC32(temp, DSPABASE);
PSB_RVDC32(DSPABASE);
temp = PSB_RVDC32(DSPASURF);
PSB_WVDC32(temp, DSPASURF);
PSB_RVDC32(DSPASURF);
}
if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) {
temp = PSB_RVDC32(DSPBCNTR);
temp &= ~DISPPLANE_PIXFORMAT_MASK;
temp |= DISPPLANE_32BPP_NO_ALPHA;
PSB_WVDC32(temp, DSPBCNTR);
temp = PSB_RVDC32(DSPBBASE);
PSB_WVDC32(temp, DSPBBASE);
PSB_RVDC32(DSPBBASE);
temp = PSB_RVDC32(DSPBSURF);
PSB_WVDC32(temp, DSPBSURF);
PSB_RVDC32(DSPBSURF);
}
if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) {
temp = PSB_RVDC32(DSPCCNTR);
temp &= ~DISPPLANE_PIXFORMAT_MASK;
temp |= DISPPLANE_32BPP_NO_ALPHA;
PSB_WVDC32(temp, DSPCCNTR);
temp = PSB_RVDC32(DSPCBASE);
PSB_WVDC32(temp, DSPCBASE);
PSB_RVDC32(DSPCBASE);
temp = PSB_RVDC32(DSPCSURF);
PSB_WVDC32(temp, DSPCSURF);
PSB_RVDC32(DSPCSURF);
}
gma_power_end(dev);
}
}
return 0;
}
static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
{
return 0;
@ -1188,9 +687,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);
}

View file

@ -25,7 +25,7 @@
#include <drm/drmP.h>
#include "drm_global.h"
#include "gem_glue.h"
#include "psb_drm.h"
#include "gma_drm.h"
#include "psb_reg.h"
#include "psb_intel_drv.h"
#include "gtt.h"
@ -42,6 +42,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)
@ -133,6 +134,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 | \
@ -258,6 +262,8 @@ struct psb_intel_opregion {
struct psb_ops;
#define PSB_NUM_PIPE 3
struct drm_psb_private {
struct drm_device *dev;
const struct psb_ops *ops;
@ -324,8 +330,6 @@ struct drm_psb_private {
* Sizes info
*/
struct drm_psb_sizes_arg sizes;
u32 fuse_reg_value;
u32 video_device_fuse;
@ -602,7 +606,7 @@ struct drm_psb_private {
void *fbdev;
/* 2D acceleration */
struct mutex mutex_2d;
spinlock_t lock_2d;
};

View file

@ -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;
} else /* Powered off, use the saved value */
ret = dev_priv->saveBLC_PWM_CTL;
return retVal;
/* 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,

View file

@ -137,22 +137,11 @@ 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;
@ -161,6 +150,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);
@ -171,27 +161,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);
@ -202,8 +188,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)
@ -219,8 +208,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;
@ -266,13 +260,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);
}
@ -464,7 +463,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);
@ -482,7 +487,13 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
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);

View file

@ -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:

91
include/drm/gma_drm.h Normal file
View file

@ -0,0 +1,91 @@
/**************************************************************************
* Copyright (c) 2007-2011, 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.
*
**************************************************************************/
#ifndef _PSB_DRM_H_
#define _PSB_DRM_H_
/*
* Manage the LUT for an output
*/
struct drm_psb_dpst_lut_arg {
uint8_t lut[256];
int output_id;
};
/*
* Validate modes
*/
struct drm_psb_mode_operation_arg {
u32 obj_id;
u16 operation;
struct drm_mode_modeinfo mode;
u64 data;
};
/*
* Query the stolen memory for smarter management of
* memory by the server
*/
struct drm_psb_stolen_memory_arg {
u32 base;
u32 size;
};
struct drm_psb_get_pipe_from_crtc_id_arg {
/** ID of CRTC being requested **/
u32 crtc_id;
/** pipe of requested CRTC **/
u32 pipe;
};
struct drm_psb_gem_create {
__u64 size;
__u32 handle;
__u32 flags;
#define GMA_GEM_CREATE_STOLEN 1 /* Stolen memory can be used */
};
struct drm_psb_gem_mmap {
__u32 handle;
__u32 pad;
/**
* Fake offset to use for subsequent mmap call
*
* This is a fixed-size type for 32/64 compatibility.
*/
__u64 offset;
};
/* Controlling the kernel modesetting buffers */
#define DRM_GMA_GEM_CREATE 0x00 /* Create a GEM object */
#define DRM_GMA_GEM_MMAP 0x01 /* Map GEM memory */
#define DRM_GMA_STOLEN_MEMORY 0x02 /* Report stolen memory */
#define DRM_GMA_2D_OP 0x03 /* Will be merged later */
#define DRM_GMA_GAMMA 0x04 /* Set gamma table */
#define DRM_GMA_ADB 0x05 /* Get backlight */
#define DRM_GMA_DPST_BL 0x06 /* Set backlight */
#define DRM_GMA_GET_PIPE_FROM_CRTC_ID 0x1 /* CRTC to physical pipe# */
#define DRM_GMA_MODE_OPERATION 0x07 /* Mode validation/DC set */
#define PSB_MODE_OPERATION_MODE_VALID 0x01
#endif