Skip to content

Commit

Permalink
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/daeinki/drm-exynos into drm-next

The summary:
. Add display mode check operaion to mixer driver
  - Mixer IP also can put certain restrictions on the proposed
    display modes and these restrictions need to be considered
    during mode negotiation, which happens immediately after
    edid parsing.
. Set correct mode for range of resolutions
  - With this patch, the mixer driver could find the correct mode
    for the range of resolutions upto 1080 vertical lines.
. Support extra resolution for hdmi
  - This patch programs the core and timing generator registers
    using the timing data provided in drm_display_mode without
    hard-coded configurations. So this patch adds additional PHY
    configs to allow us to support more permissible resolutions
    and refresh rates.
. Add device tree support for g2d
  - This patch adds just the compatible string for exynos5250 SoC
    so that with device tree enabling, this driver can be probed.
. And bug fixes and code cleanups.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: Add device tree based discovery support for G2D
  drm/exynos: hdmi: support extra resolutions using drm_display_mode timings
  drm/exynos: mixer: set correct mode for range of resolutions
  drm/exynos: implement display-mode-check callback in mixer driver
  drm/exynos: add display-mode-check operation to exynos_mixer_ops struct
  drm/exynos: release resources properly when fb creation is failed.
  drm/exynos: fix wrong pointer access at vm close.
  drm/exynos: Add missing braces around sizeof
  drm/exynos: consider exception case to fb handle creation
  drm/exynos: fix iommu address allocation order
  • Loading branch information
Dave Airlie committed Feb 22, 2013
2 parents 907a773 + 95fc633 commit c976cb3
Show file tree
Hide file tree
Showing 8 changed files with 490 additions and 698 deletions.
55 changes: 31 additions & 24 deletions drivers/gpu/drm/exynos/exynos_drm_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,

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

/* This fb should have only one gem object. */
if (WARN_ON(exynos_fb->buf_cnt != 1))
return -EINVAL;

return drm_gem_handle_create(file_priv,
&exynos_fb->exynos_gem_obj[0]->base, handle);
}
Expand Down Expand Up @@ -217,67 +221,70 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct exynos_drm_gem_obj *exynos_gem_obj;
struct exynos_drm_fb *exynos_fb;
int i, ret;

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

obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
if (!obj) {
DRM_ERROR("failed to lookup gem object\n");
return ERR_PTR(-ENOENT);
}

exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
if (!exynos_fb) {
DRM_ERROR("failed to allocate exynos drm framebuffer\n");
return ERR_PTR(-ENOMEM);
}

obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
if (!obj) {
DRM_ERROR("failed to lookup gem object\n");
ret = -ENOENT;
goto err_free;
}

drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);
exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);
exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd);

DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt);

for (i = 1; i < exynos_fb->buf_cnt; i++) {
struct exynos_drm_gem_obj *exynos_gem_obj;
int ret;

obj = drm_gem_object_lookup(dev, file_priv,
mode_cmd->handles[i]);
if (!obj) {
DRM_ERROR("failed to lookup gem object\n");
kfree(exynos_fb);
return ERR_PTR(-ENOENT);
ret = -ENOENT;
exynos_fb->buf_cnt = i;
goto err_unreference;
}

exynos_gem_obj = to_exynos_gem_obj(obj);
exynos_fb->exynos_gem_obj[i] = exynos_gem_obj;

ret = check_fb_gem_memory_type(dev, exynos_gem_obj);
if (ret < 0) {
DRM_ERROR("cannot use this gem memory type for fb.\n");
kfree(exynos_fb);
return ERR_PTR(ret);
goto err_unreference;
}

exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);
}

ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
if (ret) {
for (i = 0; i < exynos_fb->buf_cnt; i++) {
struct exynos_drm_gem_obj *gem_obj;

gem_obj = exynos_fb->exynos_gem_obj[i];
drm_gem_object_unreference_unlocked(&gem_obj->base);
}

kfree(exynos_fb);
return ERR_PTR(ret);
DRM_ERROR("failed to init framebuffer.\n");
goto err_unreference;
}

return &exynos_fb->fb;

err_unreference:
for (i = 0; i < exynos_fb->buf_cnt; i++) {
struct drm_gem_object *obj;

obj = &exynos_fb->exynos_gem_obj[i]->base;
if (obj)
drm_gem_object_unreference_unlocked(obj);
}
err_free:
kfree(exynos_fb);
return ERR_PTR(ret);
}

struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
Expand Down
12 changes: 11 additions & 1 deletion drivers/gpu/drm/exynos/exynos_drm_g2d.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/workqueue.h>
#include <linux/dma-mapping.h>
#include <linux/dma-attrs.h>
#include <linux/of.h>

#include <drm/drmP.h>
#include <drm/exynos_drm.h>
Expand Down Expand Up @@ -429,7 +430,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,

g2d_userptr->pages = pages;

sgt = kzalloc(sizeof *sgt, GFP_KERNEL);
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt) {
DRM_ERROR("failed to allocate sg table.\n");
ret = -ENOMEM;
Expand Down Expand Up @@ -1240,12 +1241,21 @@ static int g2d_resume(struct device *dev)

static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);

#ifdef CONFIG_OF
static const struct of_device_id exynos_g2d_match[] = {
{ .compatible = "samsung,exynos5250-g2d" },
{},
};
MODULE_DEVICE_TABLE(of, exynos_g2d_match);
#endif

struct platform_driver g2d_driver = {
.probe = g2d_probe,
.remove = g2d_remove,
.driver = {
.name = "s5p-g2d",
.owner = THIS_MODULE,
.pm = &g2d_pm_ops,
.of_match_table = of_match_ptr(exynos_g2d_match),
},
};
33 changes: 21 additions & 12 deletions drivers/gpu/drm/exynos/exynos_drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,17 +329,11 @@ static struct drm_file *exynos_drm_find_drm_file(struct drm_device *drm_dev,
{
struct drm_file *file_priv;

mutex_lock(&drm_dev->struct_mutex);

/* find current process's drm_file from filelist. */
list_for_each_entry(file_priv, &drm_dev->filelist, lhead) {
if (file_priv->filp == filp) {
mutex_unlock(&drm_dev->struct_mutex);
list_for_each_entry(file_priv, &drm_dev->filelist, lhead)
if (file_priv->filp == filp)
return file_priv;
}
}

mutex_unlock(&drm_dev->struct_mutex);
WARN_ON(1);

return ERR_PTR(-EFAULT);
Expand Down Expand Up @@ -400,9 +394,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
*/
drm_gem_object_reference(obj);

mutex_lock(&drm_dev->struct_mutex);
drm_vm_open_locked(drm_dev, vma);
mutex_unlock(&drm_dev->struct_mutex);

return 0;
}
Expand Down Expand Up @@ -431,6 +423,16 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}

/*
* We have to use gem object and its fops for specific mmaper,
* but vm_mmap() can deliver only filp. So we have to change
* filp->f_op and filp->private_data temporarily, then restore
* again. So it is important to keep lock until restoration the
* settings to prevent others from misuse of filp->f_op or
* filp->private_data.
*/
mutex_lock(&dev->struct_mutex);

/*
* Set specific mmper's fops. And it will be restored by
* exynos_drm_gem_mmap_buffer to dev->driver->fops.
Expand All @@ -448,13 +450,20 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
addr = vm_mmap(file_priv->filp, 0, args->size,
PROT_READ | PROT_WRITE, MAP_SHARED, 0);

drm_gem_object_unreference_unlocked(obj);
drm_gem_object_unreference(obj);

if (IS_ERR((void *)addr)) {
file_priv->filp->private_data = file_priv;
/* check filp->f_op, filp->private_data are restored */
if (file_priv->filp->f_op == &exynos_drm_gem_fops) {
file_priv->filp->f_op = fops_get(dev->driver->fops);
file_priv->filp->private_data = file_priv;
}
mutex_unlock(&dev->struct_mutex);
return PTR_ERR((void *)addr);
}

mutex_unlock(&dev->struct_mutex);

args->mapped = addr;

DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped);
Expand Down
12 changes: 12 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,21 @@ static struct edid *drm_hdmi_get_edid(struct device *dev,
static int drm_hdmi_check_timing(struct device *dev, void *timing)
{
struct drm_hdmi_context *ctx = to_context(dev);
int ret = 0;

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

/*
* Both, mixer and hdmi should be able to handle the requested mode.
* If any of the two fails, return mode as BAD.
*/

if (mixer_ops && mixer_ops->check_timing)
ret = mixer_ops->check_timing(ctx->mixer_ctx->ctx, timing);

if (ret)
return ret;

if (hdmi_ops && hdmi_ops->check_timing)
return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);

Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/exynos/exynos_drm_hdmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct exynos_hdmi_ops {
bool (*is_connected)(void *ctx);
struct edid *(*get_edid)(void *ctx,
struct drm_connector *connector);
int (*check_timing)(void *ctx, void *timing);
int (*check_timing)(void *ctx, struct fb_videomode *timing);
int (*power_on)(void *ctx, int mode);

/* manager */
Expand All @@ -58,6 +58,9 @@ struct exynos_mixer_ops {
void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
void (*win_commit)(void *ctx, int zpos);
void (*win_disable)(void *ctx, int zpos);

/* display */
int (*check_timing)(void *ctx, struct fb_videomode *timing);
};

void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/exynos_drm_iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#define EXYNOS_DEV_ADDR_START 0x20000000
#define EXYNOS_DEV_ADDR_SIZE 0x40000000
#define EXYNOS_DEV_ADDR_ORDER 0x4
#define EXYNOS_DEV_ADDR_ORDER 0x0

#ifdef CONFIG_DRM_EXYNOS_IOMMU

Expand Down
Loading

0 comments on commit c976cb3

Please sign in to comment.