Skip to content

Commit

Permalink
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Browse files Browse the repository at this point in the history
Pull drm fixes from Dave Airlie:
 "Mostly exynos and intel.

  Intel has 3 regression fixers (more info in intel merge commit), along
  with some other make hw work fixes, exynos has some cleanups and an
  ioctl fix.

  A couple of radeon fixes, couple of build fixes, and a savage
  userspace interface possible overflow fix."

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (23 commits)
  drm/exynos: fixed exynos broken ioctl
  drm/i915: clear fencing tracking state when retiring requests
  drm/exynos: fix to pointer manager member of struct exynos_drm_subdrv
  drm/exynos: fix struct for operation callback functions to driver name
  drm/exynos: use define instead of default_win member in struct mixer_context
  drm/exynos: rename s/HDMI_OVERLAY_NUMBER/MIXER_WIN_NR
  drm/exynos: remove unused codes in hdmi and mixer
  drm/exynos: remove unnecessary type conversion of hdmi and mixer
  drm/i915: make rc6 module parameter read-only
  drm/i915: implement ColorBlt w/a
  drm/i915/ringbuffer: Exclude last 2 cachlines of ring on 845g
  Revert "drm/i915: reenable gmbus on gen3+ again"
  drm/radeon: only add the mm i2c bus if the hw_i2c module param is set
  vgaarb.h: fix build warnings
  drm/i915: properly compute dp dithering for user-created modes
  drm/radeon/kms: fix DVO setup on some r4xx chips
  drm/savage: fix integer overflows in savage_bci_cmdbuf()
  drm/radeon: replace udelay with mdelay for long timeouts
  drm/i915: Finish any pending operations on the framebuffer before disabling
  drm/i915: Removed IVB forced enable of sprite dest key.
  ...
  • Loading branch information
Linus Torvalds committed Apr 12, 2012
2 parents e42bd6e + 173fa4e commit 778c2de
Show file tree
Hide file tree
Showing 31 changed files with 325 additions and 254 deletions.
47 changes: 14 additions & 33 deletions drivers/gpu/drm/exynos/exynos_drm_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@
static int lowlevel_buffer_allocate(struct drm_device *dev,
unsigned int flags, struct exynos_drm_gem_buf *buf)
{
dma_addr_t start_addr, end_addr;
dma_addr_t start_addr;
unsigned int npages, page_size, i = 0;
struct scatterlist *sgl;
int ret = 0;

DRM_DEBUG_KMS("%s\n", __FILE__);

if (flags & EXYNOS_BO_NONCONTIG) {
if (IS_NONCONTIG_BUFFER(flags)) {
DRM_DEBUG_KMS("not support allocation type.\n");
return -EINVAL;
}
Expand All @@ -52,13 +52,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
}

if (buf->size >= SZ_1M) {
npages = (buf->size >> SECTION_SHIFT) + 1;
npages = buf->size >> SECTION_SHIFT;
page_size = SECTION_SIZE;
} else if (buf->size >= SZ_64K) {
npages = (buf->size >> 16) + 1;
npages = buf->size >> 16;
page_size = SZ_64K;
} else {
npages = (buf->size >> PAGE_SHIFT) + 1;
npages = buf->size >> PAGE_SHIFT;
page_size = PAGE_SIZE;
}

Expand All @@ -76,26 +76,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
return -ENOMEM;
}

buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size,
&buf->dma_addr, GFP_KERNEL);
if (!buf->kvaddr) {
DRM_ERROR("failed to allocate buffer.\n");
ret = -ENOMEM;
goto err1;
}

start_addr = buf->dma_addr;
end_addr = buf->dma_addr + buf->size;

buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
if (!buf->pages) {
DRM_ERROR("failed to allocate pages.\n");
ret = -ENOMEM;
goto err2;
}

start_addr = buf->dma_addr;
end_addr = buf->dma_addr + buf->size;
buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size,
&buf->dma_addr, GFP_KERNEL);
if (!buf->kvaddr) {
DRM_ERROR("failed to allocate buffer.\n");
ret = -ENOMEM;
goto err1;
}

buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
if (!buf->pages) {
Expand All @@ -105,23 +92,17 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
}

sgl = buf->sgt->sgl;
start_addr = buf->dma_addr;

while (i < npages) {
buf->pages[i] = phys_to_page(start_addr);
sg_set_page(sgl, buf->pages[i], page_size, 0);
sg_dma_address(sgl) = start_addr;
start_addr += page_size;
if (end_addr - start_addr < page_size)
break;
sgl = sg_next(sgl);
i++;
}

buf->pages[i] = phys_to_page(start_addr);

sgl = sg_next(sgl);
sg_set_page(sgl, buf->pages[i+1], end_addr - start_addr, 0);

DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
(unsigned long)buf->kvaddr,
(unsigned long)buf->dma_addr,
Expand Down Expand Up @@ -150,7 +131,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
* non-continuous memory would be released by exynos
* gem framework.
*/
if (flags & EXYNOS_BO_NONCONTIG) {
if (IS_NONCONTIG_BUFFER(flags)) {
DRM_DEBUG_KMS("not support allocation type.\n");
return;
}
Expand Down
14 changes: 8 additions & 6 deletions drivers/gpu/drm/exynos/exynos_drm_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,18 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,
*
* P.S. note that this driver is considered for modularization.
*/
ret = subdrv->probe(dev, subdrv->manager.dev);
ret = subdrv->probe(dev, subdrv->dev);
if (ret)
return ret;
}

if (subdrv->is_local)
if (!subdrv->manager)
return 0;

subdrv->manager->dev = subdrv->dev;

/* create and initialize a encoder for this sub driver. */
encoder = exynos_drm_encoder_create(dev, &subdrv->manager,
encoder = exynos_drm_encoder_create(dev, subdrv->manager,
(1 << MAX_CRTC) - 1);
if (!encoder) {
DRM_ERROR("failed to create encoder\n");
Expand Down Expand Up @@ -186,7 +188,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)

list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
if (subdrv->open) {
ret = subdrv->open(dev, subdrv->manager.dev, file);
ret = subdrv->open(dev, subdrv->dev, file);
if (ret)
goto err;
}
Expand All @@ -197,7 +199,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
err:
list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
if (subdrv->close)
subdrv->close(dev, subdrv->manager.dev, file);
subdrv->close(dev, subdrv->dev, file);
}
return ret;
}
Expand All @@ -209,7 +211,7 @@ void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)

list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
if (subdrv->close)
subdrv->close(dev, subdrv->manager.dev, file);
subdrv->close(dev, subdrv->dev, file);
}
}
EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
10 changes: 5 additions & 5 deletions drivers/gpu/drm/exynos/exynos_drm_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,24 +225,25 @@ struct exynos_drm_private {
* Exynos drm sub driver structure.
*
* @list: sub driver has its own list object to register to exynos drm driver.
* @dev: pointer to device object for subdrv device driver.
* @drm_dev: pointer to drm_device and this pointer would be set
* when sub driver calls exynos_drm_subdrv_register().
* @is_local: appear encoder and connector disrelated device.
* @manager: subdrv has its own manager to control a hardware appropriately
* and we can access a hardware drawing on this manager.
* @probe: this callback would be called by exynos drm driver after
* subdrv is registered to it.
* @remove: this callback is used to release resources created
* by probe callback.
* @open: this would be called with drm device file open.
* @close: this would be called with drm device file close.
* @manager: subdrv has its own manager to control a hardware appropriately
* and we can access a hardware drawing on this manager.
* @encoder: encoder object owned by this sub driver.
* @connector: connector object owned by this sub driver.
*/
struct exynos_drm_subdrv {
struct list_head list;
struct device *dev;
struct drm_device *drm_dev;
bool is_local;
struct exynos_drm_manager *manager;

int (*probe)(struct drm_device *drm_dev, struct device *dev);
void (*remove)(struct drm_device *dev);
Expand All @@ -251,7 +252,6 @@ struct exynos_drm_subdrv {
void (*close)(struct drm_device *drm_dev, struct device *dev,
struct drm_file *file);

struct exynos_drm_manager manager;
struct drm_encoder *encoder;
struct drm_connector *connector;
};
Expand Down
20 changes: 12 additions & 8 deletions drivers/gpu/drm/exynos/exynos_drm_fimd.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
static void fimd_apply(struct device *subdrv_dev)
{
struct fimd_context *ctx = get_fimd_context(subdrv_dev);
struct exynos_drm_manager *mgr = &ctx->subdrv.manager;
struct exynos_drm_manager *mgr = ctx->subdrv.manager;
struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
struct fimd_win_data *win_data;
Expand Down Expand Up @@ -577,6 +577,13 @@ static struct exynos_drm_overlay_ops fimd_overlay_ops = {
.disable = fimd_win_disable,
};

static struct exynos_drm_manager fimd_manager = {
.pipe = -1,
.ops = &fimd_manager_ops,
.overlay_ops = &fimd_overlay_ops,
.display_ops = &fimd_display_ops,
};

static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
{
struct exynos_drm_private *dev_priv = drm_dev->dev_private;
Expand Down Expand Up @@ -628,7 +635,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
struct fimd_context *ctx = (struct fimd_context *)dev_id;
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
struct drm_device *drm_dev = subdrv->drm_dev;
struct exynos_drm_manager *manager = &subdrv->manager;
struct exynos_drm_manager *manager = subdrv->manager;
u32 val;

val = readl(ctx->regs + VIDINTCON1);
Expand Down Expand Up @@ -744,7 +751,7 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
static int fimd_power_on(struct fimd_context *ctx, bool enable)
{
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
struct device *dev = subdrv->manager.dev;
struct device *dev = subdrv->dev;

DRM_DEBUG_KMS("%s\n", __FILE__);

Expand Down Expand Up @@ -867,13 +874,10 @@ static int __devinit fimd_probe(struct platform_device *pdev)

subdrv = &ctx->subdrv;

subdrv->dev = dev;
subdrv->manager = &fimd_manager;
subdrv->probe = fimd_subdrv_probe;
subdrv->remove = fimd_subdrv_remove;
subdrv->manager.pipe = -1;
subdrv->manager.ops = &fimd_manager_ops;
subdrv->manager.overlay_ops = &fimd_overlay_ops;
subdrv->manager.display_ops = &fimd_display_ops;
subdrv->manager.dev = dev;

mutex_init(&ctx->lock);

Expand Down
45 changes: 36 additions & 9 deletions drivers/gpu/drm/exynos/exynos_drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,28 @@ static unsigned int convert_to_vm_err_msg(int msg)
return out_msg;
}

static unsigned int mask_gem_flags(unsigned int flags)
static int check_gem_flags(unsigned int flags)
{
return flags &= EXYNOS_BO_NONCONTIG;
if (flags & ~(EXYNOS_BO_MASK)) {
DRM_ERROR("invalid flags.\n");
return -EINVAL;
}

return 0;
}

static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
{
if (!IS_NONCONTIG_BUFFER(flags)) {
if (size >= SZ_1M)
return roundup(size, SECTION_SIZE);
else if (size >= SZ_64K)
return roundup(size, SZ_64K);
else
goto out;
}
out:
return roundup(size, PAGE_SIZE);
}

static struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
Expand Down Expand Up @@ -319,10 +338,17 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
struct exynos_drm_gem_buf *buf;
int ret;

size = roundup(size, PAGE_SIZE);
DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size);
if (!size) {
DRM_ERROR("invalid size.\n");
return ERR_PTR(-EINVAL);
}

flags = mask_gem_flags(flags);
size = roundup_gem_size(size, flags);
DRM_DEBUG_KMS("%s\n", __FILE__);

ret = check_gem_flags(flags);
if (ret)
return ERR_PTR(ret);

buf = exynos_drm_init_buf(dev, size);
if (!buf)
Expand All @@ -331,7 +357,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
exynos_gem_obj = exynos_drm_gem_init(dev, size);
if (!exynos_gem_obj) {
ret = -ENOMEM;
goto err;
goto err_fini_buf;
}

exynos_gem_obj->buffer = buf;
Expand All @@ -347,18 +373,19 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);
if (ret < 0) {
drm_gem_object_release(&exynos_gem_obj->base);
goto err;
goto err_fini_buf;
}
} else {
ret = exynos_drm_alloc_buf(dev, buf, flags);
if (ret < 0) {
drm_gem_object_release(&exynos_gem_obj->base);
goto err;
goto err_fini_buf;
}
}

return exynos_gem_obj;
err:

err_fini_buf:
exynos_drm_fini_buf(dev, buf);
return ERR_PTR(ret);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_gem.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#define to_exynos_gem_obj(x) container_of(x,\
struct exynos_drm_gem_obj, base)

#define IS_NONCONTIG_BUFFER(f) (f & EXYNOS_BO_NONCONTIG)

/*
* exynos drm gem buffer structure.
*
Expand Down
Loading

0 comments on commit 778c2de

Please sign in to comment.