Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 9 Jan 2013 00:08:10 +0000 (16:08 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 9 Jan 2013 00:08:10 +0000 (16:08 -0800)
Pull drm update from Dave Airlie:
 "Exynos and Radeon mostly, with a dma-buf and ttm fix thrown in.

  It's a bit big but its mostly exynos license fix ups and I'd rather
  not hold those up since its legally stuff.

  Radeon has a couple of fixes from dma engine work, TTM is just a
  locking fix, and dma-buf fix has been hanging around and I finally got
  a chance to review it."

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (30 commits)
  drm/ttm: fix fence locking in ttm_buffer_object_transfer
  drm/prime: drop reference on imported dma-buf come from gem
  drm/radeon: add quirk for d3 delay during switcheroo poweron for apple macbooks
  drm/exynos: move finish page flip to a common place
  drm/exynos: fimd: modify condition in fimd resume
  drm/radeon: fix DMA CS parser for r6xx linear copy packet
  drm/radeon: split r6xx and r7xx copy_dma functions
  drm/exynos: Use devm_clk_get in exynos_drm_gsc.c
  drm/exynos: Remove redundant NULL check in exynos_drm_gsc.c
  drm/exynos: Remove explicit freeing using devm_* APIs in exynos_drm_gsc.c
  drm/exynos: Use devm_clk_get in exynos_drm_rotator.c
  drm/exynos: Remove redundant NULL check in exynos_drm_rotator.c
  drm/exynos: Remove unnecessary devm_* freeing APIs in exynos_drm_rotator.c
  drm/exynos: Use devm_clk_get in exynos_drm_fimc.c
  drm/exynos: Remove redundant NULL check
  drm/exynos: Remove explicit freeing using devm_* APIs in exynos_drm_fimc.c
  drm/exynos: Use devm_kzalloc in exynos_drm_ipp.c
  drm/exynos: fix gem buffer allocation type checking
  drm/exynos: remove needless parenthesis.
  drm/exynos: fix incorrect interrupt induced by m2m operation.
  ...

1  2 
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_drm_ipp.c
drivers/gpu/drm/exynos/exynos_drm_rotator.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_mixer.c

index 1713e53d4751b7b9a6c7e168adafecc8dc126bc2,56e9a412c5c56a5bed26a60802bcafd0c8274cf6..3da5c2d214d88777b2dd550295c8e939673289dd
@@@ -5,24 -5,10 +5,10 @@@
   *    Joonyoung Shim <jy0922.shim@samsung.com>
   *    Seung-Woo Kim <sw0312.kim@samsung.com>
   *
-  * Permission is hereby granted, free of charge, to any person obtaining a
-  * copy of this software and associated documentation files (the "Software"),
-  * to deal in the Software without restriction, including without limitation
-  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-  * and/or sell copies of the Software, and to permit persons to whom the
-  * Software is furnished to do so, subject to the following conditions:
-  *
-  * The above copyright notice and this permission notice (including the next
-  * paragraph) shall be included in all copies or substantial portions of the
-  * Software.
-  *
-  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-  * OTHER DEALINGS IN THE SOFTWARE.
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+  * Free Software Foundation;  either version 2 of the  License, or (at your
+  * option) any later version.
   */
  
  #include <drm/drmP.h>
@@@ -325,7 -311,7 +311,7 @@@ static int exynos_drm_platform_remove(s
  
  static struct platform_driver exynos_drm_platform_driver = {
        .probe          = exynos_drm_platform_probe,
 -      .remove         = __devexit_p(exynos_drm_platform_remove),
 +      .remove         = exynos_drm_platform_remove,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "exynos-drm",
index d9963171fd0b92d793bd9e044372b6d815e5363a,88a78416f0c96ce435078d4669a868f6c41a76a2..67a83e69544bb4e285088be9227c3ed2176ebcb6
@@@ -25,7 -25,7 +25,7 @@@
  #include "exynos_drm_fimc.h"
  
  /*
-  * FIMC is stand for Fully Interactive Mobile Camera and
+  * FIMC stands for Fully Interactive Mobile Camera and
   * supports image scaler/rotator and input/output DMA operations.
   * input DMA reads image data from the memory.
   * output DMA writes image data to memory.
@@@ -163,19 -163,29 +163,29 @@@ struct fimc_context 
        bool    suspended;
  };
  
- static void fimc_sw_reset(struct fimc_context *ctx, bool pattern)
+ static void fimc_sw_reset(struct fimc_context *ctx)
  {
        u32 cfg;
  
-       DRM_DEBUG_KMS("%s:pattern[%d]\n", __func__, pattern);
+       DRM_DEBUG_KMS("%s\n", __func__);
+       /* stop dma operation */
+       cfg = fimc_read(EXYNOS_CISTATUS);
+       if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg)) {
+               cfg = fimc_read(EXYNOS_MSCTRL);
+               cfg &= ~EXYNOS_MSCTRL_ENVID;
+               fimc_write(cfg, EXYNOS_MSCTRL);
+       }
  
        cfg = fimc_read(EXYNOS_CISRCFMT);
        cfg |= EXYNOS_CISRCFMT_ITU601_8BIT;
-       if (pattern)
-               cfg |= EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR;
        fimc_write(cfg, EXYNOS_CISRCFMT);
  
+       /* disable image capture */
+       cfg = fimc_read(EXYNOS_CIIMGCPT);
+       cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
+       fimc_write(cfg, EXYNOS_CIIMGCPT);
        /* s/w reset */
        cfg = fimc_read(EXYNOS_CIGCTRL);
        cfg |= (EXYNOS_CIGCTRL_SWRST);
@@@ -695,7 -705,7 +705,7 @@@ static int fimc_src_set_addr(struct dev
  {
        struct fimc_context *ctx = get_fimc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
        struct drm_exynos_ipp_config *config;
  
        }
  
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EINVAL;
-       }
  
        DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
                property->prop_id, buf_id, buf_type);
@@@ -1206,7 -1212,7 +1212,7 @@@ static int fimc_dst_set_buf_seq(struct 
        }
  
        /* sequence id */
-       cfg &= (~mask);
+       cfg &= ~mask;
        cfg |= (enable << buf_id);
        fimc_write(cfg, EXYNOS_CIFCNTSEQ);
  
@@@ -1231,7 -1237,7 +1237,7 @@@ static int fimc_dst_set_addr(struct dev
  {
        struct fimc_context *ctx = get_fimc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
        struct drm_exynos_ipp_config *config;
  
        }
  
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EINVAL;
-       }
  
        DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
                property->prop_id, buf_id, buf_type);
@@@ -1317,7 -1319,7 +1319,7 @@@ static irqreturn_t fimc_irq_handler(in
  {
        struct fimc_context *ctx = dev_id;
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_event_work *event_work =
                c_node->event_work;
        int buf_id;
@@@ -1395,6 -1397,7 +1397,7 @@@ static inline bool fimc_check_drm_flip(
        case EXYNOS_DRM_FLIP_NONE:
        case EXYNOS_DRM_FLIP_VERTICAL:
        case EXYNOS_DRM_FLIP_HORIZONTAL:
+       case EXYNOS_DRM_FLIP_BOTH:
                return true;
        default:
                DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
@@@ -1543,7 -1546,7 +1546,7 @@@ static int fimc_ippdrv_reset(struct dev
        DRM_DEBUG_KMS("%s\n", __func__);
  
        /* reset h/w block */
-       fimc_sw_reset(ctx, false);
+       fimc_sw_reset(ctx);
  
        /* reset scaler capability */
        memset(&ctx->sc, 0x0, sizeof(ctx->sc));
@@@ -1557,7 -1560,7 +1560,7 @@@ static int fimc_ippdrv_start(struct dev
  {
        struct fimc_context *ctx = get_fimc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
        struct drm_exynos_ipp_config *config;
        struct drm_exynos_pos   img_pos[EXYNOS_DRM_OPS_MAX];
        }
  
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EINVAL;
-       }
  
        fimc_handle_irq(ctx, true, false, true);
  
@@@ -1714,7 -1713,7 +1713,7 @@@ static void fimc_ippdrv_stop(struct dev
        fimc_write(cfg, EXYNOS_CIGCTRL);
  }
  
 -static int __devinit fimc_probe(struct platform_device *pdev)
 +static int fimc_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct fimc_context *ctx;
                platform_get_device_id(pdev)->driver_data;
  
        /* clock control */
-       ctx->sclk_fimc_clk = clk_get(dev, "sclk_fimc");
+       ctx->sclk_fimc_clk = devm_clk_get(dev, "sclk_fimc");
        if (IS_ERR(ctx->sclk_fimc_clk)) {
                dev_err(dev, "failed to get src fimc clock.\n");
-               ret = PTR_ERR(ctx->sclk_fimc_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->sclk_fimc_clk);
        }
        clk_enable(ctx->sclk_fimc_clk);
  
-       ctx->fimc_clk = clk_get(dev, "fimc");
+       ctx->fimc_clk = devm_clk_get(dev, "fimc");
        if (IS_ERR(ctx->fimc_clk)) {
                dev_err(dev, "failed to get fimc clock.\n");
-               ret = PTR_ERR(ctx->fimc_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->fimc_clk);
        }
  
-       ctx->wb_clk = clk_get(dev, "pxl_async0");
+       ctx->wb_clk = devm_clk_get(dev, "pxl_async0");
        if (IS_ERR(ctx->wb_clk)) {
                dev_err(dev, "failed to get writeback a clock.\n");
-               ret = PTR_ERR(ctx->wb_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               clk_put(ctx->fimc_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->wb_clk);
        }
  
-       ctx->wb_b_clk = clk_get(dev, "pxl_async1");
+       ctx->wb_b_clk = devm_clk_get(dev, "pxl_async1");
        if (IS_ERR(ctx->wb_b_clk)) {
                dev_err(dev, "failed to get writeback b clock.\n");
-               ret = PTR_ERR(ctx->wb_b_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               clk_put(ctx->fimc_clk);
-               clk_put(ctx->wb_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->wb_b_clk);
        }
  
-       parent_clk = clk_get(dev, ddata->parent_clk);
+       parent_clk = devm_clk_get(dev, ddata->parent_clk);
  
        if (IS_ERR(parent_clk)) {
                dev_err(dev, "failed to get parent clock.\n");
-               ret = PTR_ERR(parent_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               clk_put(ctx->fimc_clk);
-               clk_put(ctx->wb_clk);
-               clk_put(ctx->wb_b_clk);
-               goto err_ctx;
+               return PTR_ERR(parent_clk);
        }
  
        if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
                dev_err(dev, "failed to set parent.\n");
-               ret = -EINVAL;
-               clk_put(parent_clk);
                clk_disable(ctx->sclk_fimc_clk);
-               clk_put(ctx->sclk_fimc_clk);
-               clk_put(ctx->fimc_clk);
-               clk_put(ctx->wb_clk);
-               clk_put(ctx->wb_b_clk);
-               goto err_ctx;
+               return -EINVAL;
        }
  
-       clk_put(parent_clk);
+       devm_clk_put(dev, parent_clk);
        clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
  
        /* resource memory */
        ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!ctx->regs_res) {
-               dev_err(dev, "failed to find registers.\n");
-               ret = -ENOENT;
-               goto err_clk;
-       }
        ctx->regs = devm_request_and_ioremap(dev, ctx->regs_res);
        if (!ctx->regs) {
                dev_err(dev, "failed to map registers.\n");
-               ret = -ENXIO;
-               goto err_clk;
+               return -ENXIO;
        }
  
        /* resource irq */
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res) {
                dev_err(dev, "failed to request irq resource.\n");
-               ret = -ENOENT;
-               goto err_get_regs;
+               return -ENOENT;
        }
  
        ctx->irq = res->start;
                IRQF_ONESHOT, "drm_fimc", ctx);
        if (ret < 0) {
                dev_err(dev, "failed to request irq.\n");
-               goto err_get_regs;
+               return ret;
        }
  
        /* context initailization */
@@@ -1879,19 -1849,11 +1849,11 @@@ err_ippdrv_register
        pm_runtime_disable(dev);
  err_get_irq:
        free_irq(ctx->irq, ctx);
- err_get_regs:
-       devm_iounmap(dev, ctx->regs);
- err_clk:
-       clk_put(ctx->sclk_fimc_clk);
-       clk_put(ctx->fimc_clk);
-       clk_put(ctx->wb_clk);
-       clk_put(ctx->wb_b_clk);
- err_ctx:
-       devm_kfree(dev, ctx);
        return ret;
  }
  
 -static int __devexit fimc_remove(struct platform_device *pdev)
 +static int fimc_remove(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct fimc_context *ctx = get_fimc_context(dev);
        pm_runtime_disable(dev);
  
        free_irq(ctx->irq, ctx);
-       devm_iounmap(dev, ctx->regs);
-       clk_put(ctx->sclk_fimc_clk);
-       clk_put(ctx->fimc_clk);
-       clk_put(ctx->wb_clk);
-       clk_put(ctx->wb_b_clk);
-       devm_kfree(dev, ctx);
  
        return 0;
  }
@@@ -1990,7 -1944,7 +1944,7 @@@ static const struct dev_pm_ops fimc_pm_
  
  struct platform_driver fimc_driver = {
        .probe          = fimc_probe,
 -      .remove         = __devexit_p(fimc_remove),
 +      .remove         = fimc_remove,
        .id_table       = fimc_driver_ids,
        .driver         = {
                .name   = "exynos-drm-fimc",
index 3ac911894dc7203c4aeda628d2dfa2969cefd64c,102f4168f4ab9a1744d5a03e0b0e3bade24d9724..9537761931ee297fb33c8cf8888a2842b1e4fc1a
@@@ -663,34 -663,6 +663,6 @@@ static struct exynos_drm_manager fimd_m
        .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;
-       struct drm_pending_vblank_event *e, *t;
-       struct timeval now;
-       unsigned long flags;
-       spin_lock_irqsave(&drm_dev->event_lock, flags);
-       list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
-                       base.link) {
-               /* if event's pipe isn't same as crtc then ignore it. */
-               if (crtc != e->pipe)
-                       continue;
-               do_gettimeofday(&now);
-               e->event.sequence = 0;
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
-               drm_vblank_put(drm_dev, crtc);
-       }
-       spin_unlock_irqrestore(&drm_dev->event_lock, flags);
- }
  static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
  {
        struct fimd_context *ctx = (struct fimd_context *)dev_id;
                goto out;
  
        drm_handle_vblank(drm_dev, manager->pipe);
-       fimd_finish_pageflip(drm_dev, manager->pipe);
+       exynos_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
  
        /* set wait vsync event to zero and wake up queue. */
        if (atomic_read(&ctx->wait_vsync_event)) {
@@@ -898,7 -870,7 +870,7 @@@ static int fimd_activate(struct fimd_co
        return 0;
  }
  
 -static int __devinit fimd_probe(struct platform_device *pdev)
 +static int fimd_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct fimd_context *ctx;
        return 0;
  }
  
 -static int __devexit fimd_remove(struct platform_device *pdev)
 +static int fimd_remove(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct fimd_context *ctx = platform_get_drvdata(pdev);
@@@ -1046,7 -1018,7 +1018,7 @@@ static int fimd_resume(struct device *d
         * of pm runtime would still be 1 so in this case, fimd driver
         * should be on directly not drawing on pm runtime interface.
         */
-       if (pm_runtime_suspended(dev)) {
+       if (!pm_runtime_suspended(dev)) {
                int ret;
  
                ret = fimd_activate(ctx, true);
@@@ -1105,7 -1077,7 +1077,7 @@@ static const struct dev_pm_ops fimd_pm_
  
  struct platform_driver fimd_driver = {
        .probe          = fimd_probe,
 -      .remove         = __devexit_p(fimd_remove),
 +      .remove         = fimd_remove,
        .id_table       = fimd_driver_ids,
        .driver         = {
                .name   = "exynos4-fb",
index 4b0e8589bd194f1afeb8fdcd551a286b8b23dddd,e8ebd6ea1cd6ecdcddc7c3220f15f684d8d6fc62..8140753ec9c824202173e631bfc1f4ba711c9ef7
@@@ -25,7 -25,7 +25,7 @@@
  #include "exynos_drm_gsc.h"
  
  /*
-  * GSC is stand for General SCaler and
+  * GSC stands for General SCaler and
   * supports image scaler/rotator and input/output DMA operations.
   * input DMA reads image data from the memory.
   * output DMA writes image data to memory.
@@@ -711,7 -711,7 +711,7 @@@ static int gsc_src_set_addr(struct devi
  {
        struct gsc_context *ctx = get_gsc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
  
        if (!c_node) {
        }
  
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EFAULT;
-       }
  
        DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
                property->prop_id, buf_id, buf_type);
@@@ -1171,7 -1167,7 +1167,7 @@@ static int gsc_dst_set_addr(struct devi
  {
        struct gsc_context *ctx = get_gsc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
  
        if (!c_node) {
        }
  
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EFAULT;
-       }
  
        DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
                property->prop_id, buf_id, buf_type);
@@@ -1312,7 -1304,7 +1304,7 @@@ static irqreturn_t gsc_irq_handler(int 
  {
        struct gsc_context *ctx = dev_id;
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_event_work *event_work =
                c_node->event_work;
        u32 status;
@@@ -1399,7 -1391,7 +1391,7 @@@ static inline bool gsc_check_drm_flip(e
        case EXYNOS_DRM_FLIP_NONE:
        case EXYNOS_DRM_FLIP_VERTICAL:
        case EXYNOS_DRM_FLIP_HORIZONTAL:
-       case EXYNOS_DRM_FLIP_VERTICAL | EXYNOS_DRM_FLIP_HORIZONTAL:
+       case EXYNOS_DRM_FLIP_BOTH:
                return true;
        default:
                DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
@@@ -1549,7 -1541,7 +1541,7 @@@ static int gsc_ippdrv_start(struct devi
  {
        struct gsc_context *ctx = get_gsc_context(dev);
        struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_property *property;
        struct drm_exynos_ipp_config *config;
        struct drm_exynos_pos   img_pos[EXYNOS_DRM_OPS_MAX];
        }
  
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property.\n");
-               return -EINVAL;
-       }
  
        gsc_handle_irq(ctx, true, false, true);
  
                exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
  
                /* src local path */
-               cfg = readl(GSC_IN_CON);
+               cfg = gsc_read(GSC_IN_CON);
                cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
                cfg |= (GSC_IN_PATH_LOCAL | GSC_IN_LOCAL_FIMD_WB);
                gsc_write(cfg, GSC_IN_CON);
@@@ -1683,7 -1671,7 +1671,7 @@@ static void gsc_ippdrv_stop(struct devi
        gsc_write(cfg, GSC_ENABLE);
  }
  
 -static int __devinit gsc_probe(struct platform_device *pdev)
 +static int gsc_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct gsc_context *ctx;
                return -ENOMEM;
  
        /* clock control */
-       ctx->gsc_clk = clk_get(dev, "gscl");
+       ctx->gsc_clk = devm_clk_get(dev, "gscl");
        if (IS_ERR(ctx->gsc_clk)) {
                dev_err(dev, "failed to get gsc clock.\n");
-               ret = PTR_ERR(ctx->gsc_clk);
-               goto err_ctx;
+               return PTR_ERR(ctx->gsc_clk);
        }
  
        /* resource memory */
        ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!ctx->regs_res) {
-               dev_err(dev, "failed to find registers.\n");
-               ret = -ENOENT;
-               goto err_clk;
-       }
        ctx->regs = devm_request_and_ioremap(dev, ctx->regs_res);
        if (!ctx->regs) {
                dev_err(dev, "failed to map registers.\n");
-               ret = -ENXIO;
-               goto err_clk;
+               return -ENXIO;
        }
  
        /* resource irq */
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res) {
                dev_err(dev, "failed to request irq resource.\n");
-               ret = -ENOENT;
-               goto err_get_regs;
+               return -ENOENT;
        }
  
        ctx->irq = res->start;
                IRQF_ONESHOT, "drm_gsc", ctx);
        if (ret < 0) {
                dev_err(dev, "failed to request irq.\n");
-               goto err_get_regs;
+               return ret;
        }
  
        /* context initailization */
@@@ -1775,16 -1754,10 +1754,10 @@@ err_ippdrv_register
        pm_runtime_disable(dev);
  err_get_irq:
        free_irq(ctx->irq, ctx);
- err_get_regs:
-       devm_iounmap(dev, ctx->regs);
- err_clk:
-       clk_put(ctx->gsc_clk);
- err_ctx:
-       devm_kfree(dev, ctx);
        return ret;
  }
  
 -static int __devexit gsc_remove(struct platform_device *pdev)
 +static int gsc_remove(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct gsc_context *ctx = get_gsc_context(dev);
        pm_runtime_disable(dev);
  
        free_irq(ctx->irq, ctx);
-       devm_iounmap(dev, ctx->regs);
-       clk_put(ctx->gsc_clk);
-       devm_kfree(dev, ctx);
  
        return 0;
  }
@@@ -1860,7 -1828,7 +1828,7 @@@ static const struct dev_pm_ops gsc_pm_o
  
  struct platform_driver gsc_driver = {
        .probe          = gsc_probe,
 -      .remove         = __devexit_p(gsc_remove),
 +      .remove         = gsc_remove,
        .driver         = {
                .name   = "exynos-drm-gsc",
                .owner  = THIS_MODULE,
index c1f12301224c83ba48e6699cd9311364f33eaf23,e7a860fb74874a469ee9a4335d23d58a5dfd8ade..0bda96454a02fe6e8cf31ced93c37249355a5f99
@@@ -27,7 -27,7 +27,7 @@@
  #include "exynos_drm_iommu.h"
  
  /*
-  * IPP is stand for Image Post Processing and
+  * IPP stands for Image Post Processing and
   * supports image scaler/rotator and input/output DMA operations.
   * using FIMC, GSC, Rotator, so on.
   * IPP is integration device driver of same attribute h/w
@@@ -1292,7 -1292,7 +1292,7 @@@ static int ipp_start_property(struct ex
        DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
  
        /* store command info in ippdrv */
-       ippdrv->cmd = c_node;
+       ippdrv->c_node = c_node;
  
        if (!ipp_check_mem_list(c_node)) {
                DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
        ret = ipp_set_property(ippdrv, property);
        if (ret) {
                DRM_ERROR("failed to set property.\n");
-               ippdrv->cmd = NULL;
+               ippdrv->c_node = NULL;
                return ret;
        }
  
@@@ -1487,11 -1487,6 +1487,6 @@@ void ipp_sched_cmd(struct work_struct *
        mutex_lock(&c_node->cmd_lock);
  
        property = &c_node->property;
-       if (!property) {
-               DRM_ERROR("failed to get property:prop_id[%d]\n",
-                       c_node->property.prop_id);
-               goto err_unlock;
-       }
  
        switch (cmd_work->ctrl) {
        case IPP_CTRL_PLAY:
@@@ -1704,7 -1699,7 +1699,7 @@@ void ipp_sched_event(struct work_struc
                return;
        }
  
-       c_node = ippdrv->cmd;
+       c_node = ippdrv->c_node;
        if (!c_node) {
                DRM_ERROR("failed to get command node.\n");
                return;
@@@ -1888,14 -1883,14 +1883,14 @@@ err_clear
        return;
  }
  
 -static int __devinit ipp_probe(struct platform_device *pdev)
 +static int ipp_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct ipp_context *ctx;
        struct exynos_drm_subdrv *subdrv;
        int ret;
  
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
  
        ctx->event_workq = create_singlethread_workqueue("ipp_event");
        if (!ctx->event_workq) {
                dev_err(dev, "failed to create event workqueue\n");
-               ret = -EINVAL;
-               goto err_clear;
+               return -EINVAL;
        }
  
        /*
@@@ -1958,12 -1952,10 +1952,10 @@@ err_cmd_workq
        destroy_workqueue(ctx->cmd_workq);
  err_event_workq:
        destroy_workqueue(ctx->event_workq);
- err_clear:
-       kfree(ctx);
        return ret;
  }
  
 -static int __devexit ipp_remove(struct platform_device *pdev)
 +static int ipp_remove(struct platform_device *pdev)
  {
        struct ipp_context *ctx = platform_get_drvdata(pdev);
  
        destroy_workqueue(ctx->cmd_workq);
        destroy_workqueue(ctx->event_workq);
  
-       kfree(ctx);
        return 0;
  }
  
@@@ -2050,7 -2040,7 +2040,7 @@@ static const struct dev_pm_ops ipp_pm_o
  
  struct platform_driver ipp_driver = {
        .probe          = ipp_probe,
 -      .remove         = __devexit_p(ipp_remove),
 +      .remove         = ipp_remove,
        .driver         = {
                .name   = "exynos-drm-ipp",
                .owner  = THIS_MODULE,
index c748850737a1f253513afcb97ae8aab3a979b118,cc553a66cfa76648edb7bd39d783fbd5e22b6be8..e9e83ef688f0c3a4ccf0253154975eebddb1d378
@@@ -139,7 -139,7 +139,7 @@@ static irqreturn_t rotator_irq_handler(
  {
        struct rot_context *rot = arg;
        struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
-       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
+       struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
        struct drm_exynos_ipp_event_work *event_work = c_node->event_work;
        enum rot_irq_status irq_status;
        u32 val;
@@@ -513,6 -513,7 +513,7 @@@ static inline bool rotator_check_drm_fl
        case EXYNOS_DRM_FLIP_NONE:
        case EXYNOS_DRM_FLIP_VERTICAL:
        case EXYNOS_DRM_FLIP_HORIZONTAL:
+       case EXYNOS_DRM_FLIP_BOTH:
                return true;
        default:
                DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
@@@ -638,7 -639,7 +639,7 @@@ static int rotator_ippdrv_start(struct 
        return 0;
  }
  
 -static int __devinit rotator_probe(struct platform_device *pdev)
 +static int rotator_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct rot_context *rot;
                                platform_get_device_id(pdev)->driver_data;
  
        rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!rot->regs_res) {
-               dev_err(dev, "failed to find registers\n");
-               ret = -ENOENT;
-               goto err_get_resource;
-       }
        rot->regs = devm_request_and_ioremap(dev, rot->regs_res);
        if (!rot->regs) {
                dev_err(dev, "failed to map register\n");
-               ret = -ENXIO;
-               goto err_get_resource;
+               return -ENXIO;
        }
  
        rot->irq = platform_get_irq(pdev, 0);
        if (rot->irq < 0) {
                dev_err(dev, "failed to get irq\n");
-               ret = rot->irq;
-               goto err_get_irq;
+               return rot->irq;
        }
  
        ret = request_threaded_irq(rot->irq, NULL, rotator_irq_handler,
                        IRQF_ONESHOT, "drm_rotator", rot);
        if (ret < 0) {
                dev_err(dev, "failed to request irq\n");
-               goto err_get_irq;
+               return ret;
        }
  
-       rot->clock = clk_get(dev, "rotator");
+       rot->clock = devm_clk_get(dev, "rotator");
        if (IS_ERR_OR_NULL(rot->clock)) {
                dev_err(dev, "failed to get clock\n");
                ret = PTR_ERR(rot->clock);
  err_ippdrv_register:
        devm_kfree(dev, ippdrv->prop_list);
        pm_runtime_disable(dev);
-       clk_put(rot->clock);
  err_clk_get:
        free_irq(rot->irq, rot);
- err_get_irq:
-       devm_iounmap(dev, rot->regs);
- err_get_resource:
-       devm_kfree(dev, rot);
        return ret;
  }
  
 -static int __devexit rotator_remove(struct platform_device *pdev)
 +static int rotator_remove(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct rot_context *rot = dev_get_drvdata(dev);
        exynos_drm_ippdrv_unregister(ippdrv);
  
        pm_runtime_disable(dev);
-       clk_put(rot->clock);
  
        free_irq(rot->irq, rot);
-       devm_iounmap(dev, rot->regs);
-       devm_kfree(dev, rot);
  
        return 0;
  }
@@@ -845,7 -829,7 +829,7 @@@ static const struct dev_pm_ops rotator_
  
  struct platform_driver rotator_driver = {
        .probe          = rotator_probe,
 -      .remove         = __devexit_p(rotator_remove),
 +      .remove         = rotator_remove,
        .id_table       = rotator_driver_ids,
        .driver         = {
                .name   = "exynos-rot",
index a5c5a179e3b64789445ca2a4e730ad0c403031e9,ae09d44af26416e0804e54ae9096d2e4eacb47d4..d0ca3c4e06c60bbeca05e87b783d1e7e4b690f16
@@@ -372,34 -372,6 +372,6 @@@ static struct exynos_drm_manager vidi_m
        .display_ops    = &vidi_display_ops,
  };
  
- static void vidi_finish_pageflip(struct drm_device *drm_dev, int crtc)
- {
-       struct exynos_drm_private *dev_priv = drm_dev->dev_private;
-       struct drm_pending_vblank_event *e, *t;
-       struct timeval now;
-       unsigned long flags;
-       spin_lock_irqsave(&drm_dev->event_lock, flags);
-       list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
-                       base.link) {
-               /* if event's pipe isn't same as crtc then ignore it. */
-               if (crtc != e->pipe)
-                       continue;
-               do_gettimeofday(&now);
-               e->event.sequence = 0;
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
-               drm_vblank_put(drm_dev, crtc);
-       }
-       spin_unlock_irqrestore(&drm_dev->event_lock, flags);
- }
  static void vidi_fake_vblank_handler(struct work_struct *work)
  {
        struct vidi_context *ctx = container_of(work, struct vidi_context,
  
        mutex_unlock(&ctx->lock);
  
-       vidi_finish_pageflip(subdrv->drm_dev, manager->pipe);
+       exynos_drm_crtc_finish_pageflip(subdrv->drm_dev, manager->pipe);
  }
  
  static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
@@@ -609,7 -581,7 +581,7 @@@ int vidi_connection_ioctl(struct drm_de
        return 0;
  }
  
 -static int __devinit vidi_probe(struct platform_device *pdev)
 +static int vidi_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct vidi_context *ctx;
        return 0;
  }
  
 -static int __devexit vidi_remove(struct platform_device *pdev)
 +static int vidi_remove(struct platform_device *pdev)
  {
        struct vidi_context *ctx = platform_get_drvdata(pdev);
  
@@@ -683,7 -655,7 +655,7 @@@ static const struct dev_pm_ops vidi_pm_
  
  struct platform_driver vidi_driver = {
        .probe          = vidi_probe,
 -      .remove         = __devexit_p(vidi_remove),
 +      .remove         = vidi_remove,
        .driver         = {
                .name   = "exynos-drm-vidi",
                .owner  = THIS_MODULE,
index 3f68b34fa1276dc34053e5f6a604b4e965a4cc59,e9dbf7935e9178782ce14b1f0a04d65ef40edbff..c187ea33b748c031b91d10e45479d98368b297f6
@@@ -35,6 -35,7 +35,7 @@@
  #include <drm/exynos_drm.h>
  
  #include "exynos_drm_drv.h"
+ #include "exynos_drm_crtc.h"
  #include "exynos_drm_hdmi.h"
  #include "exynos_drm_iommu.h"
  
@@@ -949,35 -950,6 +950,6 @@@ static struct exynos_mixer_ops mixer_op
        .win_disable            = mixer_win_disable,
  };
  
- /* for pageflip event */
- static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
- {
-       struct exynos_drm_private *dev_priv = drm_dev->dev_private;
-       struct drm_pending_vblank_event *e, *t;
-       struct timeval now;
-       unsigned long flags;
-       spin_lock_irqsave(&drm_dev->event_lock, flags);
-       list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
-                       base.link) {
-               /* if event's pipe isn't same as crtc then ignore it. */
-               if (crtc != e->pipe)
-                       continue;
-               do_gettimeofday(&now);
-               e->event.sequence = 0;
-               e->event.tv_sec = now.tv_sec;
-               e->event.tv_usec = now.tv_usec;
-               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
-               drm_vblank_put(drm_dev, crtc);
-       }
-       spin_unlock_irqrestore(&drm_dev->event_lock, flags);
- }
  static irqreturn_t mixer_irq_handler(int irq, void *arg)
  {
        struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
                }
  
                drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
-               mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
+               exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
+                               ctx->pipe);
  
                /* set wait vsync event to zero and wake up queue. */
                if (atomic_read(&ctx->wait_vsync_event)) {
@@@ -1029,8 -1002,8 +1002,8 @@@ out
        return IRQ_HANDLED;
  }
  
 -static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
 -                               struct platform_device *pdev)
 +static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
 +                              struct platform_device *pdev)
  {
        struct mixer_context *mixer_ctx = ctx->ctx;
        struct device *dev = &pdev->dev;
        return 0;
  }
  
 -static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx,
 -                               struct platform_device *pdev)
 +static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
 +                           struct platform_device *pdev)
  {
        struct mixer_context *mixer_ctx = ctx->ctx;
        struct device *dev = &pdev->dev;
@@@ -1155,7 -1128,7 +1128,7 @@@ static struct of_device_id mixer_match_
        }
  };
  
 -static int __devinit mixer_probe(struct platform_device *pdev)
 +static int mixer_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct exynos_drm_hdmi_context *drm_hdmi_ctx;
@@@ -1316,6 -1289,6 +1289,6 @@@ struct platform_driver mixer_driver = 
                .of_match_table = mixer_match_types,
        },
        .probe = mixer_probe,
 -      .remove = __devexit_p(mixer_remove),
 +      .remove = mixer_remove,
        .id_table       = mixer_driver_types,
  };