]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge tag 'drm-amdkfd-next-fixes-2015-08-05' of git://people.freedesktop.org/~gabbayo...
authorDave Airlie <airlied@redhat.com>
Fri, 14 Aug 2015 00:15:24 +0000 (10:15 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 14 Aug 2015 00:15:24 +0000 (10:15 +1000)
Two small bug fixes for the code you pulled for 4.3:

- Used a SHIFT define instead of a MASK define to check if a bit is turned on
  when destroying hqd. Luckily, this is in gfx7 interface file with amdgpu,
  which was used only for bring-up purposes of amdgpu, so no real effect on
  a running system

- Used a logical AND instead of a bitwise AND operator, when initializing
  sdma virtual memory when using SDMA queues

* tag 'drm-amdkfd-next-fixes-2015-08-05' of git://people.freedesktop.org/~gabbayo/linux:
  drm/amdkfd: fix bug when initializing sdma vm
  drm/amdgpu: fix bug when amdkfd destroys hqd

111 files changed:
Documentation/devicetree/bindings/gpu/st,stih4xx.txt
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
drivers/gpu/drm/armada/armada_fbdev.c
drivers/gpu/drm/ast/ast_fb.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
drivers/gpu/drm/bochs/bochs_drv.c
drivers/gpu/drm/bochs/bochs_fbdev.c
drivers/gpu/drm/bochs/bochs_mm.c
drivers/gpu/drm/cirrus/cirrus_drv.c
drivers/gpu/drm/cirrus/cirrus_fbdev.c
drivers/gpu/drm/cirrus/cirrus_main.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_gem_cma_helper.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_modeset_lock.c
drivers/gpu/drm/drm_plane_helper.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/gma500/accel_2d.c
drivers/gpu/drm/gma500/framebuffer.c
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/mgag200/mgag200_cursor.c
drivers/gpu/drm/mgag200/mgag200_fb.c
drivers/gpu/drm/mgag200/mgag200_main.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/msm_fbdev.c
drivers/gpu/drm/nouveau/dispnv04/overlay.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_ttm.c
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_fbdev.c
drivers/gpu/drm/qxl/qxl_fb.c
drivers/gpu/drm/qxl/qxl_object.c
drivers/gpu/drm/radeon/radeon_dp_mst.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
drivers/gpu/drm/rockchip/rockchip_drm_gem.c
drivers/gpu/drm/sti/Makefile
drivers/gpu/drm/sti/sti_compositor.c
drivers/gpu/drm/sti/sti_compositor.h
drivers/gpu/drm/sti/sti_crtc.c [moved from drivers/gpu/drm/sti/sti_drm_crtc.c with 56% similarity]
drivers/gpu/drm/sti/sti_crtc.h [new file with mode: 0644]
drivers/gpu/drm/sti/sti_cursor.c
drivers/gpu/drm/sti/sti_cursor.h
drivers/gpu/drm/sti/sti_drm_crtc.h [deleted file]
drivers/gpu/drm/sti/sti_drm_plane.c [deleted file]
drivers/gpu/drm/sti/sti_drm_plane.h [deleted file]
drivers/gpu/drm/sti/sti_drv.c [moved from drivers/gpu/drm/sti/sti_drm_drv.c with 61% similarity]
drivers/gpu/drm/sti/sti_drv.h [moved from drivers/gpu/drm/sti/sti_drm_drv.h with 90% similarity]
drivers/gpu/drm/sti/sti_gdp.c
drivers/gpu/drm/sti/sti_gdp.h
drivers/gpu/drm/sti/sti_hdmi.c
drivers/gpu/drm/sti/sti_hqvdp.c
drivers/gpu/drm/sti/sti_hqvdp.h [deleted file]
drivers/gpu/drm/sti/sti_layer.c [deleted file]
drivers/gpu/drm/sti/sti_layer.h [deleted file]
drivers/gpu/drm/sti/sti_mixer.c
drivers/gpu/drm/sti/sti_mixer.h
drivers/gpu/drm/sti/sti_plane.c [new file with mode: 0644]
drivers/gpu/drm/sti/sti_plane.h [new file with mode: 0644]
drivers/gpu/drm/sti/sti_tvout.c
drivers/gpu/drm/sti/sti_vid.c
drivers/gpu/drm/sti/sti_vid.h
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/dsi.c
drivers/gpu/drm/tegra/fb.c
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/drm/tegra/sor.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/udl/udl_fb.c
drivers/gpu/drm/virtio/virtgpu_fb.c
drivers/gpu/drm/vmwgfx/vmwgfx_context.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/vga/vga_switcheroo.c
drivers/gpu/vga/vgaarb.c
drivers/video/Kconfig
include/drm/drmP.h
include/drm/drm_atomic.h
include/drm/drm_atomic_helper.h
include/drm/drm_crtc.h
include/drm/drm_crtc_helper.h
include/drm/drm_dp_helper.h
include/drm/drm_fb_helper.h
include/drm/drm_modeset_lock.h
include/drm/drm_plane_helper.h

index 6b1d75f1a5297f7eb76c9618103f5f4400b8f7f8..a36dfce0032e25d056b460f93af099d3d6e45a11 100644 (file)
@@ -52,10 +52,9 @@ STMicroelectronics stih4xx platforms
     See ../reset/reset.txt for details.
   - reset-names: names of the resets listed in resets property in the same
     order.
-  - ranges: to allow probing of subdevices
 
 - sti-hdmi: hdmi output block
-  must be a child of sti-tvout
+  must be a child of sti-display-subsystem
   Required properties:
   - compatible: "st,stih<chip>-hdmi";
   - reg: Physical base address of the IP registers and length of memory mapped region.
@@ -72,7 +71,7 @@ STMicroelectronics stih4xx platforms
 
 sti-hda:
   Required properties:
-  must be a child of sti-tvout
+  must be a child of sti-display-subsystem
   - compatible: "st,stih<chip>-hda"
   - reg: Physical base address of the IP registers and length of memory mapped region.
   - reg-names: names of the mapped memory regions listed in regs property in
@@ -85,7 +84,7 @@ sti-hda:
 
 sti-dvo:
   Required properties:
-  must be a child of sti-tvout
+  must be a child of sti-display-subsystem
   - compatible: "st,stih<chip>-dvo"
   - reg: Physical base address of the IP registers and length of memory mapped region.
   - reg-names: names of the mapped memory regions listed in regs property in
@@ -195,38 +194,37 @@ Example:
                        reg-names       = "tvout-reg", "hda-reg", "syscfg";
                        reset-names     = "tvout";
                        resets          = <&softreset STIH416_HDTVOUT_SOFTRESET>;
-                       ranges;
-
-                       sti-hdmi@fe85c000 {
-                               compatible      = "st,stih416-hdmi";
-                               reg             = <0xfe85c000 0x1000>, <0xfe830000 0x10000>;
-                               reg-names       = "hdmi-reg", "syscfg";
-                               interrupts      = <GIC_SPI 173 IRQ_TYPE_NONE>;
-                               interrupt-names = "irq";
-                               clock-names     = "pix", "tmds", "phy", "audio";
-                               clocks          = <&clockgen_c_vcc CLK_S_PIX_HDMI>, <&clockgen_c_vcc CLK_S_TMDS_HDMI>, <&clockgen_c_vcc CLK_S_HDMI_REJECT_PLL>, <&clockgen_b1 CLK_S_PCM_0>;
-                       };
-
-                       sti-hda@fe85a000 {
-                               compatible      = "st,stih416-hda";
-                               reg             = <0xfe85a000 0x400>, <0xfe83085c 0x4>;
-                               reg-names       = "hda-reg", "video-dacs-ctrl";
-                               clock-names     = "pix", "hddac";
-                               clocks          = <&clockgen_c_vcc CLK_S_PIX_HD>, <&clockgen_c_vcc CLK_S_HDDAC>;
-                       };
-
-                       sti-dvo@8d00400 {
-                               compatible      = "st,stih407-dvo";
-                               reg             = <0x8d00400 0x200>;
-                               reg-names       = "dvo-reg";
-                               clock-names     = "dvo_pix", "dvo",
-                                                 "main_parent", "aux_parent";
-                               clocks          = <&clk_s_d2_flexgen CLK_PIX_DVO>, <&clk_s_d2_flexgen CLK_DVO>,
-                                                 <&clk_s_d2_quadfs 0>, <&clk_s_d2_quadfs 1>;
-                               pinctrl-names   = "default";
-                               pinctrl-0       = <&pinctrl_dvo>;
-                               sti,panel       = <&panel_dvo>;
-                       };
+               };
+
+               sti-hdmi@fe85c000 {
+                       compatible      = "st,stih416-hdmi";
+                       reg             = <0xfe85c000 0x1000>, <0xfe830000 0x10000>;
+                       reg-names       = "hdmi-reg", "syscfg";
+                       interrupts      = <GIC_SPI 173 IRQ_TYPE_NONE>;
+                       interrupt-names = "irq";
+                       clock-names     = "pix", "tmds", "phy", "audio";
+                       clocks          = <&clockgen_c_vcc CLK_S_PIX_HDMI>, <&clockgen_c_vcc CLK_S_TMDS_HDMI>, <&clockgen_c_vcc CLK_S_HDMI_REJECT_PLL>, <&clockgen_b1 CLK_S_PCM_0>;
+               };
+
+               sti-hda@fe85a000 {
+                       compatible      = "st,stih416-hda";
+                       reg             = <0xfe85a000 0x400>, <0xfe83085c 0x4>;
+                       reg-names       = "hda-reg", "video-dacs-ctrl";
+                       clock-names     = "pix", "hddac";
+                       clocks          = <&clockgen_c_vcc CLK_S_PIX_HD>, <&clockgen_c_vcc CLK_S_HDDAC>;
+               };
+
+               sti-dvo@8d00400 {
+                       compatible      = "st,stih407-dvo";
+                       reg             = <0x8d00400 0x200>;
+                       reg-names       = "dvo-reg";
+                       clock-names     = "dvo_pix", "dvo",
+                                         "main_parent", "aux_parent";
+                       clocks          = <&clk_s_d2_flexgen CLK_PIX_DVO>, <&clk_s_d2_flexgen CLK_DVO>,
+                                         <&clk_s_d2_quadfs 0>, <&clk_s_d2_quadfs 1>;
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_dvo>;
+                       sti,panel       = <&panel_dvo>;
                };
 
                sti-hqvdp@9c000000 {
@@ -237,7 +235,7 @@ Example:
                                reset-names     = "hqvdp";
                                resets          = <&softreset STIH407_HDQVDP_SOFTRESET>;
                                st,vtg          = <&vtg_main>;
-                       };
+               };
        };
        ...
 };
index c46ca311d8c31d27d2617eb709c1c0776c8568af..06ae5008c5edf2b96d114ea53e9527b4bc29d5fe 100644 (file)
@@ -37,9 +37,29 @@ config DRM_KMS_FB_HELPER
        select FB
        select FRAMEBUFFER_CONSOLE if !EXPERT
        select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
+       select FB_SYS_FOPS
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
        help
          FBDEV helpers for KMS drivers.
 
+config DRM_FBDEV_EMULATION
+       bool "Enable legacy fbdev support for your modesetting driver"
+       depends on DRM
+       select DRM_KMS_HELPER
+       select DRM_KMS_FB_HELPER
+       default y
+       help
+         Choose this option if you have a need for the legacy fbdev
+         support. Note that this support also provides the linux console
+         support on top of your modesetting driver.
+
+         If in doubt, say "Y".
+
 config DRM_LOAD_EDID_FIRMWARE
        bool "Allow to specify an EDID data set instead of probing for it"
        depends on DRM_KMS_HELPER
index 5713d0534504c96cc1d218749d385bedcb74d701..8858510437ea089e4fe03e7808811146751e17d8 100644 (file)
@@ -23,7 +23,7 @@ drm-$(CONFIG_OF) += drm_of.o
 drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
                drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o
 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
-drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o
+drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
 drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
 
 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
index c1645d21f8e244d6d2231073d39f88d0a5a41ca0..81b821247dde5ca4fa3992083813fe848ac97e99 100644 (file)
@@ -53,9 +53,9 @@ static struct fb_ops amdgpufb_ops = {
        .owner = THIS_MODULE,
        .fb_check_var = drm_fb_helper_check_var,
        .fb_set_par = drm_fb_helper_set_par,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = cfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
+       .fb_fillrect = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit = drm_fb_helper_cfb_imageblit,
        .fb_pan_display = drm_fb_helper_pan_display,
        .fb_blank = drm_fb_helper_blank,
        .fb_setcmap = drm_fb_helper_setcmap,
@@ -179,7 +179,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
        struct drm_mode_fb_cmd2 mode_cmd;
        struct drm_gem_object *gobj = NULL;
        struct amdgpu_bo *rbo = NULL;
-       struct device *device = &adev->pdev->dev;
        int ret;
        unsigned long tmp;
 
@@ -201,9 +200,9 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
        rbo = gem_to_amdgpu_bo(gobj);
 
        /* okay we have an object now allocate the framebuffer */
-       info = framebuffer_alloc(0, device);
-       if (info == NULL) {
-               ret = -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
                goto out_unref;
        }
 
@@ -212,14 +211,13 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
        ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
        if (ret) {
                DRM_ERROR("failed to initialize framebuffer %d\n", ret);
-               goto out_unref;
+               goto out_destroy_fbi;
        }
 
        fb = &rfbdev->rfb.base;
 
        /* setup helper */
        rfbdev->helper.fb = fb;
-       rfbdev->helper.fbdev = info;
 
        memset_io(rbo->kptr, 0x0, amdgpu_bo_size(rbo));
 
@@ -239,11 +237,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
        drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height);
 
        /* setup aperture base/size for vesafb takeover */
-       info->apertures = alloc_apertures(1);
-       if (!info->apertures) {
-               ret = -ENOMEM;
-               goto out_unref;
-       }
        info->apertures->ranges[0].base = adev->ddev->mode_config.fb_base;
        info->apertures->ranges[0].size = adev->mc.aper_size;
 
@@ -251,13 +244,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
 
        if (info->screen_base == NULL) {
                ret = -ENOSPC;
-               goto out_unref;
-       }
-
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto out_unref;
+               goto out_destroy_fbi;
        }
 
        DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
@@ -269,6 +256,8 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
        vga_switcheroo_client_fb_set(adev->ddev->pdev, info);
        return 0;
 
+out_destroy_fbi:
+       drm_fb_helper_release_fbi(helper);
 out_unref:
        if (rbo) {
 
@@ -290,17 +279,10 @@ void amdgpu_fb_output_poll_changed(struct amdgpu_device *adev)
 
 static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfbdev)
 {
-       struct fb_info *info;
        struct amdgpu_framebuffer *rfb = &rfbdev->rfb;
 
-       if (rfbdev->helper.fbdev) {
-               info = rfbdev->helper.fbdev;
-
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&rfbdev->helper);
+       drm_fb_helper_release_fbi(&rfbdev->helper);
 
        if (rfb->obj) {
                amdgpufb_destroy_pinned_object(rfb->obj);
@@ -395,7 +377,8 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev)
 void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state)
 {
        if (adev->mode_info.rfbdev)
-               fb_set_suspend(adev->mode_info.rfbdev->helper.fbdev, state);
+               drm_fb_helper_set_suspend(&adev->mode_info.rfbdev->helper,
+                       state);
 }
 
 int amdgpu_fbdev_total_size(struct amdgpu_device *adev)
index 7838e731b0de1be856af431aa3848013a3492e09..7d03c51abcb9d6e3dfc9a277be5ad4141c21606b 100644 (file)
@@ -22,9 +22,9 @@ static /*const*/ struct fb_ops armada_fb_ops = {
        .owner          = THIS_MODULE,
        .fb_check_var   = drm_fb_helper_check_var,
        .fb_set_par     = drm_fb_helper_set_par,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
+       .fb_fillrect    = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea    = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit   = drm_fb_helper_cfb_imageblit,
        .fb_pan_display = drm_fb_helper_pan_display,
        .fb_blank       = drm_fb_helper_blank,
        .fb_setcmap     = drm_fb_helper_setcmap,
@@ -80,18 +80,12 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
        if (IS_ERR(dfb))
                return PTR_ERR(dfb);
 
-       info = framebuffer_alloc(0, dev->dev);
-       if (!info) {
-               ret = -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(fbh);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
                goto err_fballoc;
        }
 
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto err_fbcmap;
-       }
-
        strlcpy(info->fix.id, "armada-drmfb", sizeof(info->fix.id));
        info->par = fbh;
        info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
@@ -101,7 +95,7 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
        info->screen_size = obj->obj.size;
        info->screen_base = ptr;
        fbh->fb = &dfb->fb;
-       fbh->fbdev = info;
+
        drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth);
        drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height);
 
@@ -111,8 +105,6 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
 
        return 0;
 
- err_fbcmap:
-       framebuffer_release(info);
  err_fballoc:
        dfb->fb.funcs->destroy(&dfb->fb);
        return ret;
@@ -171,6 +163,7 @@ int armada_fbdev_init(struct drm_device *dev)
 
        return 0;
  err_fb_setup:
+       drm_fb_helper_release_fbi(fbh);
        drm_fb_helper_fini(fbh);
  err_fb_helper:
        priv->fbdev = NULL;
@@ -191,14 +184,8 @@ void armada_fbdev_fini(struct drm_device *dev)
        struct drm_fb_helper *fbh = priv->fbdev;
 
        if (fbh) {
-               struct fb_info *info = fbh->fbdev;
-
-               if (info) {
-                       unregister_framebuffer(info);
-                       if (info->cmap.len)
-                               fb_dealloc_cmap(&info->cmap);
-                       framebuffer_release(info);
-               }
+               drm_fb_helper_unregister_fbi(fbh);
+               drm_fb_helper_release_fbi(fbh);
 
                drm_fb_helper_fini(fbh);
 
index ff68eefae27316b87d2cd72020b0639becfc7516..f31db28a684b3e2cbfb042a9aebf11f0bd912105 100644 (file)
@@ -125,7 +125,7 @@ static void ast_fillrect(struct fb_info *info,
                         const struct fb_fillrect *rect)
 {
        struct ast_fbdev *afbdev = info->par;
-       sys_fillrect(info, rect);
+       drm_fb_helper_sys_fillrect(info, rect);
        ast_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
                         rect->height);
 }
@@ -134,7 +134,7 @@ static void ast_copyarea(struct fb_info *info,
                         const struct fb_copyarea *area)
 {
        struct ast_fbdev *afbdev = info->par;
-       sys_copyarea(info, area);
+       drm_fb_helper_sys_copyarea(info, area);
        ast_dirty_update(afbdev, area->dx, area->dy, area->width,
                         area->height);
 }
@@ -143,7 +143,7 @@ static void ast_imageblit(struct fb_info *info,
                          const struct fb_image *image)
 {
        struct ast_fbdev *afbdev = info->par;
-       sys_imageblit(info, image);
+       drm_fb_helper_sys_imageblit(info, image);
        ast_dirty_update(afbdev, image->dx, image->dy, image->width,
                         image->height);
 }
@@ -193,7 +193,6 @@ static int astfb_create(struct drm_fb_helper *helper,
        struct drm_framebuffer *fb;
        struct fb_info *info;
        int size, ret;
-       struct device *device = &dev->pdev->dev;
        void *sysram;
        struct drm_gem_object *gobj = NULL;
        struct ast_bo *bo = NULL;
@@ -217,40 +216,28 @@ static int astfb_create(struct drm_fb_helper *helper,
        if (!sysram)
                return -ENOMEM;
 
-       info = framebuffer_alloc(0, device);
-       if (!info) {
-               ret = -ENOMEM;
-               goto out;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
+               goto err_free_vram;
        }
        info->par = afbdev;
 
        ret = ast_framebuffer_init(dev, &afbdev->afb, &mode_cmd, gobj);
        if (ret)
-               goto out;
+               goto err_release_fbi;
 
        afbdev->sysram = sysram;
        afbdev->size = size;
 
        fb = &afbdev->afb.base;
        afbdev->helper.fb = fb;
-       afbdev->helper.fbdev = info;
 
        strcpy(info->fix.id, "astdrmfb");
 
        info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
        info->fbops = &astfb_ops;
 
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       info->apertures = alloc_apertures(1);
-       if (!info->apertures) {
-               ret = -ENOMEM;
-               goto out;
-       }
        info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0);
        info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0);
 
@@ -266,7 +253,11 @@ static int astfb_create(struct drm_fb_helper *helper,
                      fb->width, fb->height);
 
        return 0;
-out:
+
+err_release_fbi:
+       drm_fb_helper_release_fbi(helper);
+err_free_vram:
+       vfree(afbdev->sysram);
        return ret;
 }
 
@@ -297,15 +288,10 @@ static const struct drm_fb_helper_funcs ast_fb_helper_funcs = {
 static void ast_fbdev_destroy(struct drm_device *dev,
                              struct ast_fbdev *afbdev)
 {
-       struct fb_info *info;
        struct ast_framebuffer *afb = &afbdev->afb;
-       if (afbdev->helper.fbdev) {
-               info = afbdev->helper.fbdev;
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
+
+       drm_fb_helper_unregister_fbi(&afbdev->helper);
+       drm_fb_helper_release_fbi(&afbdev->helper);
 
        if (afb->obj) {
                drm_gem_object_unreference_unlocked(afb->obj);
@@ -377,5 +363,5 @@ void ast_fbdev_set_suspend(struct drm_device *dev, int state)
        if (!ast->fbdev)
                return;
 
-       fb_set_suspend(ast->fbdev->helper.fbdev, state);
+       drm_fb_helper_set_suspend(&ast->fbdev->helper, state);
 }
index 035dacc93382f0923a9d52c645a70cc192a6756e..838217f8ce7dd681de66fa976f8d8bc93b98ece7 100644 (file)
@@ -571,24 +571,18 @@ ast_dumb_mmap_offset(struct drm_file *file,
                     uint64_t *offset)
 {
        struct drm_gem_object *obj;
-       int ret;
        struct ast_bo *bo;
 
-       mutex_lock(&dev->struct_mutex);
        obj = drm_gem_object_lookup(dev, file, handle);
-       if (obj == NULL) {
-               ret = -ENOENT;
-               goto out_unlock;
-       }
+       if (obj == NULL)
+               return -ENOENT;
 
        bo = gem_to_ast_bo(obj);
        *offset = ast_bo_mmap_offset(bo);
 
-       drm_gem_object_unreference(obj);
-       ret = 0;
-out_unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
+       drm_gem_object_unreference_unlocked(obj);
+
+       return 0;
 
 }
 
index f69b92535505b5ae1c899d6f9b08f76501851fa7..8b8fe3762ca9dba11c73b24f1dea6f75bb0ec009 100644 (file)
@@ -239,7 +239,8 @@ static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c,
        return atmel_hlcdc_plane_prepare_disc_area(s);
 }
 
-static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c)
+static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c,
+                                         struct drm_crtc_state *old_s)
 {
        struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
 
@@ -253,7 +254,8 @@ static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c)
        }
 }
 
-static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc)
+static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc,
+                                         struct drm_crtc_state *old_s)
 {
        /* TODO: write common plane control register if available */
 }
index 98837bde2d2528356c2764b27fe5ac3721c51817..7f1a3604b19f60295ded6b684159981c651ca322 100644 (file)
@@ -109,7 +109,7 @@ static int bochs_pm_suspend(struct device *dev)
 
        if (bochs->fb.initialized) {
                console_lock();
-               fb_set_suspend(bochs->fb.helper.fbdev, 1);
+               drm_fb_helper_set_suspend(&bochs->fb.helper, 1);
                console_unlock();
        }
 
@@ -126,7 +126,7 @@ static int bochs_pm_resume(struct device *dev)
 
        if (bochs->fb.initialized) {
                console_lock();
-               fb_set_suspend(bochs->fb.helper.fbdev, 0);
+               drm_fb_helper_set_suspend(&bochs->fb.helper, 0);
                console_unlock();
        }
 
index 976d9798dc99d4b1eb498b7d8f2634c35c756a34..09a0637aab3e7e7379efb6ca6aa40329b8f361ad 100644 (file)
@@ -24,9 +24,9 @@ static struct fb_ops bochsfb_ops = {
        .owner = THIS_MODULE,
        .fb_check_var = drm_fb_helper_check_var,
        .fb_set_par = drm_fb_helper_set_par,
-       .fb_fillrect = sys_fillrect,
-       .fb_copyarea = sys_copyarea,
-       .fb_imageblit = sys_imageblit,
+       .fb_fillrect = drm_fb_helper_sys_fillrect,
+       .fb_copyarea = drm_fb_helper_sys_copyarea,
+       .fb_imageblit = drm_fb_helper_sys_imageblit,
        .fb_pan_display = drm_fb_helper_pan_display,
        .fb_blank = drm_fb_helper_blank,
        .fb_setcmap = drm_fb_helper_setcmap,
@@ -56,11 +56,9 @@ static int bochsfb_create(struct drm_fb_helper *helper,
 {
        struct bochs_device *bochs =
                container_of(helper, struct bochs_device, fb.helper);
-       struct drm_device *dev = bochs->dev;
        struct fb_info *info;
        struct drm_framebuffer *fb;
        struct drm_mode_fb_cmd2 mode_cmd;
-       struct device *device = &dev->pdev->dev;
        struct drm_gem_object *gobj = NULL;
        struct bochs_bo *bo = NULL;
        int size, ret;
@@ -106,22 +104,23 @@ static int bochsfb_create(struct drm_fb_helper *helper,
        ttm_bo_unreserve(&bo->bo);
 
        /* init fb device */
-       info = framebuffer_alloc(0, device);
-       if (info == NULL)
-               return -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info))
+               return PTR_ERR(info);
 
        info->par = &bochs->fb.helper;
 
        ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj);
-       if (ret)
+       if (ret) {
+               drm_fb_helper_release_fbi(helper);
                return ret;
+       }
 
        bochs->fb.size = size;
 
        /* setup helper */
        fb = &bochs->fb.gfb.base;
        bochs->fb.helper.fb = fb;
-       bochs->fb.helper.fbdev = info;
 
        strcpy(info->fix.id, "bochsdrmfb");
 
@@ -139,30 +138,17 @@ static int bochsfb_create(struct drm_fb_helper *helper,
        info->fix.smem_start = 0;
        info->fix.smem_len = size;
 
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
-               return -ENOMEM;
-       }
-
        return 0;
 }
 
 static int bochs_fbdev_destroy(struct bochs_device *bochs)
 {
        struct bochs_framebuffer *gfb = &bochs->fb.gfb;
-       struct fb_info *info;
 
        DRM_DEBUG_DRIVER("\n");
 
-       if (bochs->fb.helper.fbdev) {
-               info = bochs->fb.helper.fbdev;
-
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&bochs->fb.helper);
+       drm_fb_helper_release_fbi(&bochs->fb.helper);
 
        if (gfb->obj) {
                drm_gem_object_unreference_unlocked(gfb->obj);
index 66286ff518d4be28e8b71b2b8ebf0d0b2ada6496..f69e6bf9bb0e3cd295285f3fbf5ad72c49a3ed93 100644 (file)
@@ -454,25 +454,17 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
                           uint32_t handle, uint64_t *offset)
 {
        struct drm_gem_object *obj;
-       int ret;
        struct bochs_bo *bo;
 
-       mutex_lock(&dev->struct_mutex);
        obj = drm_gem_object_lookup(dev, file, handle);
-       if (obj == NULL) {
-               ret = -ENOENT;
-               goto out_unlock;
-       }
+       if (obj == NULL)
+               return -ENOENT;
 
        bo = gem_to_bochs_bo(obj);
        *offset = bochs_bo_mmap_offset(bo);
 
-       drm_gem_object_unreference(obj);
-       ret = 0;
-out_unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
-
+       drm_gem_object_unreference_unlocked(obj);
+       return 0;
 }
 
 /* ---------------------------------------------------------------------- */
index b9140032962d943e658a9bc18af8be8418bc479f..b1619e29a564db97ef626fd2c32bceaa3a18cadc 100644 (file)
@@ -92,7 +92,7 @@ static int cirrus_pm_suspend(struct device *dev)
 
        if (cdev->mode_info.gfbdev) {
                console_lock();
-               fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1);
+               drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 1);
                console_unlock();
        }
 
@@ -109,7 +109,7 @@ static int cirrus_pm_resume(struct device *dev)
 
        if (cdev->mode_info.gfbdev) {
                console_lock();
-               fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0);
+               drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 0);
                console_unlock();
        }
 
index 13ddf1c4bb8e45ef5be0ddcdf82d7bad9daf79e9..589103bcc06c05951180711506110ba13b2cd2fc 100644 (file)
@@ -98,7 +98,7 @@ static void cirrus_fillrect(struct fb_info *info,
                         const struct fb_fillrect *rect)
 {
        struct cirrus_fbdev *afbdev = info->par;
-       sys_fillrect(info, rect);
+       drm_fb_helper_sys_fillrect(info, rect);
        cirrus_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
                         rect->height);
 }
@@ -107,7 +107,7 @@ static void cirrus_copyarea(struct fb_info *info,
                         const struct fb_copyarea *area)
 {
        struct cirrus_fbdev *afbdev = info->par;
-       sys_copyarea(info, area);
+       drm_fb_helper_sys_copyarea(info, area);
        cirrus_dirty_update(afbdev, area->dx, area->dy, area->width,
                         area->height);
 }
@@ -116,7 +116,7 @@ static void cirrus_imageblit(struct fb_info *info,
                          const struct fb_image *image)
 {
        struct cirrus_fbdev *afbdev = info->par;
-       sys_imageblit(info, image);
+       drm_fb_helper_sys_imageblit(info, image);
        cirrus_dirty_update(afbdev, image->dx, image->dy, image->width,
                         image->height);
 }
@@ -165,12 +165,10 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
 {
        struct cirrus_fbdev *gfbdev =
                container_of(helper, struct cirrus_fbdev, helper);
-       struct drm_device *dev = gfbdev->helper.dev;
        struct cirrus_device *cdev = gfbdev->helper.dev->dev_private;
        struct fb_info *info;
        struct drm_framebuffer *fb;
        struct drm_mode_fb_cmd2 mode_cmd;
-       struct device *device = &dev->pdev->dev;
        void *sysram;
        struct drm_gem_object *gobj = NULL;
        struct cirrus_bo *bo = NULL;
@@ -195,9 +193,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
        if (!sysram)
                return -ENOMEM;
 
-       info = framebuffer_alloc(0, device);
-       if (info == NULL)
-               return -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info))
+               return PTR_ERR(info);
 
        info->par = gfbdev;
 
@@ -216,11 +214,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
 
        /* setup helper */
        gfbdev->helper.fb = fb;
-       gfbdev->helper.fbdev = info;
 
        strcpy(info->fix.id, "cirrusdrmfb");
 
-
        info->flags = FBINFO_DEFAULT;
        info->fbops = &cirrusfb_ops;
 
@@ -229,11 +225,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
                               sizes->fb_height);
 
        /* setup aperture base/size for vesafb takeover */
-       info->apertures = alloc_apertures(1);
-       if (!info->apertures) {
-               ret = -ENOMEM;
-               goto out_iounmap;
-       }
        info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
        info->apertures->ranges[0].size = cdev->mc.vram_size;
 
@@ -246,13 +237,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
        info->fix.mmio_start = 0;
        info->fix.mmio_len = 0;
 
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
-               ret = -ENOMEM;
-               goto out_iounmap;
-       }
-
        DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
        DRM_INFO("vram aper at 0x%lX\n", (unsigned long)info->fix.smem_start);
        DRM_INFO("size %lu\n", (unsigned long)info->fix.smem_len);
@@ -260,24 +244,15 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
        DRM_INFO("   pitch is %d\n", fb->pitches[0]);
 
        return 0;
-out_iounmap:
-       return ret;
 }
 
 static int cirrus_fbdev_destroy(struct drm_device *dev,
                                struct cirrus_fbdev *gfbdev)
 {
-       struct fb_info *info;
        struct cirrus_framebuffer *gfb = &gfbdev->gfb;
 
-       if (gfbdev->helper.fbdev) {
-               info = gfbdev->helper.fbdev;
-
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&gfbdev->helper);
+       drm_fb_helper_release_fbi(&gfbdev->helper);
 
        if (gfb->obj) {
                drm_gem_object_unreference_unlocked(gfb->obj);
index e4b976658087100304cd76f66330c16b9dcb7271..055fd86ba717d3283c71fbefe398b257ec8e1c20 100644 (file)
@@ -293,25 +293,18 @@ cirrus_dumb_mmap_offset(struct drm_file *file,
                     uint64_t *offset)
 {
        struct drm_gem_object *obj;
-       int ret;
        struct cirrus_bo *bo;
 
-       mutex_lock(&dev->struct_mutex);
        obj = drm_gem_object_lookup(dev, file, handle);
-       if (obj == NULL) {
-               ret = -ENOENT;
-               goto out_unlock;
-       }
+       if (obj == NULL)
+               return -ENOENT;
 
        bo = gem_to_cirrus_bo(obj);
        *offset = cirrus_bo_mmap_offset(bo);
 
-       drm_gem_object_unreference(obj);
-       ret = 0;
-out_unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
+       drm_gem_object_unreference_unlocked(obj);
 
+       return 0;
 }
 
 bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
index 3efd91c0c6cb07b542fcd82296269b41729cdcad..1066e4b658cf9a341c1955fb34f82040a4be909c 100644 (file)
@@ -153,9 +153,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
                if (!connector)
                        continue;
 
-               WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
-
-               connector->funcs->atomic_destroy_state(connector,
+               /*
+                * FIXME: Async commits can race with connector unplugging and
+                * there's currently nothing that prevents cleanup up state for
+                * deleted connectors. As long as the callback doesn't look at
+                * the connector we'll be fine though, so make sure that's the
+                * case by setting all connector pointers to NULL.
+                */
+               state->connector_states[i]->connector = NULL;
+               connector->funcs->atomic_destroy_state(NULL,
                                                       state->connector_states[i]);
                state->connectors[i] = NULL;
                state->connector_states[i] = NULL;
@@ -1224,6 +1230,9 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
                }
        }
 
+       if (ret == 0)
+               ww_acquire_done(&state->acquire_ctx->ww_ctx);
+
        return ret;
 }
 EXPORT_SYMBOL(drm_atomic_check_only);
index 99656815641daaf3159ceae9515abe71f92712d9..52dbeedcdcc86d23a51de7b75d6d91c393421cb5 100644 (file)
@@ -124,7 +124,7 @@ steal_encoder(struct drm_atomic_state *state,
        if (IS_ERR(crtc_state))
                return PTR_ERR(crtc_state);
 
-       crtc_state->mode_changed = true;
+       crtc_state->connectors_changed = true;
 
        list_for_each_entry(connector, &config->connector_list, head) {
                if (connector->state->best_encoder != encoder)
@@ -174,14 +174,14 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
                        idx = drm_crtc_index(connector->state->crtc);
 
                        crtc_state = state->crtc_states[idx];
-                       crtc_state->mode_changed = true;
+                       crtc_state->connectors_changed = true;
                }
 
                if (connector_state->crtc) {
                        idx = drm_crtc_index(connector_state->crtc);
 
                        crtc_state = state->crtc_states[idx];
-                       crtc_state->mode_changed = true;
+                       crtc_state->connectors_changed = true;
                }
        }
 
@@ -233,7 +233,7 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
        idx = drm_crtc_index(connector_state->crtc);
 
        crtc_state = state->crtc_states[idx];
-       crtc_state->mode_changed = true;
+       crtc_state->connectors_changed = true;
 
        DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n",
                         connector->base.id,
@@ -256,7 +256,8 @@ mode_fixup(struct drm_atomic_state *state)
        bool ret;
 
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
-               if (!crtc_state->mode_changed)
+               if (!crtc_state->mode_changed &&
+                   !crtc_state->connectors_changed)
                        continue;
 
                drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode);
@@ -298,7 +299,7 @@ mode_fixup(struct drm_atomic_state *state)
                                                 encoder->base.id, encoder->name);
                                return ret;
                        }
-               } else {
+               } else if (funcs->mode_fixup) {
                        ret = funcs->mode_fixup(encoder, &crtc_state->mode,
                                                &crtc_state->adjusted_mode);
                        if (!ret) {
@@ -312,7 +313,8 @@ mode_fixup(struct drm_atomic_state *state)
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
                const struct drm_crtc_helper_funcs *funcs;
 
-               if (!crtc_state->mode_changed)
+               if (!crtc_state->mode_changed &&
+                   !crtc_state->connectors_changed)
                        continue;
 
                funcs = crtc->helper_private;
@@ -338,9 +340,14 @@ mode_fixup(struct drm_atomic_state *state)
  *
  * Check the state object to see if the requested state is physically possible.
  * This does all the crtc and connector related computations for an atomic
- * update. It computes and updates crtc_state->mode_changed, adds any additional
- * connectors needed for full modesets and calls down into ->mode_fixup
- * functions of the driver backend.
+ * update and adds any additional connectors needed for full modesets and calls
+ * down into ->mode_fixup functions of the driver backend.
+ *
+ * crtc_state->mode_changed is set when the input mode is changed.
+ * crtc_state->connectors_changed is set when a connector is added or
+ * removed from the crtc.
+ * crtc_state->active_changed is set when crtc_state->active changes,
+ * which is used for dpms.
  *
  * IMPORTANT:
  *
@@ -373,7 +380,17 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
                if (crtc->state->enable != crtc_state->enable) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d] enable changed\n",
                                         crtc->base.id);
+
+                       /*
+                        * For clarity this assignment is done here, but
+                        * enable == 0 is only true when there are no
+                        * connectors and a NULL mode.
+                        *
+                        * The other way around is true as well. enable != 0
+                        * iff connectors are attached and a mode is set.
+                        */
                        crtc_state->mode_changed = true;
+                       crtc_state->connectors_changed = true;
                }
        }
 
@@ -448,6 +465,9 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
  * This does all the plane update related checks using by calling into the
  * ->atomic_check hooks provided by the driver.
  *
+ * It also sets crtc_state->planes_changed to indicate that a crtc has
+ * updated planes.
+ *
  * RETURNS
  * Zero for success or -errno
  */
@@ -640,15 +660,29 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
        struct drm_crtc_state *old_crtc_state;
        int i;
 
-       /* clear out existing links */
+       /* clear out existing links and update dpms */
        for_each_connector_in_state(old_state, connector, old_conn_state, i) {
-               if (!connector->encoder)
-                       continue;
+               if (connector->encoder) {
+                       WARN_ON(!connector->encoder->crtc);
 
-               WARN_ON(!connector->encoder->crtc);
+                       connector->encoder->crtc = NULL;
+                       connector->encoder = NULL;
+               }
 
-               connector->encoder->crtc = NULL;
-               connector->encoder = NULL;
+               crtc = connector->state->crtc;
+               if ((!crtc && old_conn_state->crtc) ||
+                   (crtc && drm_atomic_crtc_needs_modeset(crtc->state))) {
+                       struct drm_property *dpms_prop =
+                               dev->mode_config.dpms_property;
+                       int mode = DRM_MODE_DPMS_OFF;
+
+                       if (crtc && crtc->state->active)
+                               mode = DRM_MODE_DPMS_ON;
+
+                       connector->dpms = mode;
+                       drm_object_property_set_value(&connector->base,
+                                                     dpms_prop, mode);
+               }
        }
 
        /* set new links */
@@ -924,7 +958,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
                        continue;
 
                old_crtc_state->enable = true;
-               old_crtc_state->last_vblank_count = drm_vblank_count(dev, i);
+               old_crtc_state->last_vblank_count = drm_crtc_vblank_count(crtc);
        }
 
        for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
@@ -933,7 +967,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
 
                ret = wait_event_timeout(dev->vblank[i].queue,
                                old_crtc_state->last_vblank_count !=
-                                       drm_vblank_count(dev, i),
+                                       drm_crtc_vblank_count(crtc),
                                msecs_to_jiffies(50));
 
                drm_crtc_vblank_put(crtc);
@@ -1144,7 +1178,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
                if (!funcs || !funcs->atomic_begin)
                        continue;
 
-               funcs->atomic_begin(crtc);
+               funcs->atomic_begin(crtc, old_crtc_state);
        }
 
        for_each_plane_in_state(old_state, plane, old_plane_state, i) {
@@ -1174,7 +1208,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
                if (!funcs || !funcs->atomic_flush)
                        continue;
 
-               funcs->atomic_flush(crtc);
+               funcs->atomic_flush(crtc, old_crtc_state);
        }
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
@@ -1210,7 +1244,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)
 
        crtc_funcs = crtc->helper_private;
        if (crtc_funcs && crtc_funcs->atomic_begin)
-               crtc_funcs->atomic_begin(crtc);
+               crtc_funcs->atomic_begin(crtc, old_crtc_state);
 
        drm_for_each_plane_mask(plane, crtc->dev, plane_mask) {
                struct drm_plane_state *old_plane_state =
@@ -1233,7 +1267,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)
        }
 
        if (crtc_funcs && crtc_funcs->atomic_flush)
-               crtc_funcs->atomic_flush(crtc);
+               crtc_funcs->atomic_flush(crtc, old_crtc_state);
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc);
 
@@ -1954,9 +1988,12 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip);
  * implementing the legacy DPMS connector interface. It computes the new desired
  * ->active state for the corresponding CRTC (if the connector is enabled) and
  *  updates it.
+ *
+ * Returns:
+ * Returns 0 on success, negative errno numbers on failure.
  */
-void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
-                                     int mode)
+int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
+                                    int mode)
 {
        struct drm_mode_config *config = &connector->dev->mode_config;
        struct drm_atomic_state *state;
@@ -1965,6 +2002,7 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
        struct drm_connector *tmp_connector;
        int ret;
        bool active = false;
+       int old_mode = connector->dpms;
 
        if (mode != DRM_MODE_DPMS_ON)
                mode = DRM_MODE_DPMS_OFF;
@@ -1973,18 +2011,19 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
        crtc = connector->state->crtc;
 
        if (!crtc)
-               return;
+               return 0;
 
-       /* FIXME: ->dpms has no return value so can't forward the -ENOMEM. */
        state = drm_atomic_state_alloc(connector->dev);
        if (!state)
-               return;
+               return -ENOMEM;
 
        state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
 retry:
        crtc_state = drm_atomic_get_crtc_state(state, crtc);
-       if (IS_ERR(crtc_state))
-               return;
+       if (IS_ERR(crtc_state)) {
+               ret = PTR_ERR(crtc_state);
+               goto fail;
+       }
 
        WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
 
@@ -2003,17 +2042,16 @@ retry:
        if (ret != 0)
                goto fail;
 
-       /* Driver takes ownership of state on successful async commit. */
-       return;
+       /* Driver takes ownership of state on successful commit. */
+       return 0;
 fail:
        if (ret == -EDEADLK)
                goto backoff;
 
+       connector->dpms = old_mode;
        drm_atomic_state_free(state);
 
-       WARN(1, "Driver bug: Changing ->active failed with ret=%i\n", ret);
-
-       return;
+       return ret;
 backoff:
        drm_atomic_state_clear(state);
        drm_atomic_legacy_backoff(state);
@@ -2074,6 +2112,7 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
        state->mode_changed = false;
        state->active_changed = false;
        state->planes_changed = false;
+       state->connectors_changed = false;
        state->event = NULL;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
index 1f0da41ae2a150278ab2bc9de7fcf581285e3f08..21f1f5ce2d6006657051a418b9cb756c5307b350 100644 (file)
@@ -1151,7 +1151,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup);
 int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
                             unsigned long possible_crtcs,
                             const struct drm_plane_funcs *funcs,
-                            const uint32_t *formats, uint32_t format_count,
+                            const uint32_t *formats, unsigned int format_count,
                             enum drm_plane_type type)
 {
        struct drm_mode_config *config = &dev->mode_config;
@@ -1225,7 +1225,7 @@ EXPORT_SYMBOL(drm_universal_plane_init);
 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
                   unsigned long possible_crtcs,
                   const struct drm_plane_funcs *funcs,
-                  const uint32_t *formats, uint32_t format_count,
+                  const uint32_t *formats, unsigned int format_count,
                   bool is_primary)
 {
        enum drm_plane_type type;
@@ -4753,9 +4753,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
 
        /* Do DPMS ourselves */
        if (property == connector->dev->mode_config.dpms_property) {
-               if (connector->funcs->dpms)
-                       (*connector->funcs->dpms)(connector, (int)value);
                ret = 0;
+               if (connector->funcs->dpms)
+                       ret = (*connector->funcs->dpms)(connector, (int)value);
        } else if (connector->funcs->set_property)
                ret = connector->funcs->set_property(connector, property, value);
 
@@ -5273,12 +5273,14 @@ void drm_mode_config_reset(struct drm_device *dev)
                if (encoder->funcs->reset)
                        encoder->funcs->reset(encoder);
 
+       mutex_lock(&dev->mode_config.mutex);
        drm_for_each_connector(connector, dev) {
                connector->status = connector_status_unknown;
 
                if (connector->funcs->reset)
                        connector->funcs->reset(connector);
        }
+       mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_mode_config_reset);
 
index d3d038f05bf7f7ed2bd2d19e3a2db94ff33fe45f..ef534758a02c6f946061107aaa0262527c8a25fb 100644 (file)
@@ -762,15 +762,18 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
  * implementing the DPMS connector attribute. It computes the new desired DPMS
  * state for all encoders and crtcs in the output mesh and calls the ->dpms()
  * callback provided by the driver appropriately.
+ *
+ * Returns:
+ * Always returns 0.
  */
-void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
+int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
 {
        struct drm_encoder *encoder = connector->encoder;
        struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
        int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF;
 
        if (mode == connector->dpms)
-               return;
+               return 0;
 
        old_dpms = connector->dpms;
        connector->dpms = mode;
@@ -802,7 +805,7 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
                }
        }
 
-       return;
+       return 0;
 }
 EXPORT_SYMBOL(drm_helper_connector_dpms);
 
index e6e05bb75a7715f71d894962ed435e36c9667dc8..05bb7311ac5d151a1893b3802e333f28c8707df4 100644 (file)
@@ -3802,7 +3802,7 @@ int drm_add_modes_noedid(struct drm_connector *connector,
        struct drm_display_mode *mode;
        struct drm_device *dev = connector->dev;
 
-       count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
+       count = ARRAY_SIZE(drm_dmt_modes);
        if (hdisplay < 0)
                hdisplay = 0;
        if (vdisplay < 0)
index f01dc25df2dcb61477f9cb4bbb6537516dda2b58..c19a62561183537046dc896254d09d4ac3a70b1e 100644 (file)
@@ -222,9 +222,9 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show);
 
 static struct fb_ops drm_fbdev_cma_ops = {
        .owner          = THIS_MODULE,
-       .fb_fillrect    = sys_fillrect,
-       .fb_copyarea    = sys_copyarea,
-       .fb_imageblit   = sys_imageblit,
+       .fb_fillrect    = drm_fb_helper_sys_fillrect,
+       .fb_copyarea    = drm_fb_helper_sys_copyarea,
+       .fb_imageblit   = drm_fb_helper_sys_imageblit,
        .fb_check_var   = drm_fb_helper_check_var,
        .fb_set_par     = drm_fb_helper_set_par,
        .fb_blank       = drm_fb_helper_blank,
@@ -263,10 +263,9 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
        if (IS_ERR(obj))
                return -ENOMEM;
 
-       fbi = framebuffer_alloc(0, dev->dev);
-       if (!fbi) {
-               dev_err(dev->dev, "Failed to allocate framebuffer info.\n");
-               ret = -ENOMEM;
+       fbi = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(fbi)) {
+               ret = PTR_ERR(fbi);
                goto err_drm_gem_cma_free_object;
        }
 
@@ -274,23 +273,16 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
        if (IS_ERR(fbdev_cma->fb)) {
                dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
                ret = PTR_ERR(fbdev_cma->fb);
-               goto err_framebuffer_release;
+               goto err_fb_info_destroy;
        }
 
        fb = &fbdev_cma->fb->fb;
        helper->fb = fb;
-       helper->fbdev = fbi;
 
        fbi->par = helper;
        fbi->flags = FBINFO_FLAG_DEFAULT;
        fbi->fbops = &drm_fbdev_cma_ops;
 
-       ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
-       if (ret) {
-               dev_err(dev->dev, "Failed to allocate color map.\n");
-               goto err_drm_fb_cma_destroy;
-       }
-
        drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
 
@@ -305,11 +297,8 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
 
        return 0;
 
-err_drm_fb_cma_destroy:
-       drm_framebuffer_unregister_private(fb);
-       drm_fb_cma_destroy(fb);
-err_framebuffer_release:
-       framebuffer_release(fbi);
+err_fb_info_destroy:
+       drm_fb_helper_release_fbi(helper);
 err_drm_gem_cma_free_object:
        drm_gem_cma_free_object(&obj->base);
        return ret;
@@ -385,20 +374,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
  */
 void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
 {
-       if (fbdev_cma->fb_helper.fbdev) {
-               struct fb_info *info;
-               int ret;
-
-               info = fbdev_cma->fb_helper.fbdev;
-               ret = unregister_framebuffer(info);
-               if (ret < 0)
-                       DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
-
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
+       drm_fb_helper_release_fbi(&fbdev_cma->fb_helper);
 
        if (fbdev_cma->fb) {
                drm_framebuffer_unregister_private(&fbdev_cma->fb->fb);
index 73f90f7e2f74407d2b346ce8d37f410624459314..418d299f3b129b307f86a970fdf49d3a826af4c8 100644 (file)
@@ -56,8 +56,8 @@ static LIST_HEAD(kernel_fb_helper_list);
  * Teardown is done with drm_fb_helper_fini().
  *
  * At runtime drivers should restore the fbdev console by calling
- * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
- * should also notify the fb helper code from updates to the output
+ * drm_fb_helper_restore_fbdev_mode_unlocked() from their ->lastclose callback.
+ * They should also notify the fb helper code from updates to the output
  * configuration by calling drm_fb_helper_hotplug_event(). For easier
  * integration with the output polling code in drm_crtc_helper.c the modeset
  * code provides a ->output_poll_changed callback.
@@ -168,11 +168,14 @@ static void remove_from_modeset(struct drm_mode_set *set,
        }
        set->num_connectors--;
 
-       /* because i915 is pissy about this..
+       /*
         * TODO maybe need to makes sure we set it back to !=NULL somewhere?
         */
-       if (set->num_connectors == 0)
+       if (set->num_connectors == 0) {
                set->fb = NULL;
+               drm_mode_destroy(connector->dev, set->mode);
+               set->mode = NULL;
+       }
 }
 
 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
@@ -354,21 +357,6 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
        }
        return error;
 }
-/**
- * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
- * @fb_helper: fbcon to restore
- *
- * This should be called from driver's drm ->lastclose callback
- * when implementing an fbcon on top of kms using this helper. This ensures that
- * the user isn't greeted with a black screen when e.g. X dies.
- *
- * Use this variant if you need to bypass locking (panic), or already
- * hold all modeset locks.  Otherwise use drm_fb_helper_restore_fbdev_mode_unlocked()
- */
-static bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
-{
-       return restore_fbdev_mode(fb_helper);
-}
 
 /**
  * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
@@ -398,42 +386,6 @@ bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
 }
 EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
 
-/*
- * restore fbcon display for all kms driver's using this helper, used for sysrq
- * and panic handling.
- */
-static bool drm_fb_helper_force_kernel_mode(void)
-{
-       bool ret, error = false;
-       struct drm_fb_helper *helper;
-
-       if (list_empty(&kernel_fb_helper_list))
-               return false;
-
-       list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
-               struct drm_device *dev = helper->dev;
-
-               if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
-                       continue;
-
-               /*
-                * NOTE: Use trylock mode to avoid deadlocks and sleeping in
-                * panic context.
-                */
-               if (__drm_modeset_lock_all(dev, true) != 0) {
-                       error = true;
-                       continue;
-               }
-
-               ret = drm_fb_helper_restore_fbdev_mode(helper);
-               if (ret)
-                       error = true;
-
-               drm_modeset_unlock_all(dev);
-       }
-       return error;
-}
-
 static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
 {
        struct drm_device *dev = fb_helper->dev;
@@ -459,6 +411,33 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
 }
 
 #ifdef CONFIG_MAGIC_SYSRQ
+/*
+ * restore fbcon display for all kms driver's using this helper, used for sysrq
+ * and panic handling.
+ */
+static bool drm_fb_helper_force_kernel_mode(void)
+{
+       bool ret, error = false;
+       struct drm_fb_helper *helper;
+
+       if (list_empty(&kernel_fb_helper_list))
+               return false;
+
+       list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
+               struct drm_device *dev = helper->dev;
+
+               if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+                       continue;
+
+               drm_modeset_lock_all(dev);
+               ret = restore_fbdev_mode(helper);
+               if (ret)
+                       error = true;
+               drm_modeset_unlock_all(dev);
+       }
+       return error;
+}
+
 static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
 {
        bool ret;
@@ -490,14 +469,6 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
        struct drm_connector *connector;
        int i, j;
 
-       /*
-        * fbdev->blank can be called from irq context in case of a panic.
-        * Since we already have our own special panic handler which will
-        * restore the fbdev console mode completely, just bail out early.
-        */
-       if (oops_in_progress)
-               return;
-
        /*
         * For each CRTC in this fb, turn the connectors on/off.
         */
@@ -531,6 +502,9 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
  */
 int drm_fb_helper_blank(int blank, struct fb_info *info)
 {
+       if (oops_in_progress)
+               return -EBUSY;
+
        switch (blank) {
        /* Display: On; HSync: On, VSync: On */
        case FB_BLANK_UNBLANK:
@@ -654,6 +628,86 @@ out_free:
 }
 EXPORT_SYMBOL(drm_fb_helper_init);
 
+/**
+ * drm_fb_helper_alloc_fbi - allocate fb_info and some of its members
+ * @fb_helper: driver-allocated fbdev helper
+ *
+ * A helper to alloc fb_info and the members cmap and apertures. Called
+ * by the driver within the fb_probe fb_helper callback function.
+ *
+ * RETURNS:
+ * fb_info pointer if things went okay, pointer containing error code
+ * otherwise
+ */
+struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
+{
+       struct device *dev = fb_helper->dev->dev;
+       struct fb_info *info;
+       int ret;
+
+       info = framebuffer_alloc(0, dev);
+       if (!info)
+               return ERR_PTR(-ENOMEM);
+
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (ret)
+               goto err_release;
+
+       info->apertures = alloc_apertures(1);
+       if (!info->apertures) {
+               ret = -ENOMEM;
+               goto err_free_cmap;
+       }
+
+       fb_helper->fbdev = info;
+
+       return info;
+
+err_free_cmap:
+       fb_dealloc_cmap(&info->cmap);
+err_release:
+       framebuffer_release(info);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
+
+/**
+ * drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
+ * @fb_helper: driver-allocated fbdev helper
+ *
+ * A wrapper around unregister_framebuffer, to release the fb_info
+ * framebuffer device
+ */
+void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
+{
+       if (fb_helper && fb_helper->fbdev)
+               unregister_framebuffer(fb_helper->fbdev);
+}
+EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
+
+/**
+ * drm_fb_helper_release_fbi - dealloc fb_info and its members
+ * @fb_helper: driver-allocated fbdev helper
+ *
+ * A helper to free memory taken by fb_info and the members cmap and
+ * apertures
+ */
+void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper)
+{
+       if (fb_helper) {
+               struct fb_info *info = fb_helper->fbdev;
+
+               if (info) {
+                       if (info->cmap.len)
+                               fb_dealloc_cmap(&info->cmap);
+                       framebuffer_release(info);
+               }
+
+               fb_helper->fbdev = NULL;
+       }
+}
+EXPORT_SYMBOL(drm_fb_helper_release_fbi);
+
 void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
 {
        if (!list_empty(&fb_helper->kernel_fb_list)) {
@@ -668,6 +722,149 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
 }
 EXPORT_SYMBOL(drm_fb_helper_fini);
 
+/**
+ * drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer
+ * @fb_helper: driver-allocated fbdev helper
+ *
+ * A wrapper around unlink_framebuffer implemented by fbdev core
+ */
+void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
+{
+       if (fb_helper && fb_helper->fbdev)
+               unlink_framebuffer(fb_helper->fbdev);
+}
+EXPORT_SYMBOL(drm_fb_helper_unlink_fbi);
+
+/**
+ * drm_fb_helper_sys_read - wrapper around fb_sys_read
+ * @info: fb_info struct pointer
+ * @buf: userspace buffer to read from framebuffer memory
+ * @count: number of bytes to read from framebuffer memory
+ * @ppos: read offset within framebuffer memory
+ *
+ * A wrapper around fb_sys_read implemented by fbdev core
+ */
+ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
+                              size_t count, loff_t *ppos)
+{
+       return fb_sys_read(info, buf, count, ppos);
+}
+EXPORT_SYMBOL(drm_fb_helper_sys_read);
+
+/**
+ * drm_fb_helper_sys_write - wrapper around fb_sys_write
+ * @info: fb_info struct pointer
+ * @buf: userspace buffer to write to framebuffer memory
+ * @count: number of bytes to write to framebuffer memory
+ * @ppos: write offset within framebuffer memory
+ *
+ * A wrapper around fb_sys_write implemented by fbdev core
+ */
+ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       return fb_sys_write(info, buf, count, ppos);
+}
+EXPORT_SYMBOL(drm_fb_helper_sys_write);
+
+/**
+ * drm_fb_helper_sys_fillrect - wrapper around sys_fillrect
+ * @info: fbdev registered by the helper
+ * @rect: info about rectangle to fill
+ *
+ * A wrapper around sys_fillrect implemented by fbdev core
+ */
+void drm_fb_helper_sys_fillrect(struct fb_info *info,
+                               const struct fb_fillrect *rect)
+{
+       sys_fillrect(info, rect);
+}
+EXPORT_SYMBOL(drm_fb_helper_sys_fillrect);
+
+/**
+ * drm_fb_helper_sys_copyarea - wrapper around sys_copyarea
+ * @info: fbdev registered by the helper
+ * @area: info about area to copy
+ *
+ * A wrapper around sys_copyarea implemented by fbdev core
+ */
+void drm_fb_helper_sys_copyarea(struct fb_info *info,
+                               const struct fb_copyarea *area)
+{
+       sys_copyarea(info, area);
+}
+EXPORT_SYMBOL(drm_fb_helper_sys_copyarea);
+
+/**
+ * drm_fb_helper_sys_imageblit - wrapper around sys_imageblit
+ * @info: fbdev registered by the helper
+ * @image: info about image to blit
+ *
+ * A wrapper around sys_imageblit implemented by fbdev core
+ */
+void drm_fb_helper_sys_imageblit(struct fb_info *info,
+                                const struct fb_image *image)
+{
+       sys_imageblit(info, image);
+}
+EXPORT_SYMBOL(drm_fb_helper_sys_imageblit);
+
+/**
+ * drm_fb_helper_cfb_fillrect - wrapper around cfb_fillrect
+ * @info: fbdev registered by the helper
+ * @rect: info about rectangle to fill
+ *
+ * A wrapper around cfb_imageblit implemented by fbdev core
+ */
+void drm_fb_helper_cfb_fillrect(struct fb_info *info,
+                               const struct fb_fillrect *rect)
+{
+       cfb_fillrect(info, rect);
+}
+EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect);
+
+/**
+ * drm_fb_helper_cfb_copyarea - wrapper around cfb_copyarea
+ * @info: fbdev registered by the helper
+ * @area: info about area to copy
+ *
+ * A wrapper around cfb_copyarea implemented by fbdev core
+ */
+void drm_fb_helper_cfb_copyarea(struct fb_info *info,
+                               const struct fb_copyarea *area)
+{
+       cfb_copyarea(info, area);
+}
+EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea);
+
+/**
+ * drm_fb_helper_cfb_imageblit - wrapper around cfb_imageblit
+ * @info: fbdev registered by the helper
+ * @image: info about image to blit
+ *
+ * A wrapper around cfb_imageblit implemented by fbdev core
+ */
+void drm_fb_helper_cfb_imageblit(struct fb_info *info,
+                                const struct fb_image *image)
+{
+       cfb_imageblit(info, image);
+}
+EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
+
+/**
+ * drm_fb_helper_set_suspend - wrapper around fb_set_suspend
+ * @fb_helper: driver-allocated fbdev helper
+ * @state: desired state, zero to resume, non-zero to suspend
+ *
+ * A wrapper around fb_set_suspend implemented by fbdev core
+ */
+void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state)
+{
+       if (fb_helper && fb_helper->fbdev)
+               fb_set_suspend(fb_helper->fbdev, state);
+}
+EXPORT_SYMBOL(drm_fb_helper_set_suspend);
+
 static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
                     u16 blue, u16 regno, struct fb_info *info)
 {
@@ -755,9 +952,10 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
        int i, j, rc = 0;
        int start;
 
-       if (__drm_modeset_lock_all(dev, !!oops_in_progress)) {
+       if (oops_in_progress)
                return -EBUSY;
-       }
+
+       drm_modeset_lock_all(dev);
        if (!drm_fb_helper_is_bound(fb_helper)) {
                drm_modeset_unlock_all(dev);
                return -EBUSY;
@@ -906,6 +1104,9 @@ int drm_fb_helper_set_par(struct fb_info *info)
        struct drm_fb_helper *fb_helper = info->par;
        struct fb_var_screeninfo *var = &info->var;
 
+       if (oops_in_progress)
+               return -EBUSY;
+
        if (var->pixclock != 0) {
                DRM_ERROR("PIXEL CLOCK SET\n");
                return -EINVAL;
@@ -931,9 +1132,10 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
        int ret = 0;
        int i;
 
-       if (__drm_modeset_lock_all(dev, !!oops_in_progress)) {
+       if (oops_in_progress)
                return -EBUSY;
-       }
+
+       drm_modeset_lock_all(dev);
        if (!drm_fb_helper_is_bound(fb_helper)) {
                drm_modeset_unlock_all(dev);
                return -EBUSY;
index 27a4228b43431b05da2fcd3138a9c33ab861d73a..3c2d4abd71c5eb3a82b204f28d8455ddb94a6add 100644 (file)
@@ -766,7 +766,7 @@ drm_gem_object_free(struct kref *kref)
        struct drm_gem_object *obj = (struct drm_gem_object *) kref;
        struct drm_device *dev = obj->dev;
 
-       BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
        if (dev->driver->gem_free_object != NULL)
                dev->driver->gem_free_object(obj);
index 9edad11dca9852f551138b180b4eddbdc32038f2..86cc793cdf79d154b2caad7eb42a99e595812954 100644 (file)
@@ -289,20 +289,15 @@ int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv,
 {
        struct drm_gem_object *gem_obj;
 
-       mutex_lock(&drm->struct_mutex);
-
        gem_obj = drm_gem_object_lookup(drm, file_priv, handle);
        if (!gem_obj) {
                dev_err(drm->dev, "failed to lookup GEM object\n");
-               mutex_unlock(&drm->struct_mutex);
                return -EINVAL;
        }
 
        *offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
 
-       drm_gem_object_unreference(gem_obj);
-
-       mutex_unlock(&drm->struct_mutex);
+       drm_gem_object_unreference_unlocked(gem_obj);
 
        return 0;
 }
index 9fd784b8966b9743ff29ce5fa3defbf92b292caf..05b939e8da416aff02d7ce7846e08591751fac41 100644 (file)
@@ -43,8 +43,8 @@
 #include <linux/export.h>
 
 /* Access macro for slots in vblank timestamp ringbuffer. */
-#define vblanktimestamp(dev, crtc, count) \
-       ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE])
+#define vblanktimestamp(dev, pipe, count) \
+       ((dev)->vblank[pipe].time[(count) % DRM_VBLANKTIME_RBSIZE])
 
 /* Retry timestamp calculation up to 3 times to satisfy
  * drm_timestamp_precision before giving up.
@@ -57,7 +57,7 @@
 #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
 
 static bool
-drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
+drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
                          struct timeval *tvblank, unsigned flags);
 
 static unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
@@ -107,7 +107,7 @@ static void store_vblank(struct drm_device *dev, int crtc,
 /**
  * drm_update_vblank_count - update the master vblank counter
  * @dev: DRM device
- * @crtc: counter to update
+ * @pipe: counter to update
  *
  * Call back into the driver to update the appropriate vblank counter
  * (specified by @crtc).  Deal with wraparound, if it occurred, and
@@ -120,9 +120,9 @@ static void store_vblank(struct drm_device *dev, int crtc,
  * Note: caller must hold dev->vbl_lock since this reads & writes
  * device vblank fields.
  */
-static void drm_update_vblank_count(struct drm_device *dev, int crtc)
+static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        u32 cur_vblank, diff;
        bool rc;
        struct timeval t_vblank;
@@ -140,21 +140,21 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
         * corresponding vblank timestamp.
         */
        do {
-               cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
-               rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0);
-       } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc));
+               cur_vblank = dev->driver->get_vblank_counter(dev, pipe);
+               rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0);
+       } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe));
 
        /* Deal with counter wrap */
        diff = cur_vblank - vblank->last;
        if (cur_vblank < vblank->last) {
                diff += dev->max_vblank_count + 1;
 
-               DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
-                         crtc, vblank->last, cur_vblank, diff);
+               DRM_DEBUG("last_vblank[%u]=0x%x, cur_vblank=0x%x => diff=0x%x\n",
+                         pipe, vblank->last, cur_vblank, diff);
        }
 
-       DRM_DEBUG("updating vblank count on crtc %d, missed %d\n",
-                 crtc, diff);
+       DRM_DEBUG("updating vblank count on crtc %u, missed %d\n",
+                 pipe, diff);
 
        if (diff == 0)
                return;
@@ -167,7 +167,7 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
        if (!rc)
                t_vblank = (struct timeval) {0, 0};
 
-       store_vblank(dev, crtc, diff, &t_vblank);
+       store_vblank(dev, pipe, diff, &t_vblank);
 }
 
 /*
@@ -176,9 +176,9 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
  * are preserved, even if there are any spurious vblank irq's after
  * disable.
  */
-static void vblank_disable_and_save(struct drm_device *dev, int crtc)
+static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        unsigned long irqflags;
        u32 vblcount;
        s64 diff_ns;
@@ -206,8 +206,8 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
         * vblank interrupt is disabled.
         */
        if (!vblank->enabled &&
-           drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0)) {
-               drm_update_vblank_count(dev, crtc);
+           drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0)) {
+               drm_update_vblank_count(dev, pipe);
                spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
                return;
        }
@@ -218,7 +218,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
         * hardware potentially runtime suspended.
         */
        if (vblank->enabled) {
-               dev->driver->disable_vblank(dev, crtc);
+               dev->driver->disable_vblank(dev, pipe);
                vblank->enabled = false;
        }
 
@@ -235,9 +235,9 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
         * delayed gpu counter increment.
         */
        do {
-               vblank->last = dev->driver->get_vblank_counter(dev, crtc);
-               vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0);
-       } while (vblank->last != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc);
+               vblank->last = dev->driver->get_vblank_counter(dev, pipe);
+               vblrc = drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0);
+       } while (vblank->last != dev->driver->get_vblank_counter(dev, pipe) && (--count) && vblrc);
 
        if (!count)
                vblrc = 0;
@@ -247,7 +247,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
         */
        vblcount = vblank->count;
        diff_ns = timeval_to_ns(&tvblank) -
-                 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
+                 timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount));
 
        /* If there is at least 1 msec difference between the last stored
         * timestamp and tvblank, then we are currently executing our
@@ -262,7 +262,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
         * hope for the best.
         */
        if (vblrc && (abs64(diff_ns) > 1000000))
-               store_vblank(dev, crtc, 1, &tvblank);
+               store_vblank(dev, pipe, 1, &tvblank);
 
        spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
 }
@@ -271,16 +271,16 @@ static void vblank_disable_fn(unsigned long arg)
 {
        struct drm_vblank_crtc *vblank = (void *)arg;
        struct drm_device *dev = vblank->dev;
+       unsigned int pipe = vblank->pipe;
        unsigned long irqflags;
-       int crtc = vblank->crtc;
 
        if (!dev->vblank_disable_allowed)
                return;
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) {
-               DRM_DEBUG("disabling vblank on crtc %d\n", crtc);
-               vblank_disable_and_save(dev, crtc);
+               DRM_DEBUG("disabling vblank on crtc %u\n", pipe);
+               vblank_disable_and_save(dev, pipe);
        }
        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
@@ -293,14 +293,14 @@ static void vblank_disable_fn(unsigned long arg)
  */
 void drm_vblank_cleanup(struct drm_device *dev)
 {
-       int crtc;
+       unsigned int pipe;
 
        /* Bail if the driver didn't call drm_vblank_init() */
        if (dev->num_crtcs == 0)
                return;
 
-       for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
-               struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       for (pipe = 0; pipe < dev->num_crtcs; pipe++) {
+               struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 
                WARN_ON(vblank->enabled &&
                        drm_core_check_feature(dev, DRIVER_MODESET));
@@ -316,17 +316,18 @@ EXPORT_SYMBOL(drm_vblank_cleanup);
 
 /**
  * drm_vblank_init - initialize vblank support
- * @dev: drm_device
- * @num_crtcs: number of crtcs supported by @dev
+ * @dev: DRM device
+ * @num_crtcs: number of CRTCs supported by @dev
  *
  * This function initializes vblank support for @num_crtcs display pipelines.
  *
  * Returns:
  * Zero on success or a negative error code on failure.
  */
-int drm_vblank_init(struct drm_device *dev, int num_crtcs)
+int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)
 {
-       int i, ret = -ENOMEM;
+       int ret = -ENOMEM;
+       unsigned int i;
 
        spin_lock_init(&dev->vbl_lock);
        spin_lock_init(&dev->vblank_time_lock);
@@ -341,7 +342,7 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
                struct drm_vblank_crtc *vblank = &dev->vblank[i];
 
                vblank->dev = dev;
-               vblank->crtc = i;
+               vblank->pipe = i;
                init_waitqueue_head(&vblank->queue);
                setup_timer(&vblank->disable_timer, vblank_disable_fn,
                            (unsigned long)vblank);
@@ -624,17 +625,17 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
                if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                        framedur_ns /= 2;
        } else
-               DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n",
+               DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n",
                          crtc->base.id);
 
        crtc->pixeldur_ns = pixeldur_ns;
        crtc->linedur_ns  = linedur_ns;
        crtc->framedur_ns = framedur_ns;
 
-       DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
+       DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
                  crtc->base.id, mode->crtc_htotal,
                  mode->crtc_vtotal, mode->crtc_vdisplay);
-       DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
+       DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
                  crtc->base.id, dotclock, framedur_ns,
                  linedur_ns, pixeldur_ns);
 }
@@ -643,7 +644,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
 /**
  * drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper
  * @dev: DRM device
- * @crtc: Which CRTC's vblank timestamp to retrieve
+ * @pipe: index of CRTC whose vblank timestamp to retrieve
  * @max_error: Desired maximum allowable error in timestamps (nanosecs)
  *             On return contains true maximum error of timestamp
  * @vblank_time: Pointer to struct timeval which should receive the timestamp
@@ -686,7 +687,8 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
  * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
  *
  */
-int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
+int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
+                                         unsigned int pipe,
                                          int *max_error,
                                          struct timeval *vblank_time,
                                          unsigned flags,
@@ -700,8 +702,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
        int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
        bool invbl;
 
-       if (crtc < 0 || crtc >= dev->num_crtcs) {
-               DRM_ERROR("Invalid crtc %d\n", crtc);
+       if (pipe >= dev->num_crtcs) {
+               DRM_ERROR("Invalid crtc %u\n", pipe);
                return -EINVAL;
        }
 
@@ -720,7 +722,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
         * Happens during initial modesetting of a crtc.
         */
        if (framedur_ns == 0) {
-               DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc);
+               DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe);
                return -EAGAIN;
        }
 
@@ -736,13 +738,13 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                 * Get vertical and horizontal scanout position vpos, hpos,
                 * and bounding timestamps stime, etime, pre/post query.
                 */
-               vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos,
+               vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, &vpos,
                                                               &hpos, &stime, &etime);
 
                /* Return as no-op if scanout query unsupported or failed. */
                if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
-                       DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n",
-                                 crtc, vbl_status);
+                       DRM_DEBUG("crtc %u : scanoutpos query failed [%d].\n",
+                                 pipe, vbl_status);
                        return -EIO;
                }
 
@@ -756,8 +758,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
 
        /* Noisy system timing? */
        if (i == DRM_TIMESTAMP_MAXRETRIES) {
-               DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n",
-                         crtc, duration_ns/1000, *max_error/1000, i);
+               DRM_DEBUG("crtc %u: Noisy timestamp %d us > %d us [%d reps].\n",
+                         pipe, duration_ns/1000, *max_error/1000, i);
        }
 
        /* Return upper bound of timestamp precision error. */
@@ -790,8 +792,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                etime = ktime_sub_ns(etime, delta_ns);
        *vblank_time = ktime_to_timeval(etime);
 
-       DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
-                 crtc, (int)vbl_status, hpos, vpos,
+       DRM_DEBUG("crtc %u : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
+                 pipe, (int)vbl_status, hpos, vpos,
                  (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
                  (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
                  duration_ns/1000, i);
@@ -816,7 +818,7 @@ static struct timeval get_drm_timestamp(void)
  * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
  *                             vblank interval
  * @dev: DRM device
- * @crtc: which CRTC's vblank timestamp to retrieve
+ * @pipe: index of CRTC whose vblank timestamp to retrieve
  * @tvblank: Pointer to target struct timeval which should receive the timestamp
  * @flags: Flags to pass to driver:
  *         0 = Default,
@@ -833,7 +835,7 @@ static struct timeval get_drm_timestamp(void)
  * True if timestamp is considered to be very precise, false otherwise.
  */
 static bool
-drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
+drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
                          struct timeval *tvblank, unsigned flags)
 {
        int ret;
@@ -843,7 +845,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
 
        /* Query driver if possible and precision timestamping enabled. */
        if (dev->driver->get_vblank_timestamp && (max_error > 0)) {
-               ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error,
+               ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error,
                                                        tvblank, flags);
                if (ret > 0)
                        return true;
@@ -860,7 +862,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
 /**
  * drm_vblank_count - retrieve "cooked" vblank counter value
  * @dev: DRM device
- * @crtc: which counter to retrieve
+ * @pipe: index of CRTC for which to retrieve the counter
  *
  * Fetches the "cooked" vblank count value that represents the number of
  * vblank events since the system was booted, including lost events due to
@@ -871,12 +873,13 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
  * Returns:
  * The software vblank counter.
  */
-u32 drm_vblank_count(struct drm_device *dev, int crtc)
+u32 drm_vblank_count(struct drm_device *dev, int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 
-       if (WARN_ON(crtc >= dev->num_crtcs))
+       if (WARN_ON(pipe >= dev->num_crtcs))
                return 0;
+
        return vblank->count;
 }
 EXPORT_SYMBOL(drm_vblank_count);
@@ -901,11 +904,10 @@ u32 drm_crtc_vblank_count(struct drm_crtc *crtc)
 EXPORT_SYMBOL(drm_crtc_vblank_count);
 
 /**
- * drm_vblank_count_and_time - retrieve "cooked" vblank counter value
- * and the system timestamp corresponding to that vblank counter value.
- *
+ * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the
+ *     system timestamp corresponding to that vblank counter value.
  * @dev: DRM device
- * @crtc: which counter to retrieve
+ * @pipe: index of CRTC whose counter to retrieve
  * @vblanktime: Pointer to struct timeval to receive the vblank timestamp.
  *
  * Fetches the "cooked" vblank count value that represents the number of
@@ -913,13 +915,13 @@ EXPORT_SYMBOL(drm_crtc_vblank_count);
  * modesetting activity. Returns corresponding system timestamp of the time
  * of the vblank interval that corresponds to the current vblank counter value.
  */
-u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
+u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
                              struct timeval *vblanktime)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        u32 cur_vblank;
 
-       if (WARN_ON(crtc >= dev->num_crtcs))
+       if (WARN_ON(pipe >= dev->num_crtcs))
                return 0;
 
        /*
@@ -930,7 +932,7 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
        do {
                cur_vblank = vblank->count;
                smp_rmb();
-               *vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
+               *vblanktime = vblanktimestamp(dev, pipe, cur_vblank);
                smp_rmb();
        } while (cur_vblank != vblank->count);
 
@@ -957,7 +959,7 @@ static void send_vblank_event(struct drm_device *dev,
 /**
  * drm_send_vblank_event - helper to send vblank event after pageflip
  * @dev: DRM device
- * @crtc: CRTC in question
+ * @pipe: CRTC index
  * @e: the event to send
  *
  * Updates sequence # and timestamp on event, and sends it to userspace.
@@ -965,20 +967,20 @@ static void send_vblank_event(struct drm_device *dev,
  *
  * This is the legacy version of drm_crtc_send_vblank_event().
  */
-void drm_send_vblank_event(struct drm_device *dev, int crtc,
-               struct drm_pending_vblank_event *e)
+void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe,
+                          struct drm_pending_vblank_event *e)
 {
        struct timeval now;
        unsigned int seq;
 
-       if (crtc >= 0) {
-               seq = drm_vblank_count_and_time(dev, crtc, &now);
+       if (dev->num_crtcs > 0) {
+               seq = drm_vblank_count_and_time(dev, pipe, &now);
        } else {
                seq = 0;
 
                now = get_drm_timestamp();
        }
-       e->pipe = crtc;
+       e->pipe = pipe;
        send_vblank_event(dev, e, seq, &now);
 }
 EXPORT_SYMBOL(drm_send_vblank_event);
@@ -1003,11 +1005,14 @@ EXPORT_SYMBOL(drm_crtc_send_vblank_event);
 /**
  * drm_vblank_enable - enable the vblank interrupt on a CRTC
  * @dev: DRM device
- * @crtc: CRTC in question
+ * @pipe: CRTC index
+ *
+ * Returns:
+ * Zero on success or a negative error code on failure.
  */
-static int drm_vblank_enable(struct drm_device *dev, int crtc)
+static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        int ret = 0;
 
        assert_spin_locked(&dev->vbl_lock);
@@ -1022,13 +1027,13 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc)
                 * timestamps. Filtercode in drm_handle_vblank() will
                 * prevent double-accounting of same vblank interval.
                 */
-               ret = dev->driver->enable_vblank(dev, crtc);
-               DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
+               ret = dev->driver->enable_vblank(dev, pipe);
+               DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret);
                if (ret)
                        atomic_dec(&vblank->refcount);
                else {
                        vblank->enabled = true;
-                       drm_update_vblank_count(dev, crtc);
+                       drm_update_vblank_count(dev, pipe);
                }
        }
 
@@ -1040,7 +1045,7 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc)
 /**
  * drm_vblank_get - get a reference count on vblank events
  * @dev: DRM device
- * @crtc: which CRTC to own
+ * @pipe: index of CRTC to own
  *
  * Acquire a reference count on vblank events to avoid having them disabled
  * while in use.
@@ -1048,24 +1053,24 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc)
  * This is the legacy version of drm_crtc_vblank_get().
  *
  * Returns:
- * Zero on success, nonzero on failure.
+ * Zero on success or a negative error code on failure.
  */
-int drm_vblank_get(struct drm_device *dev, int crtc)
+int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        unsigned long irqflags;
        int ret = 0;
 
        if (!dev->num_crtcs)
                return -EINVAL;
 
-       if (WARN_ON(crtc >= dev->num_crtcs))
+       if (WARN_ON(pipe >= dev->num_crtcs))
                return -EINVAL;
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        /* Going from 0->1 means we have to enable interrupts again */
        if (atomic_add_return(1, &vblank->refcount) == 1) {
-               ret = drm_vblank_enable(dev, crtc);
+               ret = drm_vblank_enable(dev, pipe);
        } else {
                if (!vblank->enabled) {
                        atomic_dec(&vblank->refcount);
@@ -1088,7 +1093,7 @@ EXPORT_SYMBOL(drm_vblank_get);
  * This is the native kms version of drm_vblank_get().
  *
  * Returns:
- * Zero on success, nonzero on failure.
+ * Zero on success or a negative error code on failure.
  */
 int drm_crtc_vblank_get(struct drm_crtc *crtc)
 {
@@ -1097,23 +1102,23 @@ int drm_crtc_vblank_get(struct drm_crtc *crtc)
 EXPORT_SYMBOL(drm_crtc_vblank_get);
 
 /**
- * drm_vblank_put - give up ownership of vblank events
+ * drm_vblank_put - release ownership of vblank events
  * @dev: DRM device
- * @crtc: which counter to give up
+ * @pipe: index of CRTC to release
  *
  * Release ownership of a given vblank counter, turning off interrupts
  * if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
  *
  * This is the legacy version of drm_crtc_vblank_put().
  */
-void drm_vblank_put(struct drm_device *dev, int crtc)
+void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 
-       if (WARN_ON(atomic_read(&vblank->refcount) == 0))
+       if (WARN_ON(pipe >= dev->num_crtcs))
                return;
 
-       if (WARN_ON(crtc >= dev->num_crtcs))
+       if (WARN_ON(atomic_read(&vblank->refcount) == 0))
                return;
 
        /* Last user schedules interrupt disable */
@@ -1147,30 +1152,34 @@ EXPORT_SYMBOL(drm_crtc_vblank_put);
 /**
  * drm_wait_one_vblank - wait for one vblank
  * @dev: DRM device
- * @crtc: crtc index
+ * @pipe: CRTC index
  *
  * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
  * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
  * due to lack of driver support or because the crtc is off.
  */
-void drm_wait_one_vblank(struct drm_device *dev, int crtc)
+void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
 {
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        int ret;
        u32 last;
 
-       ret = drm_vblank_get(dev, crtc);
-       if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", crtc, ret))
+       if (WARN_ON(pipe >= dev->num_crtcs))
                return;
 
-       last = drm_vblank_count(dev, crtc);
+       ret = drm_vblank_get(dev, pipe);
+       if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", pipe, ret))
+               return;
 
-       ret = wait_event_timeout(dev->vblank[crtc].queue,
-                                last != drm_vblank_count(dev, crtc),
+       last = drm_vblank_count(dev, pipe);
+
+       ret = wait_event_timeout(vblank->queue,
+                                last != drm_vblank_count(dev, pipe),
                                 msecs_to_jiffies(100));
 
-       WARN(ret == 0, "vblank wait timed out on crtc %i\n", crtc);
+       WARN(ret == 0, "vblank wait timed out on crtc %i\n", pipe);
 
-       drm_vblank_put(dev, crtc);
+       drm_vblank_put(dev, pipe);
 }
 EXPORT_SYMBOL(drm_wait_one_vblank);
 
@@ -1191,7 +1200,7 @@ EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
 /**
  * drm_vblank_off - disable vblank events on a CRTC
  * @dev: DRM device
- * @crtc: CRTC in question
+ * @pipe: CRTC index
  *
  * Drivers can use this function to shut down the vblank interrupt handling when
  * disabling a crtc. This function ensures that the latest vblank frame count is
@@ -1202,21 +1211,21 @@ EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
  *
  * This is the legacy version of drm_crtc_vblank_off().
  */
-void drm_vblank_off(struct drm_device *dev, int crtc)
+void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        struct drm_pending_vblank_event *e, *t;
        struct timeval now;
        unsigned long irqflags;
        unsigned int seq;
 
-       if (WARN_ON(crtc >= dev->num_crtcs))
+       if (WARN_ON(pipe >= dev->num_crtcs))
                return;
 
        spin_lock_irqsave(&dev->event_lock, irqflags);
 
        spin_lock(&dev->vbl_lock);
-       vblank_disable_and_save(dev, crtc);
+       vblank_disable_and_save(dev, pipe);
        wake_up(&vblank->queue);
 
        /*
@@ -1230,16 +1239,16 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
        spin_unlock(&dev->vbl_lock);
 
        /* Send any queued vblank events, lest the natives grow disquiet */
-       seq = drm_vblank_count_and_time(dev, crtc, &now);
+       seq = drm_vblank_count_and_time(dev, pipe, &now);
 
        list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
-               if (e->pipe != crtc)
+               if (e->pipe != pipe)
                        continue;
                DRM_DEBUG("Sending premature vblank event on disable: \
                          wanted %d, current %d\n",
                          e->event.sequence, seq);
                list_del(&e->base.link);
-               drm_vblank_put(dev, e->pipe);
+               drm_vblank_put(dev, pipe);
                send_vblank_event(dev, e, seq, &now);
        }
        spin_unlock_irqrestore(&dev->event_lock, irqflags);
@@ -1300,7 +1309,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_reset);
 /**
  * drm_vblank_on - enable vblank events on a CRTC
  * @dev: DRM device
- * @crtc: CRTC in question
+ * @pipe: CRTC index
  *
  * This functions restores the vblank interrupt state captured with
  * drm_vblank_off() again. Note that calls to drm_vblank_on() and
@@ -1309,12 +1318,12 @@ EXPORT_SYMBOL(drm_crtc_vblank_reset);
  *
  * This is the legacy version of drm_crtc_vblank_on().
  */
-void drm_vblank_on(struct drm_device *dev, int crtc)
+void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        unsigned long irqflags;
 
-       if (WARN_ON(crtc >= dev->num_crtcs))
+       if (WARN_ON(pipe >= dev->num_crtcs))
                return;
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -1332,7 +1341,7 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
         * vblank counter value before and after a modeset
         */
        vblank->last =
-               (dev->driver->get_vblank_counter(dev, crtc) - 1) &
+               (dev->driver->get_vblank_counter(dev, pipe) - 1) &
                dev->max_vblank_count;
        /*
         * re-enable interrupts if there are users left, or the
@@ -1340,7 +1349,7 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
         */
        if (atomic_read(&vblank->refcount) != 0 ||
            (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0))
-               WARN_ON(drm_vblank_enable(dev, crtc));
+               WARN_ON(drm_vblank_enable(dev, pipe));
        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 EXPORT_SYMBOL(drm_vblank_on);
@@ -1365,7 +1374,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_on);
 /**
  * drm_vblank_pre_modeset - account for vblanks across mode sets
  * @dev: DRM device
- * @crtc: CRTC in question
+ * @pipe: CRTC index
  *
  * Account for vblank events across mode setting events, which will likely
  * reset the hardware frame counter.
@@ -1385,15 +1394,15 @@ EXPORT_SYMBOL(drm_crtc_vblank_on);
  * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc
  * again.
  */
-void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
+void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 
        /* vblank is not initialized (IRQ not installed ?), or has been freed */
        if (!dev->num_crtcs)
                return;
 
-       if (WARN_ON(crtc >= dev->num_crtcs))
+       if (WARN_ON(pipe >= dev->num_crtcs))
                return;
 
        /*
@@ -1405,7 +1414,7 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
         */
        if (!vblank->inmodeset) {
                vblank->inmodeset = 0x1;
-               if (drm_vblank_get(dev, crtc) == 0)
+               if (drm_vblank_get(dev, pipe) == 0)
                        vblank->inmodeset |= 0x2;
        }
 }
@@ -1414,27 +1423,30 @@ EXPORT_SYMBOL(drm_vblank_pre_modeset);
 /**
  * drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes
  * @dev: DRM device
- * @crtc: CRTC in question
+ * @pipe: CRTC index
  *
  * This function again drops the temporary vblank reference acquired in
  * drm_vblank_pre_modeset.
  */
-void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
+void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        unsigned long irqflags;
 
        /* vblank is not initialized (IRQ not installed ?), or has been freed */
        if (!dev->num_crtcs)
                return;
 
+       if (WARN_ON(pipe >= dev->num_crtcs))
+               return;
+
        if (vblank->inmodeset) {
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
                dev->vblank_disable_allowed = true;
                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
                if (vblank->inmodeset & 0x2)
-                       drm_vblank_put(dev, crtc);
+                       drm_vblank_put(dev, pipe);
 
                vblank->inmodeset = 0;
        }
@@ -1456,7 +1468,7 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
                    struct drm_file *file_priv)
 {
        struct drm_modeset_ctl *modeset = data;
-       unsigned int crtc;
+       unsigned int pipe;
 
        /* If drm_vblank_init() hasn't been called yet, just no-op */
        if (!dev->num_crtcs)
@@ -1466,16 +1478,16 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return 0;
 
-       crtc = modeset->crtc;
-       if (crtc >= dev->num_crtcs)
+       pipe = modeset->crtc;
+       if (pipe >= dev->num_crtcs)
                return -EINVAL;
 
        switch (modeset->cmd) {
        case _DRM_PRE_MODESET:
-               drm_vblank_pre_modeset(dev, crtc);
+               drm_vblank_pre_modeset(dev, pipe);
                break;
        case _DRM_POST_MODESET:
-               drm_vblank_post_modeset(dev, crtc);
+               drm_vblank_post_modeset(dev, pipe);
                break;
        default:
                return -EINVAL;
@@ -1484,7 +1496,7 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
        return 0;
 }
 
-static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
+static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
                                  union drm_wait_vblank *vblwait,
                                  struct drm_file *file_priv)
 {
@@ -1538,7 +1550,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
                vblwait->reply.sequence = vblwait->request.sequence;
        }
 
-       DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
+       DRM_DEBUG("event on vblank count %d, current %d, crtc %u\n",
                  vblwait->request.sequence, seq, pipe);
 
        trace_drm_vblank_event_queued(current->pid, pipe,
@@ -1587,7 +1599,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
        struct drm_vblank_crtc *vblank;
        union drm_wait_vblank *vblwait = data;
        int ret;
-       unsigned int flags, seq, crtc, high_crtc;
+       unsigned int flags, seq, pipe, high_pipe;
 
        if (!dev->irq_enabled)
                return -EINVAL;
@@ -1606,22 +1618,22 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
        }
 
        flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
-       high_crtc = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
-       if (high_crtc)
-               crtc = high_crtc >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
+       high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
+       if (high_pipe)
+               pipe = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
        else
-               crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
-       if (crtc >= dev->num_crtcs)
+               pipe = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+       if (pipe >= dev->num_crtcs)
                return -EINVAL;
 
-       vblank = &dev->vblank[crtc];
+       vblank = &dev->vblank[pipe];
 
-       ret = drm_vblank_get(dev, crtc);
+       ret = drm_vblank_get(dev, pipe);
        if (ret) {
                DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
                return ret;
        }
-       seq = drm_vblank_count(dev, crtc);
+       seq = drm_vblank_count(dev, pipe);
 
        switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
        case _DRM_VBLANK_RELATIVE:
@@ -1638,7 +1650,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
                /* must hold on to the vblank ref until the event fires
                 * drm_vblank_put will be called asynchronously
                 */
-               return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
+               return drm_queue_vblank_event(dev, pipe, vblwait, file_priv);
        }
 
        if ((flags & _DRM_VBLANK_NEXTONMISS) &&
@@ -1646,11 +1658,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
                vblwait->request.sequence = seq + 1;
        }
 
-       DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
-                 vblwait->request.sequence, crtc);
+       DRM_DEBUG("waiting on vblank count %d, crtc %u\n",
+                 vblwait->request.sequence, pipe);
        vblank->last_wait = vblwait->request.sequence;
        DRM_WAIT_ON(ret, vblank->queue, 3 * HZ,
-                   (((drm_vblank_count(dev, crtc) -
+                   (((drm_vblank_count(dev, pipe) -
                       vblwait->request.sequence) <= (1 << 23)) ||
                     !vblank->enabled ||
                     !dev->irq_enabled));
@@ -1658,7 +1670,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
        if (ret != -EINTR) {
                struct timeval now;
 
-               vblwait->reply.sequence = drm_vblank_count_and_time(dev, crtc, &now);
+               vblwait->reply.sequence = drm_vblank_count_and_time(dev, pipe, &now);
                vblwait->reply.tval_sec = now.tv_sec;
                vblwait->reply.tval_usec = now.tv_usec;
 
@@ -1669,11 +1681,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
        }
 
 done:
-       drm_vblank_put(dev, crtc);
+       drm_vblank_put(dev, pipe);
        return ret;
 }
 
-static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
+static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
 {
        struct drm_pending_vblank_event *e, *t;
        struct timeval now;
@@ -1681,10 +1693,10 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
 
        assert_spin_locked(&dev->event_lock);
 
-       seq = drm_vblank_count_and_time(dev, crtc, &now);
+       seq = drm_vblank_count_and_time(dev, pipe, &now);
 
        list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
-               if (e->pipe != crtc)
+               if (e->pipe != pipe)
                        continue;
                if ((seq - e->event.sequence) > (1<<23))
                        continue;
@@ -1693,26 +1705,26 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
                          e->event.sequence, seq);
 
                list_del(&e->base.link);
-               drm_vblank_put(dev, e->pipe);
+               drm_vblank_put(dev, pipe);
                send_vblank_event(dev, e, seq, &now);
        }
 
-       trace_drm_vblank_event(crtc, seq);
+       trace_drm_vblank_event(pipe, seq);
 }
 
 /**
  * drm_handle_vblank - handle a vblank event
  * @dev: DRM device
- * @crtc: where this event occurred
+ * @pipe: index of CRTC where this event occurred
  *
  * Drivers should call this routine in their vblank interrupt handlers to
  * update the vblank counter and send any signals that may be pending.
  *
  * This is the legacy version of drm_crtc_handle_vblank().
  */
-bool drm_handle_vblank(struct drm_device *dev, int crtc)
+bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
 {
-       struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        u32 vblcount;
        s64 diff_ns;
        struct timeval tvblank;
@@ -1721,7 +1733,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
        if (WARN_ON_ONCE(!dev->num_crtcs))
                return false;
 
-       if (WARN_ON(crtc >= dev->num_crtcs))
+       if (WARN_ON(pipe >= dev->num_crtcs))
                return false;
 
        spin_lock_irqsave(&dev->event_lock, irqflags);
@@ -1745,11 +1757,11 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
 
        /* Get current timestamp and count. */
        vblcount = vblank->count;
-       drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ);
+       drm_get_last_vbltimestamp(dev, pipe, &tvblank, DRM_CALLED_FROM_VBLIRQ);
 
        /* Compute time difference to timestamp of last vblank */
        diff_ns = timeval_to_ns(&tvblank) -
-                 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
+                 timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount));
 
        /* Update vblank timestamp and count if at least
         * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds
@@ -1761,15 +1773,15 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
         * ignore those for accounting.
         */
        if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS)
-               store_vblank(dev, crtc, 1, &tvblank);
+               store_vblank(dev, pipe, 1, &tvblank);
        else
-               DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n",
-                         crtc, (int) diff_ns);
+               DRM_DEBUG("crtc %u: Redundant vblirq ignored. diff_ns = %d\n",
+                         pipe, (int) diff_ns);
 
        spin_unlock(&dev->vblank_time_lock);
 
        wake_up(&vblank->queue);
-       drm_handle_vblank_events(dev, crtc);
+       drm_handle_vblank_events(dev, pipe);
 
        spin_unlock_irqrestore(&dev->event_lock, irqflags);
 
index 744dfbc6a329aef96dfcab631c2f55fae61de7db..fba321ca434485d0f6f6d7898c84711eea47a577 100644 (file)
  *     drm_modeset_acquire_fini(&ctx);
  */
 
-
 /**
- * __drm_modeset_lock_all - internal helper to grab all modeset locks
- * @dev: DRM device
- * @trylock: trylock mode for atomic contexts
- *
- * This is a special version of drm_modeset_lock_all() which can also be used in
- * atomic contexts. Then @trylock must be set to true.
+ * drm_modeset_lock_all - take all modeset locks
+ * @dev: drm device
  *
- * Returns:
- * 0 on success or negative error code on failure.
+ * This function takes all modeset locks, suitable where a more fine-grained
+ * scheme isn't (yet) implemented. Locks must be dropped with
+ * drm_modeset_unlock_all.
  */
-int __drm_modeset_lock_all(struct drm_device *dev,
-                          bool trylock)
+void drm_modeset_lock_all(struct drm_device *dev)
 {
        struct drm_mode_config *config = &dev->mode_config;
        struct drm_modeset_acquire_ctx *ctx;
        int ret;
 
-       ctx = kzalloc(sizeof(*ctx),
-                     trylock ? GFP_ATOMIC : GFP_KERNEL);
-       if (!ctx)
-               return -ENOMEM;
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (WARN_ON(!ctx))
+               return;
 
-       if (trylock) {
-               if (!mutex_trylock(&config->mutex)) {
-                       ret = -EBUSY;
-                       goto out;
-               }
-       } else {
-               mutex_lock(&config->mutex);
-       }
+       mutex_lock(&config->mutex);
 
        drm_modeset_acquire_init(ctx, 0);
-       ctx->trylock_only = trylock;
 
 retry:
        ret = drm_modeset_lock(&config->connection_mutex, ctx);
@@ -108,7 +94,7 @@ retry:
 
        drm_warn_on_modeset_not_all_locked(dev);
 
-       return 0;
+       return;
 
 fail:
        if (ret == -EDEADLK) {
@@ -116,23 +102,7 @@ fail:
                goto retry;
        }
 
-out:
        kfree(ctx);
-       return ret;
-}
-EXPORT_SYMBOL(__drm_modeset_lock_all);
-
-/**
- * drm_modeset_lock_all - take all modeset locks
- * @dev: drm device
- *
- * This function takes all modeset locks, suitable where a more fine-grained
- * scheme isn't (yet) implemented. Locks must be dropped with
- * drm_modeset_unlock_all.
- */
-void drm_modeset_lock_all(struct drm_device *dev)
-{
-       WARN_ON(__drm_modeset_lock_all(dev, false) != 0);
 }
 EXPORT_SYMBOL(drm_modeset_lock_all);
 
index 46c7045733061e13c169d1c632fa80d82853c42a..5e5a07af02c85c4297df213847759bd620a82390 100644 (file)
@@ -437,7 +437,7 @@ int drm_plane_helper_commit(struct drm_plane *plane,
 
        for (i = 0; i < 2; i++) {
                if (crtc_funcs[i] && crtc_funcs[i]->atomic_begin)
-                       crtc_funcs[i]->atomic_begin(crtc[i]);
+                       crtc_funcs[i]->atomic_begin(crtc[i], crtc[i]->state);
        }
 
        /*
@@ -452,7 +452,7 @@ int drm_plane_helper_commit(struct drm_plane *plane,
 
        for (i = 0; i < 2; i++) {
                if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush)
-                       crtc_funcs[i]->atomic_flush(crtc[i]);
+                       crtc_funcs[i]->atomic_flush(crtc[i], crtc[i]->state);
        }
 
        /*
index 644b4b76e07176e3df75b0415227eac162fb3d26..1610757230a5f2545f7dbb7b77367cf2c5d6cc56 100644 (file)
@@ -80,7 +80,8 @@ exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
                exynos_crtc->ops->commit(exynos_crtc);
 }
 
-static void exynos_crtc_atomic_begin(struct drm_crtc *crtc)
+static void exynos_crtc_atomic_begin(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *old_crtc_state)
 {
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 
@@ -90,7 +91,8 @@ static void exynos_crtc_atomic_begin(struct drm_crtc *crtc)
        }
 }
 
-static void exynos_crtc_atomic_flush(struct drm_crtc *crtc)
+static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *old_crtc_state)
 {
 }
 
index e0b085b4bdfac33d1a8a5a436c8d5764a6fe33e8..dd64bc04ffbb47012c0d760d0aa181146c01e003 100644 (file)
@@ -65,9 +65,9 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
 static struct fb_ops exynos_drm_fb_ops = {
        .owner          = THIS_MODULE,
        .fb_mmap        = exynos_drm_fb_mmap,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
+       .fb_fillrect    = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea    = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit   = drm_fb_helper_cfb_imageblit,
        .fb_check_var   = drm_fb_helper_check_var,
        .fb_set_par     = drm_fb_helper_set_par,
        .fb_blank       = drm_fb_helper_blank,
@@ -142,10 +142,10 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
 
        mutex_lock(&dev->struct_mutex);
 
-       fbi = framebuffer_alloc(0, &pdev->dev);
-       if (!fbi) {
+       fbi = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(fbi)) {
                DRM_ERROR("failed to allocate fb info.\n");
-               ret = -ENOMEM;
+               ret = PTR_ERR(fbi);
                goto out;
        }
 
@@ -165,7 +165,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
 
        if (IS_ERR(exynos_gem_obj)) {
                ret = PTR_ERR(exynos_gem_obj);
-               goto err_release_framebuffer;
+               goto err_release_fbi;
        }
 
        exynos_fbdev->exynos_gem_obj = exynos_gem_obj;
@@ -178,33 +178,23 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
                goto err_destroy_gem;
        }
 
-       helper->fbdev = fbi;
-
        fbi->par = helper;
        fbi->flags = FBINFO_FLAG_DEFAULT;
        fbi->fbops = &exynos_drm_fb_ops;
 
-       ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
-       if (ret) {
-               DRM_ERROR("failed to allocate cmap.\n");
-               goto err_destroy_framebuffer;
-       }
-
        ret = exynos_drm_fbdev_update(helper, sizes, helper->fb);
        if (ret < 0)
-               goto err_dealloc_cmap;
+               goto err_destroy_framebuffer;
 
        mutex_unlock(&dev->struct_mutex);
        return ret;
 
-err_dealloc_cmap:
-       fb_dealloc_cmap(&fbi->cmap);
 err_destroy_framebuffer:
        drm_framebuffer_cleanup(helper->fb);
 err_destroy_gem:
        exynos_drm_gem_destroy(exynos_gem_obj);
-err_release_framebuffer:
-       framebuffer_release(fbi);
+err_release_fbi:
+       drm_fb_helper_release_fbi(helper);
 
 /*
  * if failed, all resources allocated above would be released by
@@ -312,21 +302,8 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
                }
        }
 
-       /* release linux framebuffer */
-       if (fb_helper->fbdev) {
-               struct fb_info *info;
-               int ret;
-
-               info = fb_helper->fbdev;
-               ret = unregister_framebuffer(info);
-               if (ret < 0)
-                       DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
-
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(fb_helper);
+       drm_fb_helper_release_fbi(fb_helper);
 
        drm_fb_helper_fini(fb_helper);
 }
index de6f62a6ceb7a2d85ab67ba2eb64e8f688c05320..db9f7d011832943a2d3537228b538b368b4cc5c1 100644 (file)
@@ -276,12 +276,12 @@ static void psbfb_copyarea_accel(struct fb_info *info,
                break;
        default:
                /* software fallback */
-               cfb_copyarea(info, a);
+               drm_fb_helper_cfb_copyarea(info, a);
                return;
        }
 
        if (!gma_power_begin(dev, false)) {
-               cfb_copyarea(info, a);
+               drm_fb_helper_cfb_copyarea(info, a);
                return;
        }
        psb_accel_2d_copy(dev_priv,
@@ -308,7 +308,7 @@ void psbfb_copyarea(struct fb_info *info,
        /* Avoid the 8 pixel erratum */
        if (region->width == 8 || region->height == 8 ||
                (info->flags & FBINFO_HWACCEL_DISABLED))
-               return cfb_copyarea(info, region);
+               return drm_fb_helper_cfb_copyarea(info, region);
 
        psbfb_copyarea_accel(info, region);
 }
index 2d42ce6d37577a45fc446117855244296b45760b..2eaf1b31c7bd8c76d8d69d60a0dd43343466e9ec 100644 (file)
@@ -194,9 +194,9 @@ static struct fb_ops psbfb_ops = {
        .fb_set_par = drm_fb_helper_set_par,
        .fb_blank = drm_fb_helper_blank,
        .fb_setcolreg = psbfb_setcolreg,
-       .fb_fillrect = cfb_fillrect,
+       .fb_fillrect = drm_fb_helper_cfb_fillrect,
        .fb_copyarea = psbfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
+       .fb_imageblit = drm_fb_helper_cfb_imageblit,
        .fb_mmap = psbfb_mmap,
        .fb_sync = psbfb_sync,
        .fb_ioctl = psbfb_ioctl,
@@ -208,9 +208,9 @@ static struct fb_ops psbfb_roll_ops = {
        .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_fillrect = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit = drm_fb_helper_cfb_imageblit,
        .fb_pan_display = psbfb_pan,
        .fb_mmap = psbfb_mmap,
        .fb_ioctl = psbfb_ioctl,
@@ -222,9 +222,9 @@ static struct fb_ops psbfb_unaccel_ops = {
        .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_fillrect = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit = drm_fb_helper_cfb_imageblit,
        .fb_mmap = psbfb_mmap,
        .fb_ioctl = psbfb_ioctl,
 };
@@ -343,7 +343,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
        struct drm_framebuffer *fb;
        struct psb_framebuffer *psbfb = &fbdev->pfb;
        struct drm_mode_fb_cmd2 mode_cmd;
-       struct device *device = &dev->pdev->dev;
        int size;
        int ret;
        struct gtt_range *backing;
@@ -409,9 +408,9 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 
        mutex_lock(&dev->struct_mutex);
 
-       info = framebuffer_alloc(0, device);
-       if (!info) {
-               ret = -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(&fbdev->psb_fb_helper);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
                goto out_err1;
        }
        info->par = fbdev;
@@ -426,7 +425,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
        psbfb->fbdev = info;
 
        fbdev->psb_fb_helper.fb = fb;
-       fbdev->psb_fb_helper.fbdev = info;
 
        drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
        strcpy(info->fix.id, "psbdrmfb");
@@ -440,12 +438,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
        } else  /* Software */
                info->fbops = &psbfb_unaccel_ops;
 
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto out_unref;
-       }
-
        info->fix.smem_start = dev->mode_config.fb_base;
        info->fix.smem_len = size;
        info->fix.ywrapstep = gtt_roll;
@@ -456,11 +448,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
        info->screen_size = size;
 
        if (dev_priv->gtt.stolen_size) {
-               info->apertures = alloc_apertures(1);
-               if (!info->apertures) {
-                       ret = -ENOMEM;
-                       goto out_unref;
-               }
                info->apertures->ranges[0].base = dev->mode_config.fb_base;
                info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
        }
@@ -483,6 +470,8 @@ out_unref:
                psb_gtt_free_range(dev, backing);
        else
                drm_gem_object_unreference(&backing->gem);
+
+       drm_fb_helper_release_fbi(&fbdev->psb_fb_helper);
 out_err1:
        mutex_unlock(&dev->struct_mutex);
        psb_gtt_free_range(dev, backing);
@@ -570,16 +559,11 @@ static const struct drm_fb_helper_funcs psb_fb_helper_funcs = {
 
 static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 {
-       struct fb_info *info;
        struct psb_framebuffer *psbfb = &fbdev->pfb;
 
-       if (fbdev->psb_fb_helper.fbdev) {
-               info = fbdev->psb_fb_helper.fbdev;
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&fbdev->psb_fb_helper);
+       drm_fb_helper_release_fbi(&fbdev->psb_fb_helper);
+
        drm_fb_helper_fini(&fbdev->psb_fb_helper);
        drm_framebuffer_unregister_private(&psbfb->base);
        drm_framebuffer_cleanup(&psbfb->base);
index eb87e2538861506409ad7651a6a5b7738e771fa4..051eab33e4c7b13260994ebb884cc44a5394c4bc 100644 (file)
@@ -36,21 +36,6 @@ config DRM_I915
          i810 driver instead, and the Atom z5xx series has an entirely
          different implementation.
 
-config DRM_I915_FBDEV
-       bool "Enable legacy fbdev support for the modesetting intel driver"
-       depends on DRM_I915
-       select DRM_KMS_FB_HELPER
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       default y
-       help
-         Choose this option if you have a need for the legacy fbdev
-         support. Note that this support also provide the linux console
-         support on top of the intel modesetting driver.
-
-         If in doubt, say "Y".
-
 config DRM_I915_PRELIMINARY_HW_SUPPORT
        bool "Enable preliminary support for prerelease Intel hardware by default"
        depends on DRM_I915
index e52e0125164450ad7f1e2dea841000b7a24c94bb..b3d9992f02103c8a0ba5ca4428b60e97a51b8c9d 100644 (file)
@@ -59,7 +59,7 @@ i915-y += intel_audio.o \
          intel_sideband.o \
          intel_sprite.o
 i915-$(CONFIG_ACPI)            += intel_acpi.o intel_opregion.o
-i915-$(CONFIG_DRM_I915_FBDEV)  += intel_fbdev.o
+i915-$(CONFIG_DRM_FBDEV_EMULATION)     += intel_fbdev.o
 
 # modesetting output/encoder code
 i915-y += dvo_ch7017.o \
index 51580bdd587fd8e6e3ef3f4820682924bdc35003..36fe318757376fcdb3d3ad2c63fe072f3df53733 100644 (file)
@@ -1868,7 +1868,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
        struct intel_framebuffer *fb;
        struct drm_framebuffer *drm_fb;
 
-#ifdef CONFIG_DRM_I915_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        ifbdev = dev_priv->fbdev;
index 23ce125e0298e05b430f05daf45ef56952948fed..e9d2befbcaf3b382e28f593ac1ce16a9e9184101 100644 (file)
@@ -1854,7 +1854,7 @@ struct drm_i915_private {
 
        struct drm_i915_gem_object *vlv_pctx;
 
-#ifdef CONFIG_DRM_I915_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
        /* list of fbdev register on this device */
        struct intel_fbdev *fbdev;
        struct work_struct fbdev_suspend_work;
index 521af2c069cb6aed90e379501d3fbc39c24df6e9..5d78c1feec8140f12d0c1676c74386b561111991 100644 (file)
@@ -237,7 +237,7 @@ static void intel_enable_crt(struct intel_encoder *encoder)
 }
 
 /* Special dpms function to support cloning between dvo/sdvo/crt. */
-static void intel_crt_dpms(struct drm_connector *connector, int mode)
+static int intel_crt_dpms(struct drm_connector *connector, int mode)
 {
        struct drm_device *dev = connector->dev;
        struct intel_encoder *encoder = intel_attached_encoder(connector);
@@ -249,7 +249,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
                mode = DRM_MODE_DPMS_OFF;
 
        if (mode == connector->dpms)
-               return;
+               return 0;
 
        old_dpms = connector->dpms;
        connector->dpms = mode;
@@ -258,7 +258,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
        crtc = encoder->base.crtc;
        if (!crtc) {
                encoder->connectors_active = false;
-               return;
+               return 0;
        }
 
        /* We need the pipe to run for anything but OFF. */
@@ -281,6 +281,8 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
        }
 
        intel_modeset_check_state(connector->dev);
+
+       return 0;
 }
 
 static enum drm_mode_status
index af0bcfee4771fd1af6ed0d2f06a5a9d4cf500f65..0a1d4a5d152d9f58b6af16c37dd8c873f8a20869 100644 (file)
@@ -102,8 +102,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_state *pipe_config);
 static void chv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_state *pipe_config);
-static void intel_begin_crtc_commit(struct drm_crtc *crtc);
-static void intel_finish_crtc_commit(struct drm_crtc *crtc);
+static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
+static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
 static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
        struct intel_crtc_state *crtc_state);
 static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
@@ -413,7 +413,7 @@ static const intel_limit_t intel_limits_bxt = {
 static bool
 needs_modeset(struct drm_crtc_state *state)
 {
-       return state->mode_changed || state->active_changed;
+       return drm_atomic_crtc_needs_modeset(state);
 }
 
 /**
@@ -6429,14 +6429,14 @@ struct intel_connector *intel_connector_alloc(void)
 
 /* Even simpler default implementation, if there's really no special case to
  * consider. */
-void intel_connector_dpms(struct drm_connector *connector, int mode)
+int intel_connector_dpms(struct drm_connector *connector, int mode)
 {
        /* All the simple cases only support two dpms states. */
        if (mode != DRM_MODE_DPMS_ON)
                mode = DRM_MODE_DPMS_OFF;
 
        if (mode == connector->dpms)
-               return;
+               return 0;
 
        connector->dpms = mode;
 
@@ -6445,6 +6445,8 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
                intel_encoder_dpms(to_intel_encoder(connector->encoder), mode);
 
        intel_modeset_check_state(connector->dev);
+
+       return 0;
 }
 
 /* Simple connector->get_hw_state implementation for encoders that support only
@@ -10219,7 +10221,7 @@ static struct drm_framebuffer *
 mode_fits_in_fbdev(struct drm_device *dev,
                   struct drm_display_mode *mode)
 {
-#ifdef CONFIG_DRM_I915_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
        struct drm_framebuffer *fb;
@@ -12347,16 +12349,9 @@ intel_modeset_update_state(struct drm_atomic_state *state)
                        continue;
 
                if (crtc->state->active) {
-                       struct drm_property *dpms_property =
-                               dev->mode_config.dpms_property;
-
-                       connector->dpms = DRM_MODE_DPMS_ON;
-                       drm_object_property_set_value(&connector->base, dpms_property, DRM_MODE_DPMS_ON);
-
                        intel_encoder = to_intel_encoder(connector->encoder);
                        intel_encoder->connectors_active = true;
-               } else
-                       connector->dpms = DRM_MODE_DPMS_OFF;
+               }
        }
 }
 
@@ -13628,7 +13623,8 @@ intel_disable_primary_plane(struct drm_plane *plane,
        dev_priv->display.update_primary_plane(crtc, NULL, 0, 0);
 }
 
-static void intel_begin_crtc_commit(struct drm_crtc *crtc)
+static void intel_begin_crtc_commit(struct drm_crtc *crtc,
+                                   struct drm_crtc_state *old_crtc_state)
 {
        struct drm_device *dev = crtc->dev;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -13644,7 +13640,8 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc)
                skl_detach_scalers(intel_crtc);
 }
 
-static void intel_finish_crtc_commit(struct drm_crtc *crtc)
+static void intel_finish_crtc_commit(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *old_crtc_state)
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
@@ -13684,7 +13681,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
        struct intel_plane *primary;
        struct intel_plane_state *state;
        const uint32_t *intel_primary_formats;
-       int num_formats;
+       unsigned int num_formats;
 
        primary = kzalloc(sizeof(*primary), GFP_KERNEL);
        if (primary == NULL)
@@ -14478,7 +14475,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
        return intel_framebuffer_create(dev, mode_cmd, obj);
 }
 
-#ifndef CONFIG_DRM_I915_FBDEV
+#ifndef CONFIG_DRM_FBDEV_EMULATION
 static inline void intel_fbdev_output_poll_changed(struct drm_device *dev)
 {
 }
index 585f0a45b3f1cf0cb53603c9204f9c271eb06df1..efc8cf53f0f318e650fdc3d55adf53efd5bee836 100644 (file)
@@ -395,7 +395,7 @@ static bool intel_dp_mst_get_hw_state(struct intel_connector *connector)
 
 static void intel_connector_add_to_fbdev(struct intel_connector *connector)
 {
-#ifdef CONFIG_DRM_I915_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, &connector->base);
 #endif
@@ -403,7 +403,7 @@ static void intel_connector_add_to_fbdev(struct intel_connector *connector)
 
 static void intel_connector_remove_from_fbdev(struct intel_connector *connector)
 {
-#ifdef CONFIG_DRM_I915_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, &connector->base);
 #endif
index 47cef0e6c79c985c3e1930ac02beb9eccac08d46..2e743d6abffd1b40c2b9d0a6b97d81a8f28552d3 100644 (file)
@@ -997,7 +997,7 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc);
 void intel_encoder_destroy(struct drm_encoder *encoder);
 int intel_connector_init(struct intel_connector *);
 struct intel_connector *intel_connector_alloc(void);
-void intel_connector_dpms(struct drm_connector *, int mode);
+int intel_connector_dpms(struct drm_connector *, int mode);
 bool intel_connector_get_hw_state(struct intel_connector *connector);
 void intel_modeset_check_state(struct drm_device *dev);
 bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
@@ -1203,7 +1203,7 @@ void intel_dvo_init(struct drm_device *dev);
 
 
 /* legacy fbdev emulation in intel_fbdev.c */
-#ifdef CONFIG_DRM_I915_FBDEV
+#ifdef CONFIG_DRM_FBDEV_EMULATION
 extern int intel_fbdev_init(struct drm_device *dev);
 extern void intel_fbdev_initial_config(void *data, async_cookie_t cookie);
 extern void intel_fbdev_fini(struct drm_device *dev);
index ece5bd754f85f5c0de25de036ba232ca19986b32..fd5e522abebb0c57e5fbdb71a64247915998a5dc 100644 (file)
@@ -197,7 +197,7 @@ static void intel_enable_dvo(struct intel_encoder *encoder)
 }
 
 /* Special dpms function to support cloning between dvo/sdvo/crt. */
-static void intel_dvo_dpms(struct drm_connector *connector, int mode)
+static int intel_dvo_dpms(struct drm_connector *connector, int mode)
 {
        struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
        struct drm_crtc *crtc;
@@ -208,7 +208,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
                mode = DRM_MODE_DPMS_OFF;
 
        if (mode == connector->dpms)
-               return;
+               return 0;
 
        connector->dpms = mode;
 
@@ -216,7 +216,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
        crtc = intel_dvo->base.base.crtc;
        if (!crtc) {
                intel_dvo->base.connectors_active = false;
-               return;
+               return 0;
        }
 
        /* We call connector dpms manually below in case pipe dpms doesn't
@@ -238,6 +238,8 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
        }
 
        intel_modeset_check_state(connector->dev);
+
+       return 0;
 }
 
 static enum drm_mode_status
index 7eff33ff84f69de52839817ac8d57ac219da5b53..8c6a6fa460057d38c71fe8f01986cde39f234442 100644 (file)
@@ -55,13 +55,6 @@ static int intel_fbdev_set_par(struct fb_info *info)
        ret = drm_fb_helper_set_par(info);
 
        if (ret == 0) {
-               /*
-                * FIXME: fbdev presumes that all callbacks also work from
-                * atomic contexts and relies on that for emergency oops
-                * printing. KMS totally doesn't do that and the locking here is
-                * by far not the only place this goes wrong.  Ignore this for
-                * now until we solve this for real.
-                */
                mutex_lock(&fb_helper->dev->struct_mutex);
                intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
                mutex_unlock(&fb_helper->dev->struct_mutex);
@@ -80,13 +73,6 @@ static int intel_fbdev_blank(int blank, struct fb_info *info)
        ret = drm_fb_helper_blank(blank, info);
 
        if (ret == 0) {
-               /*
-                * FIXME: fbdev presumes that all callbacks also work from
-                * atomic contexts and relies on that for emergency oops
-                * printing. KMS totally doesn't do that and the locking here is
-                * by far not the only place this goes wrong.  Ignore this for
-                * now until we solve this for real.
-                */
                mutex_lock(&fb_helper->dev->struct_mutex);
                intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
                mutex_unlock(&fb_helper->dev->struct_mutex);
@@ -106,13 +92,6 @@ static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
        ret = drm_fb_helper_pan_display(var, info);
 
        if (ret == 0) {
-               /*
-                * FIXME: fbdev presumes that all callbacks also work from
-                * atomic contexts and relies on that for emergency oops
-                * printing. KMS totally doesn't do that and the locking here is
-                * by far not the only place this goes wrong.  Ignore this for
-                * now until we solve this for real.
-                */
                mutex_lock(&fb_helper->dev->struct_mutex);
                intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
                mutex_unlock(&fb_helper->dev->struct_mutex);
@@ -125,9 +104,9 @@ static struct fb_ops intelfb_ops = {
        .owner = THIS_MODULE,
        .fb_check_var = drm_fb_helper_check_var,
        .fb_set_par = intel_fbdev_set_par,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = cfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
+       .fb_fillrect = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit = drm_fb_helper_cfb_imageblit,
        .fb_pan_display = intel_fbdev_pan_display,
        .fb_blank = intel_fbdev_blank,
        .fb_setcmap = drm_fb_helper_setcmap,
@@ -236,9 +215,9 @@ static int intelfb_create(struct drm_fb_helper *helper,
        obj = intel_fb->obj;
        size = obj->base.size;
 
-       info = framebuffer_alloc(0, &dev->pdev->dev);
-       if (!info) {
-               ret = -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
                goto out_unpin;
        }
 
@@ -247,24 +226,13 @@ static int intelfb_create(struct drm_fb_helper *helper,
        fb = &ifbdev->fb->base;
 
        ifbdev->helper.fb = fb;
-       ifbdev->helper.fbdev = info;
 
        strcpy(info->fix.id, "inteldrmfb");
 
        info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
        info->fbops = &intelfb_ops;
 
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto out_unpin;
-       }
        /* setup aperture base/size for vesafb takeover */
-       info->apertures = alloc_apertures(1);
-       if (!info->apertures) {
-               ret = -ENOMEM;
-               goto out_unpin;
-       }
        info->apertures->ranges[0].base = dev->mode_config.fb_base;
        info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
 
@@ -276,7 +244,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
                           size);
        if (!info->screen_base) {
                ret = -ENOSPC;
-               goto out_unpin;
+               goto out_destroy_fbi;
        }
        info->screen_size = size;
 
@@ -303,6 +271,8 @@ static int intelfb_create(struct drm_fb_helper *helper,
        vga_switcheroo_client_fb_set(dev->pdev, info);
        return 0;
 
+out_destroy_fbi:
+       drm_fb_helper_release_fbi(helper);
 out_unpin:
        i915_gem_object_ggtt_unpin(obj);
        drm_gem_object_unreference(&obj->base);
@@ -544,16 +514,9 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
 static void intel_fbdev_destroy(struct drm_device *dev,
                                struct intel_fbdev *ifbdev)
 {
-       if (ifbdev->helper.fbdev) {
-               struct fb_info *info = ifbdev->helper.fbdev;
 
-               unregister_framebuffer(info);
-               iounmap(info->screen_base);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&ifbdev->helper);
+       drm_fb_helper_release_fbi(&ifbdev->helper);
 
        drm_fb_helper_fini(&ifbdev->helper);
 
@@ -802,7 +765,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
        if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
                memset_io(info->screen_base, 0, info->screen_size);
 
-       fb_set_suspend(info, state);
+       drm_fb_helper_set_suspend(&ifbdev->helper, state);
        console_unlock();
 }
 
index aa2fd751609cf2be92826d4f8e6ba85df971892e..2c435a79d4da32c29619e5ef960d08959ebfb3ef 100644 (file)
@@ -1509,7 +1509,7 @@ static void intel_enable_sdvo(struct intel_encoder *encoder)
 }
 
 /* Special dpms function to support cloning between dvo/sdvo/crt. */
-static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
+static int intel_sdvo_dpms(struct drm_connector *connector, int mode)
 {
        struct drm_crtc *crtc;
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
@@ -1519,7 +1519,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
                mode = DRM_MODE_DPMS_OFF;
 
        if (mode == connector->dpms)
-               return;
+               return 0;
 
        connector->dpms = mode;
 
@@ -1527,7 +1527,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
        crtc = intel_sdvo->base.base.crtc;
        if (!crtc) {
                intel_sdvo->base.connectors_active = false;
-               return;
+               return 0;
        }
 
        /* We set active outputs manually below in case pipe dpms doesn't change
@@ -1551,6 +1551,8 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
        }
 
        intel_modeset_check_state(connector->dev);
+
+       return 0;
 }
 
 static enum drm_mode_status
index 9f9780b7ddf0be7d3a82ba77205d21d29984b02f..4f2068fe5d885cdba438a44745c27ccade5df9d0 100644 (file)
@@ -70,18 +70,22 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
        BUG_ON(pixels_2 != pixels_current && pixels_2 != pixels_prev);
        BUG_ON(pixels_current == pixels_prev);
 
+       obj = drm_gem_object_lookup(dev, file_priv, handle);
+       if (!obj)
+               return -ENOENT;
+
        ret = mgag200_bo_reserve(pixels_1, true);
        if (ret) {
                WREG8(MGA_CURPOSXL, 0);
                WREG8(MGA_CURPOSXH, 0);
-               return ret;
+               goto out_unref;
        }
        ret = mgag200_bo_reserve(pixels_2, true);
        if (ret) {
                WREG8(MGA_CURPOSXL, 0);
                WREG8(MGA_CURPOSXH, 0);
                mgag200_bo_unreserve(pixels_1);
-               return ret;
+               goto out_unreserve1;
        }
 
        if (!handle) {
@@ -106,16 +110,6 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
                }
        }
 
-       mutex_lock(&dev->struct_mutex);
-       obj = drm_gem_object_lookup(dev, file_priv, handle);
-       if (!obj) {
-               mutex_unlock(&dev->struct_mutex);
-               ret = -ENOENT;
-               goto out1;
-       }
-       drm_gem_object_unreference(obj);
-       mutex_unlock(&dev->struct_mutex);
-
        bo = gem_to_mga_bo(obj);
        ret = mgag200_bo_reserve(bo, true);
        if (ret) {
@@ -252,7 +246,11 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
        if (ret)
                mga_hide_cursor(mdev);
        mgag200_bo_unreserve(pixels_1);
+out_unreserve1:
        mgag200_bo_unreserve(pixels_2);
+out_unref:
+       drm_gem_object_unreference_unlocked(obj);
+
        return ret;
 }
 
index 958cf3cf082dcbef92a0d7926ff98d65a6484c23..87de15ea1f93fd72cc05ad358995b313d75a1b76 100644 (file)
@@ -101,7 +101,7 @@ static void mga_fillrect(struct fb_info *info,
                         const struct fb_fillrect *rect)
 {
        struct mga_fbdev *mfbdev = info->par;
-       sys_fillrect(info, rect);
+       drm_fb_helper_sys_fillrect(info, rect);
        mga_dirty_update(mfbdev, rect->dx, rect->dy, rect->width,
                         rect->height);
 }
@@ -110,7 +110,7 @@ static void mga_copyarea(struct fb_info *info,
                         const struct fb_copyarea *area)
 {
        struct mga_fbdev *mfbdev = info->par;
-       sys_copyarea(info, area);
+       drm_fb_helper_sys_copyarea(info, area);
        mga_dirty_update(mfbdev, area->dx, area->dy, area->width,
                         area->height);
 }
@@ -119,7 +119,7 @@ static void mga_imageblit(struct fb_info *info,
                          const struct fb_image *image)
 {
        struct mga_fbdev *mfbdev = info->par;
-       sys_imageblit(info, image);
+       drm_fb_helper_sys_imageblit(info, image);
        mga_dirty_update(mfbdev, image->dx, image->dy, image->width,
                         image->height);
 }
@@ -166,7 +166,6 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
        struct fb_info *info;
        struct drm_framebuffer *fb;
        struct drm_gem_object *gobj = NULL;
-       struct device *device = &dev->pdev->dev;
        int ret;
        void *sysram;
        int size;
@@ -189,9 +188,9 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
        if (!sysram)
                return -ENOMEM;
 
-       info = framebuffer_alloc(0, device);
-       if (info == NULL)
-               return -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info))
+               return PTR_ERR(info);
 
        info->par = mfbdev;
 
@@ -206,14 +205,6 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
 
        /* setup helper */
        mfbdev->helper.fb = fb;
-       mfbdev->helper.fbdev = info;
-
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
-               ret = -ENOMEM;
-               goto out;
-       }
 
        strcpy(info->fix.id, "mgadrmfb");
 
@@ -221,11 +212,6 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
        info->fbops = &mgag200fb_ops;
 
        /* setup aperture base/size for vesafb takeover */
-       info->apertures = alloc_apertures(1);
-       if (!info->apertures) {
-               ret = -ENOMEM;
-               goto out;
-       }
        info->apertures->ranges[0].base = mdev->dev->mode_config.fb_base;
        info->apertures->ranges[0].size = mdev->mc.vram_size;
 
@@ -240,24 +226,15 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
        DRM_DEBUG_KMS("allocated %dx%d\n",
                      fb->width, fb->height);
        return 0;
-out:
-       return ret;
 }
 
 static int mga_fbdev_destroy(struct drm_device *dev,
                                struct mga_fbdev *mfbdev)
 {
-       struct fb_info *info;
        struct mga_framebuffer *mfb = &mfbdev->mfb;
 
-       if (mfbdev->helper.fbdev) {
-               info = mfbdev->helper.fbdev;
-
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&mfbdev->helper);
+       drm_fb_helper_release_fbi(&mfbdev->helper);
 
        if (mfb->obj) {
                drm_gem_object_unreference_unlocked(mfb->obj);
index f6b283b8375ec7071adb32459a1bc2f6427dc2ad..c99c2cb2893907e0154cb73b4f354508502a197c 100644 (file)
@@ -345,23 +345,15 @@ mgag200_dumb_mmap_offset(struct drm_file *file,
                     uint64_t *offset)
 {
        struct drm_gem_object *obj;
-       int ret;
        struct mgag200_bo *bo;
 
-       mutex_lock(&dev->struct_mutex);
        obj = drm_gem_object_lookup(dev, file, handle);
-       if (obj == NULL) {
-               ret = -ENOENT;
-               goto out_unlock;
-       }
+       if (obj == NULL)
+               return -ENOENT;
 
        bo = gem_to_mga_bo(obj);
        *offset = mgag200_bo_mmap_offset(bo);
 
-       drm_gem_object_unreference(obj);
-       ret = 0;
-out_unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
-
+       drm_gem_object_unreference_unlocked(obj);
+       return 0;
 }
index c4bb9d9c7667e8453242fced07eae6d06c63bf74..4dc158ed2e9540ccb6358ce43aaec9d3adf8f1d1 100644 (file)
@@ -334,13 +334,15 @@ static int mdp4_crtc_atomic_check(struct drm_crtc *crtc,
        return 0;
 }
 
-static void mdp4_crtc_atomic_begin(struct drm_crtc *crtc)
+static void mdp4_crtc_atomic_begin(struct drm_crtc *crtc,
+                                  struct drm_crtc_state *old_crtc_state)
 {
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
        DBG("%s: begin", mdp4_crtc->name);
 }
 
-static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc)
+static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc,
+                                  struct drm_crtc_state *old_crtc_state)
 {
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
        struct drm_device *dev = crtc->dev;
index dea3d2e559b1cdf80c04cb35ca1fc3ae61ba3814..4c1df4e6e5bcaef44736a919b6e9382d7a3240a4 100644 (file)
@@ -388,13 +388,15 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
        return 0;
 }
 
-static void mdp5_crtc_atomic_begin(struct drm_crtc *crtc)
+static void mdp5_crtc_atomic_begin(struct drm_crtc *crtc,
+                                  struct drm_crtc_state *old_crtc_state)
 {
        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
        DBG("%s: begin", mdp5_crtc->name);
 }
 
-static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc)
+static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc,
+                                  struct drm_crtc_state *old_crtc_state)
 {
        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
        struct drm_device *dev = crtc->dev;
index 95f6532df02d9f9ab8eb8ff7da8b64a5f24a8349..f97a1964ef39494d9c9c2813482a33d4f7fc7a80 100644 (file)
@@ -43,11 +43,11 @@ static struct fb_ops msm_fb_ops = {
        /* Note: to properly handle manual update displays, we wrap the
         * basic fbdev ops which write to the framebuffer
         */
-       .fb_read = fb_sys_read,
-       .fb_write = fb_sys_write,
-       .fb_fillrect = sys_fillrect,
-       .fb_copyarea = sys_copyarea,
-       .fb_imageblit = sys_imageblit,
+       .fb_read = drm_fb_helper_sys_read,
+       .fb_write = drm_fb_helper_sys_write,
+       .fb_fillrect = drm_fb_helper_sys_fillrect,
+       .fb_copyarea = drm_fb_helper_sys_copyarea,
+       .fb_imageblit = drm_fb_helper_sys_imageblit,
        .fb_mmap = msm_fbdev_mmap,
 
        .fb_check_var = drm_fb_helper_check_var,
@@ -144,10 +144,10 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
                goto fail_unlock;
        }
 
-       fbi = framebuffer_alloc(0, dev->dev);
-       if (!fbi) {
+       fbi = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(fbi)) {
                dev_err(dev->dev, "failed to allocate fb info\n");
-               ret = -ENOMEM;
+               ret = PTR_ERR(fbi);
                goto fail_unlock;
        }
 
@@ -155,7 +155,6 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
 
        fbdev->fb = fb;
        helper->fb = fb;
-       helper->fbdev = fbi;
 
        fbi->par = helper;
        fbi->flags = FBINFO_DEFAULT;
@@ -163,12 +162,6 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
 
        strcpy(fbi->fix.id, "msm");
 
-       ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto fail_unlock;
-       }
-
        drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
 
@@ -191,7 +184,6 @@ fail_unlock:
 fail:
 
        if (ret) {
-               framebuffer_release(fbi);
                if (fb) {
                        drm_framebuffer_unregister_private(fb);
                        drm_framebuffer_remove(fb);
@@ -266,17 +258,11 @@ void msm_fbdev_free(struct drm_device *dev)
        struct msm_drm_private *priv = dev->dev_private;
        struct drm_fb_helper *helper = priv->fbdev;
        struct msm_fbdev *fbdev;
-       struct fb_info *fbi;
 
        DBG();
 
-       fbi = helper->fbdev;
-
-       /* only cleanup framebuffer if it is present */
-       if (fbi) {
-               unregister_framebuffer(fbi);
-               framebuffer_release(fbi);
-       }
+       drm_fb_helper_unregister_fbi(helper);
+       drm_fb_helper_release_fbi(helper);
 
        drm_fb_helper_fini(helper);
 
index 9f2498571d0953801e30108e439a473b4afff71c..5f6ea1873f517d1bbf357690b9fa817427ce91f1 100644 (file)
@@ -261,7 +261,7 @@ nv10_overlay_init(struct drm_device *device)
 {
        struct nouveau_drm *drm = nouveau_drm(device);
        struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
-       int num_formats = ARRAY_SIZE(formats);
+       unsigned int num_formats = ARRAY_SIZE(formats);
        int ret;
 
        if (!plane)
index 3162040bc3148b2157249dd29f945d8d05585812..1f26eba245d10b624ecdbab392ed7ef30f0d163d 100644 (file)
@@ -919,7 +919,7 @@ nouveau_connector_funcs_lvds = {
        .force = nouveau_connector_force
 };
 
-static void
+static int
 nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
 {
        struct nouveau_encoder *nv_encoder = NULL;
@@ -938,7 +938,7 @@ nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
                }
        }
 
-       drm_helper_connector_dpms(connector, mode);
+       return drm_helper_connector_dpms(connector, mode);
 }
 
 static const struct drm_connector_funcs
index 6751553abe4afe4bc408cd08863a7981b858bece..2791701685dc82bf4e2655ce3ea8ea6c3b278e49 100644 (file)
@@ -84,7 +84,7 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 
        if (ret != -ENODEV)
                nouveau_fbcon_gpu_lockup(info);
-       cfb_fillrect(info, rect);
+       drm_fb_helper_cfb_fillrect(info, rect);
 }
 
 static void
@@ -116,7 +116,7 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
 
        if (ret != -ENODEV)
                nouveau_fbcon_gpu_lockup(info);
-       cfb_copyarea(info, image);
+       drm_fb_helper_cfb_copyarea(info, image);
 }
 
 static void
@@ -148,7 +148,7 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
 
        if (ret != -ENODEV)
                nouveau_fbcon_gpu_lockup(info);
-       cfb_imageblit(info, image);
+       drm_fb_helper_cfb_imageblit(info, image);
 }
 
 static int
@@ -197,9 +197,9 @@ static struct fb_ops nouveau_fbcon_sw_ops = {
        .owner = THIS_MODULE,
        .fb_check_var = drm_fb_helper_check_var,
        .fb_set_par = drm_fb_helper_set_par,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = cfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
+       .fb_fillrect = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit = drm_fb_helper_cfb_imageblit,
        .fb_pan_display = drm_fb_helper_pan_display,
        .fb_blank = drm_fb_helper_blank,
        .fb_setcmap = drm_fb_helper_setcmap,
@@ -319,7 +319,6 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
        struct nouveau_channel *chan;
        struct nouveau_bo *nvbo;
        struct drm_mode_fb_cmd2 mode_cmd;
-       struct pci_dev *pdev = dev->pdev;
        int size, ret;
 
        mode_cmd.width = sizes->surface_width;
@@ -365,20 +364,13 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
 
        mutex_lock(&dev->struct_mutex);
 
-       info = framebuffer_alloc(0, &pdev->dev);
-       if (!info) {
-               ret = -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
                goto out_unlock;
        }
        info->skip_vt_switch = 1;
 
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               framebuffer_release(info);
-               goto out_unlock;
-       }
-
        info->par = fbcon;
 
        nouveau_framebuffer_init(dev, &fbcon->nouveau_fb, &mode_cmd, nvbo);
@@ -388,7 +380,6 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
 
        /* setup helper */
        fbcon->helper.fb = fb;
-       fbcon->helper.fbdev = info;
 
        strcpy(info->fix.id, "nouveaufb");
        if (!chan)
@@ -450,15 +441,9 @@ static int
 nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
 {
        struct nouveau_framebuffer *nouveau_fb = &fbcon->nouveau_fb;
-       struct fb_info *info;
 
-       if (fbcon->helper.fbdev) {
-               info = fbcon->helper.fbdev;
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&fbcon->helper);
+       drm_fb_helper_release_fbi(&fbcon->helper);
 
        if (nouveau_fb->nvbo) {
                nouveau_bo_unmap(nouveau_fb->nvbo);
@@ -496,7 +481,7 @@ nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
                console_lock();
                if (state == FBINFO_STATE_RUNNING)
                        nouveau_fbcon_accel_restore(dev);
-               fb_set_suspend(drm->fbcon->helper.fbdev, state);
+               drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
                if (state != FBINFO_STATE_RUNNING)
                        nouveau_fbcon_accel_save_disable(dev);
                console_unlock();
index 18f4497157885a897a9cbec14c390d397a02ca25..1f8ec0e2156cade9705e39a546ff719cdc0835ae 100644 (file)
@@ -424,10 +424,8 @@ nouveau_ttm_init(struct nouveau_drm *drm)
 void
 nouveau_ttm_fini(struct nouveau_drm *drm)
 {
-       mutex_lock(&drm->dev->struct_mutex);
        ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_VRAM);
        ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_TT);
-       mutex_unlock(&drm->dev->struct_mutex);
 
        ttm_bo_device_release(&drm->ttm.bdev);
 
index 23d9c928cdc91b44c20efd05fd361e85f20089f3..9a4ba4f035673e859c6687fcc76bc507b4ab8996 100644 (file)
@@ -388,11 +388,13 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
        copy_timings_drm_to_omap(&omap_crtc->timings, mode);
 }
 
-static void omap_crtc_atomic_begin(struct drm_crtc *crtc)
+static void omap_crtc_atomic_begin(struct drm_crtc *crtc,
+                                  struct drm_crtc_state *old_crtc_state)
 {
 }
 
-static void omap_crtc_atomic_flush(struct drm_crtc *crtc)
+static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
+                                  struct drm_crtc_state *old_crtc_state)
 {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 
index 720d16bce7e82b790a7aff17f5bbec94b6df18fe..b8e4cdec28c363c7e5c10881be4ea61461023ace 100644 (file)
@@ -86,11 +86,11 @@ static struct fb_ops omap_fb_ops = {
        /* Note: to properly handle manual update displays, we wrap the
         * basic fbdev ops which write to the framebuffer
         */
-       .fb_read = fb_sys_read,
-       .fb_write = fb_sys_write,
-       .fb_fillrect = sys_fillrect,
-       .fb_copyarea = sys_copyarea,
-       .fb_imageblit = sys_imageblit,
+       .fb_read = drm_fb_helper_sys_read,
+       .fb_write = drm_fb_helper_sys_write,
+       .fb_fillrect = drm_fb_helper_sys_fillrect,
+       .fb_copyarea = drm_fb_helper_sys_copyarea,
+       .fb_imageblit = drm_fb_helper_sys_imageblit,
 
        .fb_check_var = drm_fb_helper_check_var,
        .fb_set_par = drm_fb_helper_set_par,
@@ -179,10 +179,10 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
 
        mutex_lock(&dev->struct_mutex);
 
-       fbi = framebuffer_alloc(0, dev->dev);
-       if (!fbi) {
+       fbi = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(fbi)) {
                dev_err(dev->dev, "failed to allocate fb info\n");
-               ret = -ENOMEM;
+               ret = PTR_ERR(fbi);
                goto fail_unlock;
        }
 
@@ -190,7 +190,6 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
 
        fbdev->fb = fb;
        helper->fb = fb;
-       helper->fbdev = fbi;
 
        fbi->par = helper;
        fbi->flags = FBINFO_DEFAULT;
@@ -198,12 +197,6 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
 
        strcpy(fbi->fix.id, MODULE_NAME);
 
-       ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto fail_unlock;
-       }
-
        drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
 
@@ -236,8 +229,9 @@ fail_unlock:
 fail:
 
        if (ret) {
-               if (fbi)
-                       framebuffer_release(fbi);
+
+               drm_fb_helper_release_fbi(helper);
+
                if (fb) {
                        drm_framebuffer_unregister_private(fb);
                        drm_framebuffer_remove(fb);
@@ -312,17 +306,11 @@ void omap_fbdev_free(struct drm_device *dev)
        struct omap_drm_private *priv = dev->dev_private;
        struct drm_fb_helper *helper = priv->fbdev;
        struct omap_fbdev *fbdev;
-       struct fb_info *fbi;
 
        DBG();
 
-       fbi = helper->fbdev;
-
-       /* only cleanup framebuffer if it is present */
-       if (fbi) {
-               unregister_framebuffer(fbi);
-               framebuffer_release(fbi);
-       }
+       drm_fb_helper_unregister_fbi(helper);
+       drm_fb_helper_release_fbi(helper);
 
        drm_fb_helper_fini(helper);
 
index 6b6e57e8c2d6292255d2cb1438f1ec36025511e4..41c422fee31a02dbc932964bc4686921e533fdd3 100644 (file)
@@ -197,7 +197,7 @@ static void qxl_fb_fillrect(struct fb_info *info,
 {
        struct qxl_fbdev *qfbdev = info->par;
 
-       sys_fillrect(info, rect);
+       drm_fb_helper_sys_fillrect(info, rect);
        qxl_dirty_update(qfbdev, rect->dx, rect->dy, rect->width,
                         rect->height);
 }
@@ -207,7 +207,7 @@ static void qxl_fb_copyarea(struct fb_info *info,
 {
        struct qxl_fbdev *qfbdev = info->par;
 
-       sys_copyarea(info, area);
+       drm_fb_helper_sys_copyarea(info, area);
        qxl_dirty_update(qfbdev, area->dx, area->dy, area->width,
                         area->height);
 }
@@ -217,7 +217,7 @@ static void qxl_fb_imageblit(struct fb_info *info,
 {
        struct qxl_fbdev *qfbdev = info->par;
 
-       sys_imageblit(info, image);
+       drm_fb_helper_sys_imageblit(info, image);
        qxl_dirty_update(qfbdev, image->dx, image->dy, image->width,
                         image->height);
 }
@@ -345,7 +345,6 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
        struct drm_mode_fb_cmd2 mode_cmd;
        struct drm_gem_object *gobj = NULL;
        struct qxl_bo *qbo = NULL;
-       struct device *device = &qdev->pdev->dev;
        int ret;
        int size;
        int bpp = sizes->surface_bpp;
@@ -374,9 +373,9 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
                 shadow);
        size = mode_cmd.pitches[0] * mode_cmd.height;
 
-       info = framebuffer_alloc(0, device);
-       if (info == NULL) {
-               ret = -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(&qfbdev->helper);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
                goto out_unref;
        }
 
@@ -388,7 +387,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
 
        /* setup helper with fb data */
        qfbdev->helper.fb = fb;
-       qfbdev->helper.fbdev = info;
+
        qfbdev->shadow = shadow;
        strcpy(info->fix.id, "qxldrmfb");
 
@@ -410,11 +409,6 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
                               sizes->fb_height);
 
        /* setup aperture base/size for vesafb takeover */
-       info->apertures = alloc_apertures(1);
-       if (!info->apertures) {
-               ret = -ENOMEM;
-               goto out_unref;
-       }
        info->apertures->ranges[0].base = qdev->ddev->mode_config.fb_base;
        info->apertures->ranges[0].size = qdev->vram_size;
 
@@ -423,13 +417,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
 
        if (info->screen_base == NULL) {
                ret = -ENOSPC;
-               goto out_unref;
-       }
-
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto out_unref;
+               goto out_destroy_fbi;
        }
 
        info->fbdefio = &qxl_defio;
@@ -441,6 +429,8 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
        DRM_INFO("fb: depth %d, pitch %d, width %d, height %d\n", fb->depth, fb->pitches[0], fb->width, fb->height);
        return 0;
 
+out_destroy_fbi:
+       drm_fb_helper_release_fbi(&qfbdev->helper);
 out_unref:
        if (qbo) {
                ret = qxl_bo_reserve(qbo, false);
@@ -479,15 +469,11 @@ static int qxl_fb_find_or_create_single(
 
 static int qxl_fbdev_destroy(struct drm_device *dev, struct qxl_fbdev *qfbdev)
 {
-       struct fb_info *info;
        struct qxl_framebuffer *qfb = &qfbdev->qfb;
 
-       if (qfbdev->helper.fbdev) {
-               info = qfbdev->helper.fbdev;
+       drm_fb_helper_unregister_fbi(&qfbdev->helper);
+       drm_fb_helper_release_fbi(&qfbdev->helper);
 
-               unregister_framebuffer(info);
-               framebuffer_release(info);
-       }
        if (qfb->obj) {
                qxlfb_destroy_pinned_object(qfb->obj);
                qfb->obj = NULL;
@@ -557,7 +543,7 @@ void qxl_fbdev_fini(struct qxl_device *qdev)
 
 void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state)
 {
-       fb_set_suspend(qdev->mode_info.qfbdev->helper.fbdev, state);
+       drm_fb_helper_set_suspend(&qdev->mode_info.qfbdev->helper, state);
 }
 
 bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj)
index 6d6f33de48f48a93da1a0eadf681c5ac46874b4a..b28370e014c6c0b1547c5d88378d4d161e80a935 100644 (file)
@@ -272,7 +272,6 @@ void qxl_bo_force_delete(struct qxl_device *qdev)
                return;
        dev_err(qdev->dev, "Userspace still has active objects !\n");
        list_for_each_entry_safe(bo, n, &qdev->gem.objects, list) {
-               mutex_lock(&qdev->ddev->struct_mutex);
                dev_err(qdev->dev, "%p %p %lu %lu force free\n",
                        &bo->gem_base, bo, (unsigned long)bo->gem_base.size,
                        *((unsigned long *)&bo->gem_base.refcount));
@@ -280,8 +279,7 @@ void qxl_bo_force_delete(struct qxl_device *qdev)
                list_del_init(&bo->list);
                mutex_unlock(&qdev->gem.mutex);
                /* this should unref the ttm bo */
-               drm_gem_object_unreference(&bo->gem_base);
-               mutex_unlock(&qdev->ddev->struct_mutex);
+               drm_gem_object_unreference_unlocked(&bo->gem_base);
        }
 }
 
index e4fc8f3bf58b09175c0d1dc868b2ce52327c4c18..5e09c061847f50c688650d12625a462e8c4737cd 100644 (file)
@@ -246,9 +246,10 @@ radeon_dp_mst_connector_destroy(struct drm_connector *connector)
        kfree(radeon_connector);
 }
 
-static void radeon_connector_dpms(struct drm_connector *connector, int mode)
+static int radeon_connector_dpms(struct drm_connector *connector, int mode)
 {
        DRM_DEBUG_KMS("\n");
+       return 0;
 }
 
 static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = {
index aeb676708e60cfb1871326bfc5a689631bb98741..7214858ffceaa8c20409206533dcc332fd663705 100644 (file)
@@ -82,9 +82,9 @@ static struct fb_ops radeonfb_ops = {
        .owner = THIS_MODULE,
        .fb_check_var = drm_fb_helper_check_var,
        .fb_set_par = radeon_fb_helper_set_par,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = cfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
+       .fb_fillrect = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit = drm_fb_helper_cfb_imageblit,
        .fb_pan_display = drm_fb_helper_pan_display,
        .fb_blank = drm_fb_helper_blank,
        .fb_setcmap = drm_fb_helper_setcmap,
@@ -227,7 +227,6 @@ static int radeonfb_create(struct drm_fb_helper *helper,
        struct drm_mode_fb_cmd2 mode_cmd;
        struct drm_gem_object *gobj = NULL;
        struct radeon_bo *rbo = NULL;
-       struct device *device = &rdev->pdev->dev;
        int ret;
        unsigned long tmp;
 
@@ -250,9 +249,9 @@ static int radeonfb_create(struct drm_fb_helper *helper,
        rbo = gem_to_radeon_bo(gobj);
 
        /* okay we have an object now allocate the framebuffer */
-       info = framebuffer_alloc(0, device);
-       if (info == NULL) {
-               ret = -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
                goto out_unref;
        }
 
@@ -262,14 +261,13 @@ static int radeonfb_create(struct drm_fb_helper *helper,
        ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
        if (ret) {
                DRM_ERROR("failed to initialize framebuffer %d\n", ret);
-               goto out_unref;
+               goto out_destroy_fbi;
        }
 
        fb = &rfbdev->rfb.base;
 
        /* setup helper */
        rfbdev->helper.fb = fb;
-       rfbdev->helper.fbdev = info;
 
        memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo));
 
@@ -289,11 +287,6 @@ static int radeonfb_create(struct drm_fb_helper *helper,
        drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height);
 
        /* setup aperture base/size for vesafb takeover */
-       info->apertures = alloc_apertures(1);
-       if (!info->apertures) {
-               ret = -ENOMEM;
-               goto out_unref;
-       }
        info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
        info->apertures->ranges[0].size = rdev->mc.aper_size;
 
@@ -301,13 +294,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
 
        if (info->screen_base == NULL) {
                ret = -ENOSPC;
-               goto out_unref;
-       }
-
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto out_unref;
+               goto out_destroy_fbi;
        }
 
        DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
@@ -319,6 +306,8 @@ static int radeonfb_create(struct drm_fb_helper *helper,
        vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
        return 0;
 
+out_destroy_fbi:
+       drm_fb_helper_release_fbi(helper);
 out_unref:
        if (rbo) {
 
@@ -339,17 +328,10 @@ void radeon_fb_output_poll_changed(struct radeon_device *rdev)
 
 static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev)
 {
-       struct fb_info *info;
        struct radeon_framebuffer *rfb = &rfbdev->rfb;
 
-       if (rfbdev->helper.fbdev) {
-               info = rfbdev->helper.fbdev;
-
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&rfbdev->helper);
+       drm_fb_helper_release_fbi(&rfbdev->helper);
 
        if (rfb->obj) {
                radeonfb_destroy_pinned_object(rfb->obj);
index 65d6ba6621aca5b1883ac8a4a57a93a92e0ca913..48cb19949ca3f01eeb365b3a1dadc30509888cfd 100644 (file)
@@ -496,7 +496,8 @@ static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc,
        return true;
 }
 
-static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc)
+static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
+                                     struct drm_crtc_state *old_crtc_state)
 {
        struct drm_pending_vblank_event *event = crtc->state->event;
        struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
@@ -512,7 +513,8 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc)
        }
 }
 
-static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc)
+static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
+                                     struct drm_crtc_state *old_crtc_state)
 {
        struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
 
index 5b0dc0f6fd940f7d6689f832e03c0c3cd1048656..f261512bb4a03539f55e40b0e545c3ee8469c57e 100644 (file)
@@ -37,9 +37,9 @@ static int rockchip_fbdev_mmap(struct fb_info *info,
 static struct fb_ops rockchip_drm_fbdev_ops = {
        .owner          = THIS_MODULE,
        .fb_mmap        = rockchip_fbdev_mmap,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
+       .fb_fillrect    = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea    = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit   = drm_fb_helper_cfb_imageblit,
        .fb_check_var   = drm_fb_helper_check_var,
        .fb_set_par     = drm_fb_helper_set_par,
        .fb_blank       = drm_fb_helper_blank,
@@ -77,10 +77,10 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
 
        private->fbdev_bo = &rk_obj->base;
 
-       fbi = framebuffer_alloc(0, dev->dev);
-       if (!fbi) {
-               dev_err(dev->dev, "Failed to allocate framebuffer info.\n");
-               ret = -ENOMEM;
+       fbi = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(fbi)) {
+               dev_err(dev->dev, "Failed to create framebuffer info.\n");
+               ret = PTR_ERR(fbi);
                goto err_rockchip_gem_free_object;
        }
 
@@ -89,21 +89,13 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
        if (IS_ERR(helper->fb)) {
                dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
                ret = PTR_ERR(helper->fb);
-               goto err_framebuffer_release;
+               goto err_release_fbi;
        }
 
-       helper->fbdev = fbi;
-
        fbi->par = helper;
        fbi->flags = FBINFO_FLAG_DEFAULT;
        fbi->fbops = &rockchip_drm_fbdev_ops;
 
-       ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
-       if (ret) {
-               dev_err(dev->dev, "Failed to allocate color map.\n");
-               goto err_drm_framebuffer_unref;
-       }
-
        fb = helper->fb;
        drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
@@ -124,10 +116,8 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
 
        return 0;
 
-err_drm_framebuffer_unref:
-       drm_framebuffer_unreference(helper->fb);
-err_framebuffer_release:
-       framebuffer_release(fbi);
+err_release_fbi:
+       drm_fb_helper_release_fbi(helper);
 err_rockchip_gem_free_object:
        rockchip_gem_free_object(&rk_obj->base);
        return ret;
@@ -190,21 +180,8 @@ void rockchip_drm_fbdev_fini(struct drm_device *dev)
 
        helper = &private->fbdev_helper;
 
-       if (helper->fbdev) {
-               struct fb_info *info;
-               int ret;
-
-               info = helper->fbdev;
-               ret = unregister_framebuffer(info);
-               if (ret < 0)
-                       DRM_DEBUG_KMS("failed unregister_framebuffer() - %d\n",
-                                     ret);
-
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(helper);
+       drm_fb_helper_release_fbi(helper);
 
        if (helper->fb)
                drm_framebuffer_unreference(helper->fb);
index eba5f8a52fbd9ff2bf7941687f54e11320cb10b3..a6d9104f7f157f55426843690dee62c00e97cb4b 100644 (file)
@@ -200,13 +200,10 @@ int rockchip_gem_dumb_map_offset(struct drm_file *file_priv,
        struct drm_gem_object *obj;
        int ret;
 
-       mutex_lock(&dev->struct_mutex);
-
        obj = drm_gem_object_lookup(dev, file_priv, handle);
        if (!obj) {
                DRM_ERROR("failed to lookup gem object.\n");
-               ret = -EINVAL;
-               goto unlock;
+               return -EINVAL;
        }
 
        ret = drm_gem_create_mmap_offset(obj);
@@ -217,10 +214,9 @@ int rockchip_gem_dumb_map_offset(struct drm_file *file_priv,
        DRM_DEBUG_KMS("offset = 0x%llx\n", *offset);
 
 out:
-       drm_gem_object_unreference(obj);
-unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
+       drm_gem_object_unreference_unlocked(obj);
+
+       return 0;
 }
 
 /*
index f0f1e4ee2d922060d579e40ed2f664576f94a1d5..e27490b492a5280a254b9a196d452f429abb9466 100644 (file)
@@ -1,12 +1,11 @@
 sticompositor-y := \
-       sti_layer.o \
        sti_mixer.o \
        sti_gdp.o \
        sti_vid.o \
        sti_cursor.o \
        sti_compositor.o \
-       sti_drm_crtc.o \
-       sti_drm_plane.o
+       sti_crtc.o \
+       sti_plane.o
 
 stihdmi-y := sti_hdmi.o \
        sti_hdmi_tx3g0c55phy.o \
@@ -24,4 +23,4 @@ obj-$(CONFIG_DRM_STI) = \
        sticompositor.o \
        sti_hqvdp.o \
        stidvo.o \
-       sti_drm_drv.o
+       sti_drv.o
index 43215d3020fb6e8060d2fd2fb48e0e50b3c28c47..c652627b1bcadbe05a1a759677724f7be8819c0a 100644 (file)
 #include <drm/drmP.h>
 
 #include "sti_compositor.h"
-#include "sti_drm_crtc.h"
-#include "sti_drm_drv.h"
-#include "sti_drm_plane.h"
+#include "sti_crtc.h"
+#include "sti_cursor.h"
+#include "sti_drv.h"
 #include "sti_gdp.h"
+#include "sti_plane.h"
+#include "sti_vid.h"
 #include "sti_vtg.h"
 
 /*
@@ -31,7 +33,7 @@ struct sti_compositor_data stih407_compositor_data = {
                        {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
                        {STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300},
                        {STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400},
-                       {STI_VID_SUBDEV, (int)STI_VID_0, 0x700},
+                       {STI_VID_SUBDEV, (int)STI_HQVDP_0, 0x700},
                        {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00},
                        {STI_MIXER_AUX_SUBDEV, STI_MIXER_AUX, 0xD00},
        },
@@ -53,14 +55,29 @@ struct sti_compositor_data stih416_compositor_data = {
        },
 };
 
-static int sti_compositor_init_subdev(struct sti_compositor *compo,
-               struct sti_compositor_subdev_descriptor *desc,
-               unsigned int array_size)
+static int sti_compositor_bind(struct device *dev,
+                              struct device *master,
+                              void *data)
 {
-       unsigned int i, mixer_id = 0, layer_id = 0;
+       struct sti_compositor *compo = dev_get_drvdata(dev);
+       struct drm_device *drm_dev = data;
+       unsigned int i, mixer_id = 0, vid_id = 0, crtc_id = 0;
+       struct sti_private *dev_priv = drm_dev->dev_private;
+       struct drm_plane *cursor = NULL;
+       struct drm_plane *primary = NULL;
+       struct sti_compositor_subdev_descriptor *desc = compo->data.subdev_desc;
+       unsigned int array_size = compo->data.nb_subdev;
+
+       dev_priv->compo = compo;
 
+       /* Register mixer subdev and video subdev first */
        for (i = 0; i < array_size; i++) {
                switch (desc[i].type) {
+               case STI_VID_SUBDEV:
+                       compo->vid[vid_id++] =
+                           sti_vid_create(compo->dev, desc[i].id,
+                                          compo->regs + desc[i].offset);
+                       break;
                case STI_MIXER_MAIN_SUBDEV:
                case STI_MIXER_AUX_SUBDEV:
                        compo->mixer[mixer_id++] =
@@ -68,83 +85,68 @@ static int sti_compositor_init_subdev(struct sti_compositor *compo,
                                             compo->regs + desc[i].offset);
                        break;
                case STI_GPD_SUBDEV:
-               case STI_VID_SUBDEV:
                case STI_CURSOR_SUBDEV:
-                       compo->layer[layer_id++] =
-                           sti_layer_create(compo->dev, desc[i].id,
-                                            compo->regs + desc[i].offset);
+                       /* Nothing to do, wait for the second round */
                        break;
                default:
                        DRM_ERROR("Unknow subdev compoment type\n");
                        return 1;
                }
-
        }
-       compo->nb_mixers = mixer_id;
-       compo->nb_layers = layer_id;
-
-       return 0;
-}
-
-static int sti_compositor_bind(struct device *dev, struct device *master,
-       void *data)
-{
-       struct sti_compositor *compo = dev_get_drvdata(dev);
-       struct drm_device *drm_dev = data;
-       unsigned int i, crtc = 0, plane = 0;
-       struct sti_drm_private *dev_priv = drm_dev->dev_private;
-       struct drm_plane *cursor = NULL;
-       struct drm_plane *primary = NULL;
 
-       dev_priv->compo = compo;
-
-       for (i = 0; i < compo->nb_layers; i++) {
-               if (compo->layer[i]) {
-                       enum sti_layer_desc desc = compo->layer[i]->desc;
-                       enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK;
-                       enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;
+       /* Register the other subdevs, create crtc and planes */
+       for (i = 0; i < array_size; i++) {
+               enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;
 
-                       if (crtc < compo->nb_mixers)
-                               plane_type = DRM_PLANE_TYPE_PRIMARY;
+               if (crtc_id < mixer_id)
+                       plane_type = DRM_PLANE_TYPE_PRIMARY;
 
-                       switch (type) {
-                       case STI_CUR:
-                               cursor = sti_drm_plane_init(drm_dev,
-                                               compo->layer[i],
-                                               1, DRM_PLANE_TYPE_CURSOR);
-                               break;
-                       case STI_GDP:
-                       case STI_VID:
-                               primary = sti_drm_plane_init(drm_dev,
-                                               compo->layer[i],
-                                               (1 << compo->nb_mixers) - 1,
-                                               plane_type);
-                               plane++;
+               switch (desc[i].type) {
+               case STI_MIXER_MAIN_SUBDEV:
+               case STI_MIXER_AUX_SUBDEV:
+               case STI_VID_SUBDEV:
+                       /* Nothing to do, already done at the first round */
+                       break;
+               case STI_CURSOR_SUBDEV:
+                       cursor = sti_cursor_create(drm_dev, compo->dev,
+                                                  desc[i].id,
+                                                  compo->regs + desc[i].offset,
+                                                  1);
+                       if (!cursor) {
+                               DRM_ERROR("Can't create CURSOR plane\n");
                                break;
-                       case STI_BCK:
-                       case STI_VDP:
+                       }
+                       break;
+               case STI_GPD_SUBDEV:
+                       primary = sti_gdp_create(drm_dev, compo->dev,
+                                                desc[i].id,
+                                                compo->regs + desc[i].offset,
+                                                (1 << mixer_id) - 1,
+                                                plane_type);
+                       if (!primary) {
+                               DRM_ERROR("Can't create GDP plane\n");
                                break;
                        }
+                       break;
+               default:
+                       DRM_ERROR("Unknown subdev compoment type\n");
+                       return 1;
+               }
 
-                       /* The first planes are reserved for primary planes*/
-                       if (crtc < compo->nb_mixers && primary) {
-                               sti_drm_crtc_init(drm_dev, compo->mixer[crtc],
-                                               primary, cursor);
-                               crtc++;
-                               cursor = NULL;
-                               primary = NULL;
-                       }
+               /* The first planes are reserved for primary planes*/
+               if (crtc_id < mixer_id && primary) {
+                       sti_crtc_init(drm_dev, compo->mixer[crtc_id],
+                                     primary, cursor);
+                       crtc_id++;
+                       cursor = NULL;
+                       primary = NULL;
                }
        }
 
-       drm_vblank_init(drm_dev, crtc);
+       drm_vblank_init(drm_dev, crtc_id);
        /* Allow usage of vblank without having to call drm_irq_install */
        drm_dev->irq_enabled = 1;
 
-       DRM_DEBUG_DRIVER("Initialized %d DRM CRTC(s) and %d DRM plane(s)\n",
-                        crtc, plane);
-       DRM_DEBUG_DRIVER("DRM plane(s) for VID/VDP not created yet\n");
-
        return 0;
 }
 
@@ -179,7 +181,6 @@ static int sti_compositor_probe(struct platform_device *pdev)
        struct device_node *vtg_np;
        struct sti_compositor *compo;
        struct resource *res;
-       int err;
 
        compo = devm_kzalloc(dev, sizeof(*compo), GFP_KERNEL);
        if (!compo) {
@@ -187,7 +188,7 @@ static int sti_compositor_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        compo->dev = dev;
-       compo->vtg_vblank_nb.notifier_call = sti_drm_crtc_vblank_cb;
+       compo->vtg_vblank_nb.notifier_call = sti_crtc_vblank_cb;
 
        /* populate data structure depending on compatibility */
        BUG_ON(!of_match_node(compositor_of_match, np)->data);
@@ -251,12 +252,6 @@ static int sti_compositor_probe(struct platform_device *pdev)
        if (vtg_np)
                compo->vtg_aux = of_vtg_find(vtg_np);
 
-       /* Initialize compositor subdevices */
-       err = sti_compositor_init_subdev(compo, compo->data.subdev_desc,
-                                        compo->data.nb_subdev);
-       if (err)
-               return err;
-
        platform_set_drvdata(pdev, compo);
 
        return component_add(&pdev->dev, &sti_compositor_ops);
index 019eb44c62cc4c51923dac410f67c158613ff6f4..1a4a73dab11e94f8451ec8f4805894b2d99a6a57 100644 (file)
 #include <linux/clk.h>
 #include <linux/kernel.h>
 
-#include "sti_layer.h"
 #include "sti_mixer.h"
+#include "sti_plane.h"
 
 #define WAIT_NEXT_VSYNC_MS      50 /*ms*/
 
-#define STI_MAX_LAYER 8
 #define STI_MAX_MIXER 2
+#define STI_MAX_VID   1
 
 enum sti_compositor_subdev_type {
        STI_MIXER_MAIN_SUBDEV,
@@ -59,11 +59,9 @@ struct sti_compositor_data {
  * @rst_main: reset control of the main path
  * @rst_aux: reset control of the aux path
  * @mixer: array of mixers
+ * @vid: array of vids
  * @vtg_main: vtg for main data path
  * @vtg_aux: vtg for auxillary data path
- * @layer: array of layers
- * @nb_mixers: number of mixers for this compositor
- * @nb_layers: number of layers (GDP,VID,...) for this compositor
  * @vtg_vblank_nb: callback for VTG VSYNC notification
  */
 struct sti_compositor {
@@ -77,11 +75,9 @@ struct sti_compositor {
        struct reset_control *rst_main;
        struct reset_control *rst_aux;
        struct sti_mixer *mixer[STI_MAX_MIXER];
+       struct sti_vid *vid[STI_MAX_VID];
        struct sti_vtg *vtg_main;
        struct sti_vtg *vtg_aux;
-       struct sti_layer *layer[STI_MAX_LAYER];
-       int nb_mixers;
-       int nb_layers;
        struct notifier_block vtg_vblank_nb;
 };
 
similarity index 56%
rename from drivers/gpu/drm/sti/sti_drm_crtc.c
rename to drivers/gpu/drm/sti/sti_crtc.c
index 6b641c5a2ec7d10609f20a38cbe6bab56c9f4c5e..018ffc970e96e6cd209935c2e6c5f480a4676ebb 100644 (file)
 #include <drm/drm_plane_helper.h>
 
 #include "sti_compositor.h"
-#include "sti_drm_drv.h"
-#include "sti_drm_crtc.h"
+#include "sti_crtc.h"
+#include "sti_drv.h"
+#include "sti_vid.h"
 #include "sti_vtg.h"
 
-static void sti_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-       DRM_DEBUG_KMS("\n");
-}
-
-static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
+static void sti_crtc_enable(struct drm_crtc *crtc)
 {
        struct sti_mixer *mixer = to_sti_mixer(crtc);
        struct device *dev = mixer->dev;
        struct sti_compositor *compo = dev_get_drvdata(dev);
 
-       mixer->enabled = true;
+       DRM_DEBUG_DRIVER("\n");
+
+       mixer->status = STI_MIXER_READY;
 
        /* Prepare and enable the compo IP clock */
        if (mixer->id == STI_MIXER_MAIN) {
@@ -41,45 +39,28 @@ static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
                        DRM_INFO("Failed to prepare/enable compo_aux clk\n");
        }
 
-       sti_mixer_clear_all_layers(mixer);
+       drm_crtc_vblank_on(crtc);
 }
 
-static void sti_drm_crtc_commit(struct drm_crtc *crtc)
+static void sti_crtc_disabling(struct drm_crtc *crtc)
 {
        struct sti_mixer *mixer = to_sti_mixer(crtc);
-       struct device *dev = mixer->dev;
-       struct sti_compositor *compo = dev_get_drvdata(dev);
-       struct sti_layer *layer;
-
-       if ((!mixer || !compo)) {
-               DRM_ERROR("Can not find mixer or compositor)\n");
-               return;
-       }
 
-       /* get GDP which is reserved to the CRTC FB */
-       layer = to_sti_layer(crtc->primary);
-       if (layer)
-               sti_layer_commit(layer);
-       else
-               DRM_ERROR("Can not find CRTC dedicated plane (GDP0)\n");
-
-       /* Enable layer on mixer */
-       if (sti_mixer_set_layer_status(mixer, layer, true))
-               DRM_ERROR("Can not enable layer at mixer\n");
+       DRM_DEBUG_DRIVER("\n");
 
-       drm_crtc_vblank_on(crtc);
+       mixer->status = STI_MIXER_DISABLING;
 }
 
-static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc,
-                                   const struct drm_display_mode *mode,
-                                   struct drm_display_mode *adjusted_mode)
+static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
+                               const struct drm_display_mode *mode,
+                               struct drm_display_mode *adjusted_mode)
 {
        /* accept the provided drm_display_mode, do not fix it up */
        return true;
 }
 
 static int
-sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
+sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
 {
        struct sti_mixer *mixer = to_sti_mixer(crtc);
        struct device *dev = mixer->dev;
@@ -122,22 +103,19 @@ sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
 
        res = sti_mixer_active_video_area(mixer, &crtc->mode);
        if (res) {
-               DRM_ERROR("Can not set active video area\n");
+               DRM_ERROR("Can't set active video area\n");
                return -EINVAL;
        }
 
        return res;
 }
 
-static void sti_drm_crtc_disable(struct drm_crtc *crtc)
+static void sti_crtc_disable(struct drm_crtc *crtc)
 {
        struct sti_mixer *mixer = to_sti_mixer(crtc);
        struct device *dev = mixer->dev;
        struct sti_compositor *compo = dev_get_drvdata(dev);
 
-       if (!mixer->enabled)
-               return;
-
        DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
 
        /* Disable Background */
@@ -154,17 +132,18 @@ static void sti_drm_crtc_disable(struct drm_crtc *crtc)
                clk_disable_unprepare(compo->clk_compo_aux);
        }
 
-       mixer->enabled = false;
+       mixer->status = STI_MIXER_DISABLED;
 }
 
 static void
-sti_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
+sti_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
-       sti_drm_crtc_prepare(crtc);
-       sti_drm_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
+       sti_crtc_enable(crtc);
+       sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
 }
 
-static void sti_drm_atomic_begin(struct drm_crtc *crtc)
+static void sti_crtc_atomic_begin(struct drm_crtc *crtc,
+                                 struct drm_crtc_state *old_crtc_state)
 {
        struct sti_mixer *mixer = to_sti_mixer(crtc);
 
@@ -178,46 +157,109 @@ static void sti_drm_atomic_begin(struct drm_crtc *crtc)
        }
 }
 
-static void sti_drm_atomic_flush(struct drm_crtc *crtc)
+static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
+                                 struct drm_crtc_state *old_crtc_state)
 {
+       struct drm_device *drm_dev = crtc->dev;
+       struct sti_mixer *mixer = to_sti_mixer(crtc);
+       struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
+       struct drm_plane *p;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       /* perform plane actions */
+       list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
+               struct sti_plane *plane = to_sti_plane(p);
+
+               switch (plane->status) {
+               case STI_PLANE_UPDATED:
+                       /* update planes tag as updated */
+                       DRM_DEBUG_DRIVER("update plane %s\n",
+                                        sti_plane_to_str(plane));
+
+                       if (sti_mixer_set_plane_depth(mixer, plane)) {
+                               DRM_ERROR("Cannot set plane %s depth\n",
+                                         sti_plane_to_str(plane));
+                               break;
+                       }
+
+                       if (sti_mixer_set_plane_status(mixer, plane, true)) {
+                               DRM_ERROR("Cannot enable plane %s at mixer\n",
+                                         sti_plane_to_str(plane));
+                               break;
+                       }
+
+                       /* if plane is HQVDP_0 then commit the vid[0] */
+                       if (plane->desc == STI_HQVDP_0)
+                               sti_vid_commit(compo->vid[0], p->state);
+
+                       plane->status = STI_PLANE_READY;
+
+                       break;
+               case STI_PLANE_DISABLING:
+                       /* disabling sequence for planes tag as disabling */
+                       DRM_DEBUG_DRIVER("disable plane %s from mixer\n",
+                                        sti_plane_to_str(plane));
+
+                       if (sti_mixer_set_plane_status(mixer, plane, false)) {
+                               DRM_ERROR("Cannot disable plane %s at mixer\n",
+                                         sti_plane_to_str(plane));
+                               continue;
+                       }
+
+                       if (plane->desc == STI_CURSOR)
+                               /* tag plane status for disabled */
+                               plane->status = STI_PLANE_DISABLED;
+                       else
+                               /* tag plane status for flushing */
+                               plane->status = STI_PLANE_FLUSHING;
+
+                       /* if plane is HQVDP_0 then disable the vid[0] */
+                       if (plane->desc == STI_HQVDP_0)
+                               sti_vid_disable(compo->vid[0]);
+
+                       break;
+               default:
+                       /* Other status case are not handled */
+                       break;
+               }
+       }
 }
 
 static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
-       .dpms = sti_drm_crtc_dpms,
-       .prepare = sti_drm_crtc_prepare,
-       .commit = sti_drm_crtc_commit,
-       .mode_fixup = sti_drm_crtc_mode_fixup,
+       .enable = sti_crtc_enable,
+       .disable = sti_crtc_disabling,
+       .mode_fixup = sti_crtc_mode_fixup,
        .mode_set = drm_helper_crtc_mode_set,
-       .mode_set_nofb = sti_drm_crtc_mode_set_nofb,
+       .mode_set_nofb = sti_crtc_mode_set_nofb,
        .mode_set_base = drm_helper_crtc_mode_set_base,
-       .disable = sti_drm_crtc_disable,
-       .atomic_begin = sti_drm_atomic_begin,
-       .atomic_flush = sti_drm_atomic_flush,
+       .atomic_begin = sti_crtc_atomic_begin,
+       .atomic_flush = sti_crtc_atomic_flush,
 };
 
-static void sti_drm_crtc_destroy(struct drm_crtc *crtc)
+static void sti_crtc_destroy(struct drm_crtc *crtc)
 {
        DRM_DEBUG_KMS("\n");
        drm_crtc_cleanup(crtc);
 }
 
-static int sti_drm_crtc_set_property(struct drm_crtc *crtc,
-                                    struct drm_property *property,
-                                    uint64_t val)
+static int sti_crtc_set_property(struct drm_crtc *crtc,
+                                struct drm_property *property,
+                                uint64_t val)
 {
        DRM_DEBUG_KMS("\n");
        return 0;
 }
 
-int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
-                          unsigned long event, void *data)
+int sti_crtc_vblank_cb(struct notifier_block *nb,
+                      unsigned long event, void *data)
 {
        struct drm_device *drm_dev;
        struct sti_compositor *compo =
                container_of(nb, struct sti_compositor, vtg_vblank_nb);
        int *crtc = data;
        unsigned long flags;
-       struct sti_drm_private *priv;
+       struct sti_private *priv;
 
        drm_dev = compo->mixer[*crtc]->drm_crtc.dev;
        priv = drm_dev->dev_private;
@@ -233,21 +275,38 @@ int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
        spin_lock_irqsave(&drm_dev->event_lock, flags);
        if (compo->mixer[*crtc]->pending_event) {
                drm_send_vblank_event(drm_dev, -1,
-                               compo->mixer[*crtc]->pending_event);
+                                     compo->mixer[*crtc]->pending_event);
                drm_vblank_put(drm_dev, *crtc);
                compo->mixer[*crtc]->pending_event = NULL;
        }
        spin_unlock_irqrestore(&drm_dev->event_lock, flags);
 
+       if (compo->mixer[*crtc]->status == STI_MIXER_DISABLING) {
+               struct drm_plane *p;
+
+               /* Disable mixer only if all overlay planes (GDP and VDP)
+                * are disabled */
+               list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
+                       struct sti_plane *plane = to_sti_plane(p);
+
+                       if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
+                               if (plane->status != STI_PLANE_DISABLED)
+                                       return 0;
+               }
+               sti_crtc_disable(&compo->mixer[*crtc]->drm_crtc);
+       }
+
        return 0;
 }
 
-int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
+int sti_crtc_enable_vblank(struct drm_device *dev, int crtc)
 {
-       struct sti_drm_private *dev_priv = dev->dev_private;
+       struct sti_private *dev_priv = dev->dev_private;
        struct sti_compositor *compo = dev_priv->compo;
        struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
 
+       DRM_DEBUG_DRIVER("\n");
+
        if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ?
                        compo->vtg_main : compo->vtg_aux,
                        vtg_vblank_nb, crtc)) {
@@ -257,11 +316,11 @@ int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
 
        return 0;
 }
-EXPORT_SYMBOL(sti_drm_crtc_enable_vblank);
+EXPORT_SYMBOL(sti_crtc_enable_vblank);
 
-void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
+void sti_crtc_disable_vblank(struct drm_device *drm_dev, int crtc)
 {
-       struct sti_drm_private *priv = dev->dev_private;
+       struct sti_private *priv = drm_dev->dev_private;
        struct sti_compositor *compo = priv->compo;
        struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
 
@@ -273,23 +332,23 @@ void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
 
        /* free the resources of the pending requests */
        if (compo->mixer[crtc]->pending_event) {
-               drm_vblank_put(dev, crtc);
+               drm_vblank_put(drm_dev, crtc);
                compo->mixer[crtc]->pending_event = NULL;
        }
 }
-EXPORT_SYMBOL(sti_drm_crtc_disable_vblank);
+EXPORT_SYMBOL(sti_crtc_disable_vblank);
 
 static struct drm_crtc_funcs sti_crtc_funcs = {
        .set_config = drm_atomic_helper_set_config,
        .page_flip = drm_atomic_helper_page_flip,
-       .destroy = sti_drm_crtc_destroy,
-       .set_property = sti_drm_crtc_set_property,
+       .destroy = sti_crtc_destroy,
+       .set_property = sti_crtc_set_property,
        .reset = drm_atomic_helper_crtc_reset,
        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
-bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
+bool sti_crtc_is_main(struct drm_crtc *crtc)
 {
        struct sti_mixer *mixer = to_sti_mixer(crtc);
 
@@ -298,18 +357,18 @@ bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
 
        return false;
 }
-EXPORT_SYMBOL(sti_drm_crtc_is_main);
+EXPORT_SYMBOL(sti_crtc_is_main);
 
-int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
-               struct drm_plane *primary, struct drm_plane *cursor)
+int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
+                 struct drm_plane *primary, struct drm_plane *cursor)
 {
        struct drm_crtc *crtc = &mixer->drm_crtc;
        int res;
 
        res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
-                       &sti_crtc_funcs);
+                                       &sti_crtc_funcs);
        if (res) {
-               DRM_ERROR("Can not initialze CRTC\n");
+               DRM_ERROR("Can't initialze CRTC\n");
                return -EINVAL;
        }
 
diff --git a/drivers/gpu/drm/sti/sti_crtc.h b/drivers/gpu/drm/sti/sti_crtc.h
new file mode 100644 (file)
index 0000000..51963e6
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_CRTC_H_
+#define _STI_CRTC_H_
+
+#include <drm/drmP.h>
+
+struct sti_mixer;
+
+int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
+                 struct drm_plane *primary, struct drm_plane *cursor);
+int sti_crtc_enable_vblank(struct drm_device *dev, int crtc);
+void sti_crtc_disable_vblank(struct drm_device *dev, int crtc);
+int sti_crtc_vblank_cb(struct notifier_block *nb,
+                      unsigned long event, void *data);
+bool sti_crtc_is_main(struct drm_crtc *drm_crtc);
+
+#endif
index 010eaee60bf7c17c27f5e8e3d14f76771e161ccd..dd10321950518587b9fc06776f2ca2478572bcc3 100644 (file)
@@ -7,8 +7,14 @@
  */
 #include <drm/drmP.h>
 
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "sti_compositor.h"
 #include "sti_cursor.h"
-#include "sti_layer.h"
+#include "sti_plane.h"
 #include "sti_vtg.h"
 
 /* Registers */
@@ -42,15 +48,19 @@ struct dma_pixmap {
 /**
  * STI Cursor structure
  *
- * @layer:      layer structure
- * @width:      cursor width
- * @height:     cursor height
- * @clut:       color look up table
- * @clut_paddr: color look up table physical address
- * @pixmap:     pixmap dma buffer (clut8-format cursor)
+ * @sti_plane:    sti_plane structure
+ * @dev:          driver device
+ * @regs:         cursor registers
+ * @width:        cursor width
+ * @height:       cursor height
+ * @clut:         color look up table
+ * @clut_paddr:   color look up table physical address
+ * @pixmap:       pixmap dma buffer (clut8-format cursor)
  */
 struct sti_cursor {
-       struct sti_layer layer;
+       struct sti_plane plane;
+       struct device *dev;
+       void __iomem *regs;
        unsigned int width;
        unsigned int height;
        unsigned short *clut;
@@ -62,22 +72,10 @@ static const uint32_t cursor_supported_formats[] = {
        DRM_FORMAT_ARGB8888,
 };
 
-#define to_sti_cursor(x) container_of(x, struct sti_cursor, layer)
-
-static const uint32_t *sti_cursor_get_formats(struct sti_layer *layer)
-{
-       return cursor_supported_formats;
-}
-
-static unsigned int sti_cursor_get_nb_formats(struct sti_layer *layer)
-{
-       return ARRAY_SIZE(cursor_supported_formats);
-}
+#define to_sti_cursor(x) container_of(x, struct sti_cursor, plane)
 
-static void sti_cursor_argb8888_to_clut8(struct sti_layer *layer)
+static void sti_cursor_argb8888_to_clut8(struct sti_cursor *cursor, u32 *src)
 {
-       struct sti_cursor *cursor = to_sti_cursor(layer);
-       u32 *src = layer->vaddr;
        u8  *dst = cursor->pixmap.base;
        unsigned int i, j;
        u32 a, r, g, b;
@@ -96,127 +94,155 @@ static void sti_cursor_argb8888_to_clut8(struct sti_layer *layer)
        }
 }
 
-static int sti_cursor_prepare_layer(struct sti_layer *layer, bool first_prepare)
+static void sti_cursor_init(struct sti_cursor *cursor)
 {
-       struct sti_cursor *cursor = to_sti_cursor(layer);
-       struct drm_display_mode *mode = layer->mode;
+       unsigned short *base = cursor->clut;
+       unsigned int a, r, g, b;
+
+       /* Assign CLUT values, ARGB444 format */
+       for (a = 0; a < 4; a++)
+               for (r = 0; r < 4; r++)
+                       for (g = 0; g < 4; g++)
+                               for (b = 0; b < 4; b++)
+                                       *base++ = (a * 5) << 12 |
+                                                 (r * 5) << 8 |
+                                                 (g * 5) << 4 |
+                                                 (b * 5);
+}
+
+static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
+                                    struct drm_plane_state *oldstate)
+{
+       struct drm_plane_state *state = drm_plane->state;
+       struct sti_plane *plane = to_sti_plane(drm_plane);
+       struct sti_cursor *cursor = to_sti_cursor(plane);
+       struct drm_crtc *crtc = state->crtc;
+       struct sti_mixer *mixer = to_sti_mixer(crtc);
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_display_mode *mode = &crtc->mode;
+       int dst_x = state->crtc_x;
+       int dst_y = state->crtc_y;
+       int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
+       int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
+       /* src_x are in 16.16 format */
+       int src_w = state->src_w >> 16;
+       int src_h = state->src_h >> 16;
+       bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
+       struct drm_gem_cma_object *cma_obj;
        u32 y, x;
        u32 val;
 
-       DRM_DEBUG_DRIVER("\n");
+       DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
+                     crtc->base.id, sti_mixer_to_str(mixer),
+                     drm_plane->base.id, sti_plane_to_str(plane));
+       DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", dst_w, dst_h, dst_x, dst_y);
 
-       dev_dbg(layer->dev, "%s %s\n", __func__, sti_layer_to_str(layer));
+       dev_dbg(cursor->dev, "%s %s\n", __func__,
+               sti_plane_to_str(plane));
 
-       if (layer->src_w < STI_CURS_MIN_SIZE ||
-           layer->src_h < STI_CURS_MIN_SIZE ||
-           layer->src_w > STI_CURS_MAX_SIZE ||
-           layer->src_h > STI_CURS_MAX_SIZE) {
+       if (src_w < STI_CURS_MIN_SIZE ||
+           src_h < STI_CURS_MIN_SIZE ||
+           src_w > STI_CURS_MAX_SIZE ||
+           src_h > STI_CURS_MAX_SIZE) {
                DRM_ERROR("Invalid cursor size (%dx%d)\n",
-                               layer->src_w, layer->src_h);
-               return -EINVAL;
+                               src_w, src_h);
+               return;
        }
 
        /* If the cursor size has changed, re-allocated the pixmap */
        if (!cursor->pixmap.base ||
-           (cursor->width != layer->src_w) ||
-           (cursor->height != layer->src_h)) {
-               cursor->width = layer->src_w;
-               cursor->height = layer->src_h;
+           (cursor->width != src_w) ||
+           (cursor->height != src_h)) {
+               cursor->width = src_w;
+               cursor->height = src_h;
 
                if (cursor->pixmap.base)
-                       dma_free_writecombine(layer->dev,
+                       dma_free_writecombine(cursor->dev,
                                              cursor->pixmap.size,
                                              cursor->pixmap.base,
                                              cursor->pixmap.paddr);
 
                cursor->pixmap.size = cursor->width * cursor->height;
 
-               cursor->pixmap.base = dma_alloc_writecombine(layer->dev,
+               cursor->pixmap.base = dma_alloc_writecombine(cursor->dev,
                                                        cursor->pixmap.size,
                                                        &cursor->pixmap.paddr,
                                                        GFP_KERNEL | GFP_DMA);
                if (!cursor->pixmap.base) {
                        DRM_ERROR("Failed to allocate memory for pixmap\n");
-                       return -ENOMEM;
+                       return;
                }
        }
 
+       cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       if (!cma_obj) {
+               DRM_ERROR("Can't get CMA GEM object for fb\n");
+               return;
+       }
+
        /* Convert ARGB8888 to CLUT8 */
-       sti_cursor_argb8888_to_clut8(layer);
+       sti_cursor_argb8888_to_clut8(cursor, (u32 *)cma_obj->vaddr);
 
        /* AWS and AWE depend on the mode */
        y = sti_vtg_get_line_number(*mode, 0);
        x = sti_vtg_get_pixel_number(*mode, 0);
        val = y << 16 | x;
-       writel(val, layer->regs + CUR_AWS);
+       writel(val, cursor->regs + CUR_AWS);
        y = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);
        x = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);
        val = y << 16 | x;
-       writel(val, layer->regs + CUR_AWE);
+       writel(val, cursor->regs + CUR_AWE);
 
        if (first_prepare) {
                /* Set and fetch CLUT */
-               writel(cursor->clut_paddr, layer->regs + CUR_CML);
-               writel(CUR_CTL_CLUT_UPDATE, layer->regs + CUR_CTL);
+               writel(cursor->clut_paddr, cursor->regs + CUR_CML);
+               writel(CUR_CTL_CLUT_UPDATE, cursor->regs + CUR_CTL);
        }
 
-       return 0;
-}
-
-static int sti_cursor_commit_layer(struct sti_layer *layer)
-{
-       struct sti_cursor *cursor = to_sti_cursor(layer);
-       struct drm_display_mode *mode = layer->mode;
-       u32 ydo, xdo;
-
-       dev_dbg(layer->dev, "%s %s\n", __func__, sti_layer_to_str(layer));
-
        /* Set memory location, size, and position */
-       writel(cursor->pixmap.paddr, layer->regs + CUR_PML);
-       writel(cursor->width, layer->regs + CUR_PMP);
-       writel(cursor->height << 16 | cursor->width, layer->regs + CUR_SIZE);
+       writel(cursor->pixmap.paddr, cursor->regs + CUR_PML);
+       writel(cursor->width, cursor->regs + CUR_PMP);
+       writel(cursor->height << 16 | cursor->width, cursor->regs + CUR_SIZE);
 
-       ydo = sti_vtg_get_line_number(*mode, layer->dst_y);
-       xdo = sti_vtg_get_pixel_number(*mode, layer->dst_y);
-       writel((ydo << 16) | xdo, layer->regs + CUR_VPO);
+       y = sti_vtg_get_line_number(*mode, dst_y);
+       x = sti_vtg_get_pixel_number(*mode, dst_y);
+       writel((y << 16) | x, cursor->regs + CUR_VPO);
 
-       return 0;
+       plane->status = STI_PLANE_UPDATED;
 }
 
-static int sti_cursor_disable_layer(struct sti_layer *layer)
+static void sti_cursor_atomic_disable(struct drm_plane *drm_plane,
+                                     struct drm_plane_state *oldstate)
 {
-       return 0;
-}
+       struct sti_plane *plane = to_sti_plane(drm_plane);
+       struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
 
-static void sti_cursor_init(struct sti_layer *layer)
-{
-       struct sti_cursor *cursor = to_sti_cursor(layer);
-       unsigned short *base = cursor->clut;
-       unsigned int a, r, g, b;
+       if (!drm_plane->crtc) {
+               DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
+                                drm_plane->base.id);
+               return;
+       }
 
-       /* Assign CLUT values, ARGB444 format */
-       for (a = 0; a < 4; a++)
-               for (r = 0; r < 4; r++)
-                       for (g = 0; g < 4; g++)
-                               for (b = 0; b < 4; b++)
-                                       *base++ = (a * 5) << 12 |
-                                                 (r * 5) << 8 |
-                                                 (g * 5) << 4 |
-                                                 (b * 5);
+       DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+                        drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
+                        drm_plane->base.id, sti_plane_to_str(plane));
+
+       plane->status = STI_PLANE_DISABLING;
 }
 
-static const struct sti_layer_funcs cursor_ops = {
-       .get_formats = sti_cursor_get_formats,
-       .get_nb_formats = sti_cursor_get_nb_formats,
-       .init = sti_cursor_init,
-       .prepare = sti_cursor_prepare_layer,
-       .commit = sti_cursor_commit_layer,
-       .disable = sti_cursor_disable_layer,
+static const struct drm_plane_helper_funcs sti_cursor_helpers_funcs = {
+       .atomic_update = sti_cursor_atomic_update,
+       .atomic_disable = sti_cursor_atomic_disable,
 };
 
-struct sti_layer *sti_cursor_create(struct device *dev)
+struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
+                                   struct device *dev, int desc,
+                                   void __iomem *baseaddr,
+                                   unsigned int possible_crtcs)
 {
        struct sti_cursor *cursor;
+       size_t size;
+       int res;
 
        cursor = devm_kzalloc(dev, sizeof(*cursor), GFP_KERNEL);
        if (!cursor) {
@@ -225,18 +251,43 @@ struct sti_layer *sti_cursor_create(struct device *dev)
        }
 
        /* Allocate clut buffer */
-       cursor->clut = dma_alloc_writecombine(dev,
-                       0x100 * sizeof(unsigned short),
-                       &cursor->clut_paddr,
-                       GFP_KERNEL | GFP_DMA);
+       size = 0x100 * sizeof(unsigned short);
+       cursor->clut = dma_alloc_writecombine(dev, size, &cursor->clut_paddr,
+                                             GFP_KERNEL | GFP_DMA);
 
        if (!cursor->clut) {
                DRM_ERROR("Failed to allocate memory for cursor clut\n");
-               devm_kfree(dev, cursor);
-               return NULL;
+               goto err_clut;
+       }
+
+       cursor->dev = dev;
+       cursor->regs = baseaddr;
+       cursor->plane.desc = desc;
+       cursor->plane.status = STI_PLANE_DISABLED;
+
+       sti_cursor_init(cursor);
+
+       res = drm_universal_plane_init(drm_dev, &cursor->plane.drm_plane,
+                                      possible_crtcs,
+                                      &sti_plane_helpers_funcs,
+                                      cursor_supported_formats,
+                                      ARRAY_SIZE(cursor_supported_formats),
+                                      DRM_PLANE_TYPE_CURSOR);
+       if (res) {
+               DRM_ERROR("Failed to initialize universal plane\n");
+               goto err_plane;
        }
 
-       cursor->layer.ops = &cursor_ops;
+       drm_plane_helper_add(&cursor->plane.drm_plane,
+                            &sti_cursor_helpers_funcs);
+
+       sti_plane_init_property(&cursor->plane, DRM_PLANE_TYPE_CURSOR);
+
+       return &cursor->plane.drm_plane;
 
-       return (struct sti_layer *)cursor;
+err_plane:
+       dma_free_writecombine(dev, size, cursor->clut, cursor->clut_paddr);
+err_clut:
+       devm_kfree(dev, cursor);
+       return NULL;
 }
index 3c9827404f27900e5239ae4140730da415514315..2ee5c10e8b33c7a125278a2f5247247a3769f112 100644 (file)
@@ -7,6 +7,9 @@
 #ifndef _STI_CURSOR_H_
 #define _STI_CURSOR_H_
 
-struct sti_layer *sti_cursor_create(struct device *dev);
+struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
+                                   struct device *dev, int desc,
+                                   void __iomem *baseaddr,
+                                   unsigned int possible_crtcs);
 
 #endif
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.h b/drivers/gpu/drm/sti/sti_drm_crtc.h
deleted file mode 100644 (file)
index caca8b1..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#ifndef _STI_DRM_CRTC_H_
-#define _STI_DRM_CRTC_H_
-
-#include <drm/drmP.h>
-
-struct sti_mixer;
-
-int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
-               struct drm_plane *primary, struct drm_plane *cursor);
-int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
-void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
-int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
-               unsigned long event, void *data);
-bool sti_drm_crtc_is_main(struct drm_crtc *drm_crtc);
-
-#endif
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c
deleted file mode 100644 (file)
index 64d4ed4..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
- *          Fabien Dessenne <fabien.dessenne@st.com>
- *          for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
-
-#include "sti_compositor.h"
-#include "sti_drm_drv.h"
-#include "sti_drm_plane.h"
-#include "sti_vtg.h"
-
-enum sti_layer_desc sti_layer_default_zorder[] = {
-       STI_GDP_0,
-       STI_VID_0,
-       STI_GDP_1,
-       STI_VID_1,
-       STI_GDP_2,
-       STI_GDP_3,
-};
-
-/* (Background) < GDP0 < VID0 < GDP1 < VID1 < GDP2 < GDP3 < (ForeGround) */
-
-static int
-sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
-                    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
-                    unsigned int crtc_w, unsigned int crtc_h,
-                    uint32_t src_x, uint32_t src_y,
-                    uint32_t src_w, uint32_t src_h)
-{
-       struct sti_layer *layer = to_sti_layer(plane);
-       struct sti_mixer *mixer = to_sti_mixer(crtc);
-       int res;
-
-       DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
-                     crtc->base.id, sti_mixer_to_str(mixer),
-                     plane->base.id, sti_layer_to_str(layer));
-       DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", crtc_w, crtc_h, crtc_x, crtc_y);
-
-       res = sti_mixer_set_layer_depth(mixer, layer);
-       if (res) {
-               DRM_ERROR("Can not set layer depth\n");
-               return res;
-       }
-
-       /* src_x are in 16.16 format. */
-       res = sti_layer_prepare(layer, crtc, fb,
-                       &crtc->mode, mixer->id,
-                       crtc_x, crtc_y, crtc_w, crtc_h,
-                       src_x >> 16, src_y >> 16,
-                       src_w >> 16, src_h >> 16);
-       if (res) {
-               DRM_ERROR("Layer prepare failed\n");
-               return res;
-       }
-
-       res = sti_layer_commit(layer);
-       if (res) {
-               DRM_ERROR("Layer commit failed\n");
-               return res;
-       }
-
-       res = sti_mixer_set_layer_status(mixer, layer, true);
-       if (res) {
-               DRM_ERROR("Can not enable layer at mixer\n");
-               return res;
-       }
-
-       return 0;
-}
-
-static int sti_drm_disable_plane(struct drm_plane *plane)
-{
-       struct sti_layer *layer;
-       struct sti_mixer *mixer;
-       int lay_res, mix_res;
-
-       if (!plane->crtc) {
-               DRM_DEBUG_DRIVER("drm plane:%d not enabled\n", plane->base.id);
-               return 0;
-       }
-       layer = to_sti_layer(plane);
-       mixer = to_sti_mixer(plane->crtc);
-
-       DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
-                       plane->crtc->base.id, sti_mixer_to_str(mixer),
-                       plane->base.id, sti_layer_to_str(layer));
-
-       /* Disable layer at mixer level */
-       mix_res = sti_mixer_set_layer_status(mixer, layer, false);
-       if (mix_res)
-               DRM_ERROR("Can not disable layer at mixer\n");
-
-       /* Wait a while to be sure that a Vsync event is received */
-       msleep(WAIT_NEXT_VSYNC_MS);
-
-       /* Then disable layer itself */
-       lay_res = sti_layer_disable(layer);
-       if (lay_res)
-               DRM_ERROR("Layer disable failed\n");
-
-       if (lay_res || mix_res)
-               return -EINVAL;
-
-       return 0;
-}
-
-static void sti_drm_plane_destroy(struct drm_plane *plane)
-{
-       DRM_DEBUG_DRIVER("\n");
-
-       drm_plane_helper_disable(plane);
-       drm_plane_cleanup(plane);
-}
-
-static int sti_drm_plane_set_property(struct drm_plane *plane,
-                                     struct drm_property *property,
-                                     uint64_t val)
-{
-       struct drm_device *dev = plane->dev;
-       struct sti_drm_private *private = dev->dev_private;
-       struct sti_layer *layer = to_sti_layer(plane);
-
-       DRM_DEBUG_DRIVER("\n");
-
-       if (property == private->plane_zorder_property) {
-               layer->zorder = val;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-static struct drm_plane_funcs sti_drm_plane_funcs = {
-       .update_plane = drm_atomic_helper_update_plane,
-       .disable_plane = drm_atomic_helper_disable_plane,
-       .destroy = sti_drm_plane_destroy,
-       .set_property = sti_drm_plane_set_property,
-       .reset = drm_atomic_helper_plane_reset,
-       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
-};
-
-static int sti_drm_plane_prepare_fb(struct drm_plane *plane,
-                                 struct drm_framebuffer *fb,
-                                 const struct drm_plane_state *new_state)
-{
-       return 0;
-}
-
-static void sti_drm_plane_cleanup_fb(struct drm_plane *plane,
-                                  struct drm_framebuffer *fb,
-                                  const struct drm_plane_state *old_fb)
-{
-}
-
-static int sti_drm_plane_atomic_check(struct drm_plane *plane,
-                                     struct drm_plane_state *state)
-{
-       return 0;
-}
-
-static void sti_drm_plane_atomic_update(struct drm_plane *plane,
-                                       struct drm_plane_state *oldstate)
-{
-       struct drm_plane_state *state = plane->state;
-
-       sti_drm_update_plane(plane, state->crtc, state->fb,
-                           state->crtc_x, state->crtc_y,
-                           state->crtc_w, state->crtc_h,
-                           state->src_x, state->src_y,
-                           state->src_w, state->src_h);
-}
-
-static void sti_drm_plane_atomic_disable(struct drm_plane *plane,
-                                        struct drm_plane_state *oldstate)
-{
-       sti_drm_disable_plane(plane);
-}
-
-static const struct drm_plane_helper_funcs sti_drm_plane_helpers_funcs = {
-       .prepare_fb = sti_drm_plane_prepare_fb,
-       .cleanup_fb = sti_drm_plane_cleanup_fb,
-       .atomic_check = sti_drm_plane_atomic_check,
-       .atomic_update = sti_drm_plane_atomic_update,
-       .atomic_disable = sti_drm_plane_atomic_disable,
-};
-
-static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane,
-                                                uint64_t default_val)
-{
-       struct drm_device *dev = plane->dev;
-       struct sti_drm_private *private = dev->dev_private;
-       struct drm_property *prop;
-       struct sti_layer *layer = to_sti_layer(plane);
-
-       prop = private->plane_zorder_property;
-       if (!prop) {
-               prop = drm_property_create_range(dev, 0, "zpos", 0,
-                                                GAM_MIXER_NB_DEPTH_LEVEL - 1);
-               if (!prop)
-                       return;
-
-               private->plane_zorder_property = prop;
-       }
-
-       drm_object_attach_property(&plane->base, prop, default_val);
-       layer->zorder = default_val;
-}
-
-struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
-                                    struct sti_layer *layer,
-                                    unsigned int possible_crtcs,
-                                    enum drm_plane_type type)
-{
-       int err, i;
-       uint64_t default_zorder = 0;
-
-       err = drm_universal_plane_init(dev, &layer->plane, possible_crtcs,
-                            &sti_drm_plane_funcs,
-                            sti_layer_get_formats(layer),
-                            sti_layer_get_nb_formats(layer), type);
-       if (err) {
-               DRM_ERROR("Failed to initialize plane\n");
-               return NULL;
-       }
-
-       drm_plane_helper_add(&layer->plane, &sti_drm_plane_helpers_funcs);
-
-       for (i = 0; i < ARRAY_SIZE(sti_layer_default_zorder); i++)
-               if (sti_layer_default_zorder[i] == layer->desc)
-                       break;
-
-       default_zorder = i + 1;
-
-       if (type == DRM_PLANE_TYPE_OVERLAY)
-               sti_drm_plane_attach_zorder_property(&layer->plane,
-                               default_zorder);
-
-       DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%llu\n",
-                        layer->plane.base.id,
-                        sti_layer_to_str(layer), default_zorder);
-
-       return &layer->plane;
-}
-EXPORT_SYMBOL(sti_drm_plane_init);
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.h b/drivers/gpu/drm/sti/sti_drm_plane.h
deleted file mode 100644 (file)
index 4f19183..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#ifndef _STI_DRM_PLANE_H_
-#define _STI_DRM_PLANE_H_
-
-#include <drm/drmP.h>
-
-struct sti_layer;
-
-struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
-               struct sti_layer *layer,
-               unsigned int possible_crtcs,
-               enum drm_plane_type type);
-#endif
similarity index 61%
rename from drivers/gpu/drm/sti/sti_drm_drv.c
rename to drivers/gpu/drm/sti/sti_drv.c
index 59d558b400b33f390cdd6db00014ab29c94b84d4..6f4af6a8ba1bf7883b8c04db0c863018f092f275 100644 (file)
@@ -18,8 +18,8 @@
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 
-#include "sti_drm_drv.h"
-#include "sti_drm_crtc.h"
+#include "sti_crtc.h"
+#include "sti_drv.h"
 
 #define DRIVER_NAME    "sti"
 #define DRIVER_DESC    "STMicroelectronics SoC DRM"
 #define STI_MAX_FB_HEIGHT      4096
 #define STI_MAX_FB_WIDTH       4096
 
-static void sti_drm_atomic_schedule(struct sti_drm_private *private,
-                                 struct drm_atomic_state *state)
+static void sti_atomic_schedule(struct sti_private *private,
+                               struct drm_atomic_state *state)
 {
        private->commit.state = state;
        schedule_work(&private->commit.work);
 }
 
-static void sti_drm_atomic_complete(struct sti_drm_private *private,
-                                 struct drm_atomic_state *state)
+static void sti_atomic_complete(struct sti_private *private,
+                               struct drm_atomic_state *state)
 {
        struct drm_device *drm = private->drm_dev;
 
@@ -68,18 +68,18 @@ static void sti_drm_atomic_complete(struct sti_drm_private *private,
        drm_atomic_state_free(state);
 }
 
-static void sti_drm_atomic_work(struct work_struct *work)
+static void sti_atomic_work(struct work_struct *work)
 {
-       struct sti_drm_private *private = container_of(work,
-                       struct sti_drm_private, commit.work);
+       struct sti_private *private = container_of(work,
+                       struct sti_private, commit.work);
 
-       sti_drm_atomic_complete(private, private->commit.state);
+       sti_atomic_complete(private, private->commit.state);
 }
 
-static int sti_drm_atomic_commit(struct drm_device *drm,
-                              struct drm_atomic_state *state, bool async)
+static int sti_atomic_commit(struct drm_device *drm,
+                            struct drm_atomic_state *state, bool async)
 {
-       struct sti_drm_private *private = drm->dev_private;
+       struct sti_private *private = drm->dev_private;
        int err;
 
        err = drm_atomic_helper_prepare_planes(drm, state);
@@ -99,21 +99,21 @@ static int sti_drm_atomic_commit(struct drm_device *drm,
        drm_atomic_helper_swap_state(drm, state);
 
        if (async)
-               sti_drm_atomic_schedule(private, state);
+               sti_atomic_schedule(private, state);
        else
-               sti_drm_atomic_complete(private, state);
+               sti_atomic_complete(private, state);
 
        mutex_unlock(&private->commit.lock);
        return 0;
 }
 
-static struct drm_mode_config_funcs sti_drm_mode_config_funcs = {
+static struct drm_mode_config_funcs sti_mode_config_funcs = {
        .fb_create = drm_fb_cma_create,
        .atomic_check = drm_atomic_helper_check,
-       .atomic_commit = sti_drm_atomic_commit,
+       .atomic_commit = sti_atomic_commit,
 };
 
-static void sti_drm_mode_config_init(struct drm_device *dev)
+static void sti_mode_config_init(struct drm_device *dev)
 {
        dev->mode_config.min_width = 0;
        dev->mode_config.min_height = 0;
@@ -126,15 +126,15 @@ static void sti_drm_mode_config_init(struct drm_device *dev)
        dev->mode_config.max_width = STI_MAX_FB_HEIGHT;
        dev->mode_config.max_height = STI_MAX_FB_WIDTH;
 
-       dev->mode_config.funcs = &sti_drm_mode_config_funcs;
+       dev->mode_config.funcs = &sti_mode_config_funcs;
 }
 
-static int sti_drm_load(struct drm_device *dev, unsigned long flags)
+static int sti_load(struct drm_device *dev, unsigned long flags)
 {
-       struct sti_drm_private *private;
+       struct sti_private *private;
        int ret;
 
-       private = kzalloc(sizeof(struct sti_drm_private), GFP_KERNEL);
+       private = kzalloc(sizeof(*private), GFP_KERNEL);
        if (!private) {
                DRM_ERROR("Failed to allocate private\n");
                return -ENOMEM;
@@ -143,12 +143,12 @@ static int sti_drm_load(struct drm_device *dev, unsigned long flags)
        private->drm_dev = dev;
 
        mutex_init(&private->commit.lock);
-       INIT_WORK(&private->commit.work, sti_drm_atomic_work);
+       INIT_WORK(&private->commit.work, sti_atomic_work);
 
        drm_mode_config_init(dev);
        drm_kms_helper_poll_init(dev);
 
-       sti_drm_mode_config_init(dev);
+       sti_mode_config_init(dev);
 
        ret = component_bind_all(dev->dev, dev);
        if (ret) {
@@ -162,13 +162,13 @@ static int sti_drm_load(struct drm_device *dev, unsigned long flags)
 
 #ifdef CONFIG_DRM_STI_FBDEV
        drm_fbdev_cma_init(dev, 32,
-                  dev->mode_config.num_crtc,
-                  dev->mode_config.num_connector);
+                          dev->mode_config.num_crtc,
+                          dev->mode_config.num_connector);
 #endif
        return 0;
 }
 
-static const struct file_operations sti_drm_driver_fops = {
+static const struct file_operations sti_driver_fops = {
        .owner = THIS_MODULE,
        .open = drm_open,
        .mmap = drm_gem_cma_mmap,
@@ -181,33 +181,33 @@ static const struct file_operations sti_drm_driver_fops = {
        .release = drm_release,
 };
 
-static struct dma_buf *sti_drm_gem_prime_export(struct drm_device *dev,
-                                               struct drm_gem_object *obj,
-                                               int flags)
+static struct dma_buf *sti_gem_prime_export(struct drm_device *dev,
+                                           struct drm_gem_object *obj,
+                                           int flags)
 {
        /* we want to be able to write in mmapped buffer */
        flags |= O_RDWR;
        return drm_gem_prime_export(dev, obj, flags);
 }
 
-static struct drm_driver sti_drm_driver = {
+static struct drm_driver sti_driver = {
        .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET |
            DRIVER_GEM | DRIVER_PRIME,
-       .load = sti_drm_load,
+       .load = sti_load,
        .gem_free_object = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = drm_gem_cma_dumb_create,
        .dumb_map_offset = drm_gem_cma_dumb_map_offset,
        .dumb_destroy = drm_gem_dumb_destroy,
-       .fops = &sti_drm_driver_fops,
+       .fops = &sti_driver_fops,
 
        .get_vblank_counter = drm_vblank_count,
-       .enable_vblank = sti_drm_crtc_enable_vblank,
-       .disable_vblank = sti_drm_crtc_disable_vblank,
+       .enable_vblank = sti_crtc_enable_vblank,
+       .disable_vblank = sti_crtc_disable_vblank,
 
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = sti_drm_gem_prime_export,
+       .gem_prime_export = sti_gem_prime_export,
        .gem_prime_import = drm_gem_prime_import,
        .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
        .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
@@ -227,30 +227,32 @@ static int compare_of(struct device *dev, void *data)
        return dev->of_node == data;
 }
 
-static int sti_drm_bind(struct device *dev)
+static int sti_bind(struct device *dev)
 {
-       return drm_platform_init(&sti_drm_driver, to_platform_device(dev));
+       return drm_platform_init(&sti_driver, to_platform_device(dev));
 }
 
-static void sti_drm_unbind(struct device *dev)
+static void sti_unbind(struct device *dev)
 {
        drm_put_dev(dev_get_drvdata(dev));
 }
 
-static const struct component_master_ops sti_drm_ops = {
-       .bind = sti_drm_bind,
-       .unbind = sti_drm_unbind,
+static const struct component_master_ops sti_ops = {
+       .bind = sti_bind,
+       .unbind = sti_unbind,
 };
 
-static int sti_drm_master_probe(struct platform_device *pdev)
+static int sti_platform_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct device_node *node = dev->parent->of_node;
+       struct device_node *node = dev->of_node;
        struct device_node *child_np;
        struct component_match *match = NULL;
 
        dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
 
+       of_platform_populate(node, NULL, NULL, dev);
+
        child_np = of_get_next_available_child(node, NULL);
 
        while (child_np) {
@@ -259,68 +261,33 @@ static int sti_drm_master_probe(struct platform_device *pdev)
                child_np = of_get_next_available_child(node, child_np);
        }
 
-       return component_master_add_with_match(dev, &sti_drm_ops, match);
-}
-
-static int sti_drm_master_remove(struct platform_device *pdev)
-{
-       component_master_del(&pdev->dev, &sti_drm_ops);
-       return 0;
+       return component_master_add_with_match(dev, &sti_ops, match);
 }
 
-static struct platform_driver sti_drm_master_driver = {
-       .probe = sti_drm_master_probe,
-       .remove = sti_drm_master_remove,
-       .driver = {
-               .name = DRIVER_NAME "__master",
-       },
-};
-
-static int sti_drm_platform_probe(struct platform_device *pdev)
+static int sti_platform_remove(struct platform_device *pdev)
 {
-       struct device *dev = &pdev->dev;
-       struct device_node *node = dev->of_node;
-       struct platform_device *master;
-
-       of_platform_populate(node, NULL, NULL, dev);
-
-       platform_driver_register(&sti_drm_master_driver);
-       master = platform_device_register_resndata(dev,
-                       DRIVER_NAME "__master", -1,
-                       NULL, 0, NULL, 0);
-       if (IS_ERR(master))
-               return PTR_ERR(master);
-
-       platform_set_drvdata(pdev, master);
-       return 0;
-}
-
-static int sti_drm_platform_remove(struct platform_device *pdev)
-{
-       struct platform_device *master = platform_get_drvdata(pdev);
-
+       component_master_del(&pdev->dev, &sti_ops);
        of_platform_depopulate(&pdev->dev);
-       platform_device_unregister(master);
-       platform_driver_unregister(&sti_drm_master_driver);
+
        return 0;
 }
 
-static const struct of_device_id sti_drm_dt_ids[] = {
+static const struct of_device_id sti_dt_ids[] = {
        { .compatible = "st,sti-display-subsystem", },
        { /* end node */ },
 };
-MODULE_DEVICE_TABLE(of, sti_drm_dt_ids);
+MODULE_DEVICE_TABLE(of, sti_dt_ids);
 
-static struct platform_driver sti_drm_platform_driver = {
-       .probe = sti_drm_platform_probe,
-       .remove = sti_drm_platform_remove,
+static struct platform_driver sti_platform_driver = {
+       .probe = sti_platform_probe,
+       .remove = sti_platform_remove,
        .driver = {
                .name = DRIVER_NAME,
-               .of_match_table = sti_drm_dt_ids,
+               .of_match_table = sti_dt_ids,
        },
 };
 
-module_platform_driver(sti_drm_platform_driver);
+module_platform_driver(sti_platform_driver);
 
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
similarity index 90%
rename from drivers/gpu/drm/sti/sti_drm_drv.h
rename to drivers/gpu/drm/sti/sti_drv.h
index c413aa3ff4021449791f3ce73668d8beabdb94c9..9372f69e1859ff96986b0cea5c795f3d3325c047 100644 (file)
@@ -4,8 +4,8 @@
  * License terms:  GNU General Public License (GPL), version 2
  */
 
-#ifndef _STI_DRM_DRV_H_
-#define _STI_DRM_DRV_H_
+#ifndef _STI_DRV_H_
+#define _STI_DRV_H_
 
 #include <drm/drmP.h>
 
@@ -20,7 +20,7 @@ struct sti_tvout;
  * @plane_zorder_property: z-order property for CRTC planes
  * @drm_dev:               drm device
  */
-struct sti_drm_private {
+struct sti_private {
        struct sti_compositor *compo;
        struct drm_property *plane_zorder_property;
        struct drm_device *drm_dev;
index 087906fd884685a4f22454974ebfd966a05a2f1f..9365670427ad26ef7224b085557c678769c63c6c 100644 (file)
@@ -9,9 +9,12 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
 #include "sti_compositor.h"
 #include "sti_gdp.h"
-#include "sti_layer.h"
+#include "sti_plane.h"
 #include "sti_vtg.h"
 
 #define ALPHASWITCH     BIT(6)
@@ -26,7 +29,7 @@
 #define GDP_XBGR8888    (GDP_RGB888_32 | BIGNOTLITTLE | ALPHASWITCH)
 #define GDP_ARGB8565    0x04
 #define GDP_ARGB8888    0x05
-#define GDP_ABGR8888   (GDP_ARGB8888 | BIGNOTLITTLE | ALPHASWITCH)
+#define GDP_ABGR8888    (GDP_ARGB8888 | BIGNOTLITTLE | ALPHASWITCH)
 #define GDP_ARGB1555    0x06
 #define GDP_ARGB4444    0x07
 #define GDP_CLUT8       0x0B
@@ -53,8 +56,8 @@
 #define GAM_GDP_PPT_IGNORE      (BIT(1) | BIT(0))
 #define GAM_GDP_SIZE_MAX        0x7FF
 
-#define GDP_NODE_NB_BANK       2
-#define GDP_NODE_PER_FIELD     2
+#define GDP_NODE_NB_BANK        2
+#define GDP_NODE_PER_FIELD      2
 
 struct sti_gdp_node {
        u32 gam_gdp_ctl;
@@ -85,16 +88,20 @@ struct sti_gdp_node_list {
 /**
  * STI GDP structure
  *
- * @layer:             layer structure
+ * @sti_plane:          sti_plane structure
+ * @dev:                driver device
+ * @regs:               gdp registers
  * @clk_pix:            pixel clock for the current gdp
  * @clk_main_parent:    gdp parent clock if main path used
  * @clk_aux_parent:     gdp parent clock if aux path used
  * @vtg_field_nb:       callback for VTG FIELD (top or bottom) notification
  * @is_curr_top:        true if the current node processed is the top field
- * @node_list:         array of node list
+ * @node_list:          array of node list
  */
 struct sti_gdp {
-       struct sti_layer layer;
+       struct sti_plane plane;
+       struct device *dev;
+       void __iomem *regs;
        struct clk *clk_pix;
        struct clk *clk_main_parent;
        struct clk *clk_aux_parent;
@@ -103,7 +110,7 @@ struct sti_gdp {
        struct sti_gdp_node_list node_list[GDP_NODE_NB_BANK];
 };
 
-#define to_sti_gdp(x) container_of(x, struct sti_gdp, layer)
+#define to_sti_gdp(x) container_of(x, struct sti_gdp, plane)
 
 static const uint32_t gdp_supported_formats[] = {
        DRM_FORMAT_XRGB8888,
@@ -120,16 +127,6 @@ static const uint32_t gdp_supported_formats[] = {
        DRM_FORMAT_C8,
 };
 
-static const uint32_t *sti_gdp_get_formats(struct sti_layer *layer)
-{
-       return gdp_supported_formats;
-}
-
-static unsigned int sti_gdp_get_nb_formats(struct sti_layer *layer)
-{
-       return ARRAY_SIZE(gdp_supported_formats);
-}
-
 static int sti_gdp_fourcc2format(int fourcc)
 {
        switch (fourcc) {
@@ -175,20 +172,19 @@ static int sti_gdp_get_alpharange(int format)
 
 /**
  * sti_gdp_get_free_nodes
- * @layer: gdp layer
+ * @gdp: gdp pointer
  *
  * Look for a GDP node list that is not currently read by the HW.
  *
  * RETURNS:
  * Pointer to the free GDP node list
  */
-static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer)
+static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_gdp *gdp)
 {
        int hw_nvn;
-       struct sti_gdp *gdp = to_sti_gdp(layer);
        unsigned int i;
 
-       hw_nvn = readl(layer->regs + GAM_GDP_NVN_OFFSET);
+       hw_nvn = readl(gdp->regs + GAM_GDP_NVN_OFFSET);
        if (!hw_nvn)
                goto end;
 
@@ -199,7 +195,7 @@ static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer)
 
        /* in hazardious cases restart with the first node */
        DRM_ERROR("inconsistent NVN for %s: 0x%08X\n",
-                       sti_layer_to_str(layer), hw_nvn);
+                       sti_plane_to_str(&gdp->plane), hw_nvn);
 
 end:
        return &gdp->node_list[0];
@@ -207,7 +203,7 @@ end:
 
 /**
  * sti_gdp_get_current_nodes
- * @layer: GDP layer
+ * @gdp: gdp pointer
  *
  * Look for GDP nodes that are currently read by the HW.
  *
@@ -215,13 +211,12 @@ end:
  * Pointer to the current GDP node list
  */
 static
-struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer)
+struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_gdp *gdp)
 {
        int hw_nvn;
-       struct sti_gdp *gdp = to_sti_gdp(layer);
        unsigned int i;
 
-       hw_nvn = readl(layer->regs + GAM_GDP_NVN_OFFSET);
+       hw_nvn = readl(gdp->regs + GAM_GDP_NVN_OFFSET);
        if (!hw_nvn)
                goto end;
 
@@ -232,205 +227,25 @@ struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer)
 
 end:
        DRM_DEBUG_DRIVER("Warning, NVN 0x%08X for %s does not match any node\n",
-                               hw_nvn, sti_layer_to_str(layer));
+                               hw_nvn, sti_plane_to_str(&gdp->plane));
 
        return NULL;
 }
 
 /**
- * sti_gdp_prepare_layer
- * @lay: gdp layer
- * @first_prepare: true if it is the first time this function is called
- *
- * Update the free GDP node list according to the layer properties.
- *
- * RETURNS:
- * 0 on success.
- */
-static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
-{
-       struct sti_gdp_node_list *list;
-       struct sti_gdp_node *top_field, *btm_field;
-       struct drm_display_mode *mode = layer->mode;
-       struct device *dev = layer->dev;
-       struct sti_gdp *gdp = to_sti_gdp(layer);
-       struct sti_compositor *compo = dev_get_drvdata(dev);
-       int format;
-       unsigned int depth, bpp;
-       int rate = mode->clock * 1000;
-       int res;
-       u32 ydo, xdo, yds, xds;
-
-       list = sti_gdp_get_free_nodes(layer);
-       top_field = list->top_field;
-       btm_field = list->btm_field;
-
-       dev_dbg(dev, "%s %s top_node:0x%p btm_node:0x%p\n", __func__,
-                       sti_layer_to_str(layer), top_field, btm_field);
-
-       /* Build the top field from layer params */
-       top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE;
-       top_field->gam_gdp_ctl = WAIT_NEXT_VSYNC;
-       format = sti_gdp_fourcc2format(layer->format);
-       if (format == -1) {
-               DRM_ERROR("Format not supported by GDP %.4s\n",
-                         (char *)&layer->format);
-               return 1;
-       }
-       top_field->gam_gdp_ctl |= format;
-       top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format);
-       top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE;
-
-       /* pixel memory location */
-       drm_fb_get_bpp_depth(layer->format, &depth, &bpp);
-       top_field->gam_gdp_pml = (u32) layer->paddr + layer->offsets[0];
-       top_field->gam_gdp_pml += layer->src_x * (bpp >> 3);
-       top_field->gam_gdp_pml += layer->src_y * layer->pitches[0];
-
-       /* input parameters */
-       top_field->gam_gdp_pmp = layer->pitches[0];
-       top_field->gam_gdp_size =
-           clamp_val(layer->src_h, 0, GAM_GDP_SIZE_MAX) << 16 |
-           clamp_val(layer->src_w, 0, GAM_GDP_SIZE_MAX);
-
-       /* output parameters */
-       ydo = sti_vtg_get_line_number(*mode, layer->dst_y);
-       yds = sti_vtg_get_line_number(*mode, layer->dst_y + layer->dst_h - 1);
-       xdo = sti_vtg_get_pixel_number(*mode, layer->dst_x);
-       xds = sti_vtg_get_pixel_number(*mode, layer->dst_x + layer->dst_w - 1);
-       top_field->gam_gdp_vpo = (ydo << 16) | xdo;
-       top_field->gam_gdp_vps = (yds << 16) | xds;
-
-       /* Same content and chained together */
-       memcpy(btm_field, top_field, sizeof(*btm_field));
-       top_field->gam_gdp_nvn = list->btm_field_paddr;
-       btm_field->gam_gdp_nvn = list->top_field_paddr;
-
-       /* Interlaced mode */
-       if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE)
-               btm_field->gam_gdp_pml = top_field->gam_gdp_pml +
-                   layer->pitches[0];
-
-       if (first_prepare) {
-               /* Register gdp callback */
-               if (sti_vtg_register_client(layer->mixer_id == STI_MIXER_MAIN ?
-                               compo->vtg_main : compo->vtg_aux,
-                               &gdp->vtg_field_nb, layer->mixer_id)) {
-                       DRM_ERROR("Cannot register VTG notifier\n");
-                       return 1;
-               }
-
-               /* Set and enable gdp clock */
-               if (gdp->clk_pix) {
-                       struct clk *clkp;
-                       /* According to the mixer used, the gdp pixel clock
-                        * should have a different parent clock. */
-                       if (layer->mixer_id == STI_MIXER_MAIN)
-                               clkp = gdp->clk_main_parent;
-                       else
-                               clkp = gdp->clk_aux_parent;
-
-                       if (clkp)
-                               clk_set_parent(gdp->clk_pix, clkp);
-
-                       res = clk_set_rate(gdp->clk_pix, rate);
-                       if (res < 0) {
-                               DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
-                                               rate);
-                               return 1;
-                       }
-
-                       if (clk_prepare_enable(gdp->clk_pix)) {
-                               DRM_ERROR("Failed to prepare/enable gdp\n");
-                               return 1;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-/**
- * sti_gdp_commit_layer
- * @lay: gdp layer
- *
- * Update the NVN field of the 'right' field of the current GDP node (being
- * used by the HW) with the address of the updated ('free') top field GDP node.
- * - In interlaced mode the 'right' field is the bottom field as we update
- *   frames starting from their top field
- * - In progressive mode, we update both bottom and top fields which are
- *   equal nodes.
- * At the next VSYNC, the updated node list will be used by the HW.
- *
- * RETURNS:
- * 0 on success.
- */
-static int sti_gdp_commit_layer(struct sti_layer *layer)
-{
-       struct sti_gdp_node_list *updated_list = sti_gdp_get_free_nodes(layer);
-       struct sti_gdp_node *updated_top_node = updated_list->top_field;
-       struct sti_gdp_node *updated_btm_node = updated_list->btm_field;
-       struct sti_gdp *gdp = to_sti_gdp(layer);
-       u32 dma_updated_top = updated_list->top_field_paddr;
-       u32 dma_updated_btm = updated_list->btm_field_paddr;
-       struct sti_gdp_node_list *curr_list = sti_gdp_get_current_nodes(layer);
-
-       dev_dbg(layer->dev, "%s %s top/btm_node:0x%p/0x%p\n", __func__,
-                       sti_layer_to_str(layer),
-                       updated_top_node, updated_btm_node);
-       dev_dbg(layer->dev, "Current NVN:0x%X\n",
-               readl(layer->regs + GAM_GDP_NVN_OFFSET));
-       dev_dbg(layer->dev, "Posted buff: %lx current buff: %x\n",
-               (unsigned long)layer->paddr,
-               readl(layer->regs + GAM_GDP_PML_OFFSET));
-
-       if (curr_list == NULL) {
-               /* First update or invalid node should directly write in the
-                * hw register */
-               DRM_DEBUG_DRIVER("%s first update (or invalid node)",
-                               sti_layer_to_str(layer));
-
-               writel(gdp->is_curr_top == true ?
-                               dma_updated_btm : dma_updated_top,
-                               layer->regs + GAM_GDP_NVN_OFFSET);
-               return 0;
-       }
-
-       if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE) {
-               if (gdp->is_curr_top == true) {
-                       /* Do not update in the middle of the frame, but
-                        * postpone the update after the bottom field has
-                        * been displayed */
-                       curr_list->btm_field->gam_gdp_nvn = dma_updated_top;
-               } else {
-                       /* Direct update to avoid one frame delay */
-                       writel(dma_updated_top,
-                               layer->regs + GAM_GDP_NVN_OFFSET);
-               }
-       } else {
-               /* Direct update for progressive to avoid one frame delay */
-               writel(dma_updated_top, layer->regs + GAM_GDP_NVN_OFFSET);
-       }
-
-       return 0;
-}
-
-/**
- * sti_gdp_disable_layer
- * @lay: gdp layer
+ * sti_gdp_disable
+ * @gdp: gdp pointer
  *
  * Disable a GDP.
- *
- * RETURNS:
- * 0 on success.
  */
-static int sti_gdp_disable_layer(struct sti_layer *layer)
+static void sti_gdp_disable(struct sti_gdp *gdp)
 {
+       struct drm_plane *drm_plane = &gdp->plane.drm_plane;
+       struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
+       struct sti_compositor *compo = dev_get_drvdata(gdp->dev);
        unsigned int i;
-       struct sti_gdp *gdp = to_sti_gdp(layer);
-       struct sti_compositor *compo = dev_get_drvdata(layer->dev);
 
-       DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
+       DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(&gdp->plane));
 
        /* Set the nodes as 'to be ignored on mixer' */
        for (i = 0; i < GDP_NODE_NB_BANK; i++) {
@@ -438,14 +253,14 @@ static int sti_gdp_disable_layer(struct sti_layer *layer)
                gdp->node_list[i].btm_field->gam_gdp_ppt |= GAM_GDP_PPT_IGNORE;
        }
 
-       if (sti_vtg_unregister_client(layer->mixer_id == STI_MIXER_MAIN ?
+       if (sti_vtg_unregister_client(mixer->id == STI_MIXER_MAIN ?
                        compo->vtg_main : compo->vtg_aux, &gdp->vtg_field_nb))
                DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
 
        if (gdp->clk_pix)
                clk_disable_unprepare(gdp->clk_pix);
 
-       return 0;
+       gdp->plane.status = STI_PLANE_DISABLED;
 }
 
 /**
@@ -464,6 +279,14 @@ int sti_gdp_field_cb(struct notifier_block *nb,
 {
        struct sti_gdp *gdp = container_of(nb, struct sti_gdp, vtg_field_nb);
 
+       if (gdp->plane.status == STI_PLANE_FLUSHING) {
+               /* disable need to be synchronize on vsync event */
+               DRM_DEBUG_DRIVER("Vsync event received => disable %s\n",
+                                sti_plane_to_str(&gdp->plane));
+
+               sti_gdp_disable(gdp);
+       }
+
        switch (event) {
        case VTG_TOP_FIELD_EVENT:
                gdp->is_curr_top = true;
@@ -479,10 +302,9 @@ int sti_gdp_field_cb(struct notifier_block *nb,
        return 0;
 }
 
-static void sti_gdp_init(struct sti_layer *layer)
+static void sti_gdp_init(struct sti_gdp *gdp)
 {
-       struct sti_gdp *gdp = to_sti_gdp(layer);
-       struct device_node *np = layer->dev->of_node;
+       struct device_node *np = gdp->dev->of_node;
        dma_addr_t dma_addr;
        void *base;
        unsigned int i, size;
@@ -490,8 +312,8 @@ static void sti_gdp_init(struct sti_layer *layer)
        /* Allocate all the nodes within a single memory page */
        size = sizeof(struct sti_gdp_node) *
            GDP_NODE_PER_FIELD * GDP_NODE_NB_BANK;
-       base = dma_alloc_writecombine(layer->dev,
-                       size, &dma_addr, GFP_KERNEL | GFP_DMA);
+       base = dma_alloc_writecombine(gdp->dev,
+                                     size, &dma_addr, GFP_KERNEL | GFP_DMA);
 
        if (!base) {
                DRM_ERROR("Failed to allocate memory for GDP node\n");
@@ -526,7 +348,7 @@ static void sti_gdp_init(struct sti_layer *layer)
                /* GDP of STiH407 chip have its own pixel clock */
                char *clk_name;
 
-               switch (layer->desc) {
+               switch (gdp->plane.desc) {
                case STI_GDP_0:
                        clk_name = "pix_gdp1";
                        break;
@@ -544,32 +366,249 @@ static void sti_gdp_init(struct sti_layer *layer)
                        return;
                }
 
-               gdp->clk_pix = devm_clk_get(layer->dev, clk_name);
+               gdp->clk_pix = devm_clk_get(gdp->dev, clk_name);
                if (IS_ERR(gdp->clk_pix))
                        DRM_ERROR("Cannot get %s clock\n", clk_name);
 
-               gdp->clk_main_parent = devm_clk_get(layer->dev, "main_parent");
+               gdp->clk_main_parent = devm_clk_get(gdp->dev, "main_parent");
                if (IS_ERR(gdp->clk_main_parent))
                        DRM_ERROR("Cannot get main_parent clock\n");
 
-               gdp->clk_aux_parent = devm_clk_get(layer->dev, "aux_parent");
+               gdp->clk_aux_parent = devm_clk_get(gdp->dev, "aux_parent");
                if (IS_ERR(gdp->clk_aux_parent))
                        DRM_ERROR("Cannot get aux_parent clock\n");
        }
 }
 
-static const struct sti_layer_funcs gdp_ops = {
-       .get_formats = sti_gdp_get_formats,
-       .get_nb_formats = sti_gdp_get_nb_formats,
-       .init = sti_gdp_init,
-       .prepare = sti_gdp_prepare_layer,
-       .commit = sti_gdp_commit_layer,
-       .disable = sti_gdp_disable_layer,
+static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
+                                 struct drm_plane_state *oldstate)
+{
+       struct drm_plane_state *state = drm_plane->state;
+       struct sti_plane *plane = to_sti_plane(drm_plane);
+       struct sti_gdp *gdp = to_sti_gdp(plane);
+       struct drm_crtc *crtc = state->crtc;
+       struct sti_compositor *compo = dev_get_drvdata(gdp->dev);
+       struct drm_framebuffer *fb =  state->fb;
+       bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
+       struct sti_mixer *mixer;
+       struct drm_display_mode *mode;
+       int dst_x, dst_y, dst_w, dst_h;
+       int src_x, src_y, src_w, src_h;
+       struct drm_gem_cma_object *cma_obj;
+       struct sti_gdp_node_list *list;
+       struct sti_gdp_node_list *curr_list;
+       struct sti_gdp_node *top_field, *btm_field;
+       u32 dma_updated_top;
+       u32 dma_updated_btm;
+       int format;
+       unsigned int depth, bpp;
+       u32 ydo, xdo, yds, xds;
+       int res;
+
+       /* Manage the case where crtc is null (disabled) */
+       if (!crtc)
+               return;
+
+       mixer = to_sti_mixer(crtc);
+       mode = &crtc->mode;
+       dst_x = state->crtc_x;
+       dst_y = state->crtc_y;
+       dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
+       dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
+       /* src_x are in 16.16 format */
+       src_x = state->src_x >> 16;
+       src_y = state->src_y >> 16;
+       src_w = state->src_w >> 16;
+       src_h = state->src_h >> 16;
+
+       DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
+                     crtc->base.id, sti_mixer_to_str(mixer),
+                     drm_plane->base.id, sti_plane_to_str(plane));
+       DRM_DEBUG_KMS("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
+                     sti_plane_to_str(plane),
+                     dst_w, dst_h, dst_x, dst_y,
+                     src_w, src_h, src_x, src_y);
+
+       list = sti_gdp_get_free_nodes(gdp);
+       top_field = list->top_field;
+       btm_field = list->btm_field;
+
+       dev_dbg(gdp->dev, "%s %s top_node:0x%p btm_node:0x%p\n", __func__,
+               sti_plane_to_str(plane), top_field, btm_field);
+
+       /* build the top field */
+       top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE;
+       top_field->gam_gdp_ctl = WAIT_NEXT_VSYNC;
+       format = sti_gdp_fourcc2format(fb->pixel_format);
+       if (format == -1) {
+               DRM_ERROR("Format not supported by GDP %.4s\n",
+                         (char *)&fb->pixel_format);
+               return;
+       }
+       top_field->gam_gdp_ctl |= format;
+       top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format);
+       top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE;
+
+       cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       if (!cma_obj) {
+               DRM_ERROR("Can't get CMA GEM object for fb\n");
+               return;
+       }
+
+       DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
+                        (char *)&fb->pixel_format,
+                        (unsigned long)cma_obj->paddr);
+
+       /* pixel memory location */
+       drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
+       top_field->gam_gdp_pml = (u32)cma_obj->paddr + fb->offsets[0];
+       top_field->gam_gdp_pml += src_x * (bpp >> 3);
+       top_field->gam_gdp_pml += src_y * fb->pitches[0];
+
+       /* input parameters */
+       top_field->gam_gdp_pmp = fb->pitches[0];
+       top_field->gam_gdp_size = clamp_val(src_h, 0, GAM_GDP_SIZE_MAX) << 16 |
+                                 clamp_val(src_w, 0, GAM_GDP_SIZE_MAX);
+
+       /* output parameters */
+       ydo = sti_vtg_get_line_number(*mode, dst_y);
+       yds = sti_vtg_get_line_number(*mode, dst_y + dst_h - 1);
+       xdo = sti_vtg_get_pixel_number(*mode, dst_x);
+       xds = sti_vtg_get_pixel_number(*mode, dst_x + dst_w - 1);
+       top_field->gam_gdp_vpo = (ydo << 16) | xdo;
+       top_field->gam_gdp_vps = (yds << 16) | xds;
+
+       /* Same content and chained together */
+       memcpy(btm_field, top_field, sizeof(*btm_field));
+       top_field->gam_gdp_nvn = list->btm_field_paddr;
+       btm_field->gam_gdp_nvn = list->top_field_paddr;
+
+       /* Interlaced mode */
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+               btm_field->gam_gdp_pml = top_field->gam_gdp_pml +
+                                        fb->pitches[0];
+
+       if (first_prepare) {
+               /* Register gdp callback */
+               if (sti_vtg_register_client(mixer->id == STI_MIXER_MAIN ?
+                               compo->vtg_main : compo->vtg_aux,
+                               &gdp->vtg_field_nb, mixer->id)) {
+                       DRM_ERROR("Cannot register VTG notifier\n");
+                       return;
+               }
+
+               /* Set and enable gdp clock */
+               if (gdp->clk_pix) {
+                       struct clk *clkp;
+                       int rate = mode->clock * 1000;
+
+                       /* According to the mixer used, the gdp pixel clock
+                        * should have a different parent clock. */
+                       if (mixer->id == STI_MIXER_MAIN)
+                               clkp = gdp->clk_main_parent;
+                       else
+                               clkp = gdp->clk_aux_parent;
+
+                       if (clkp)
+                               clk_set_parent(gdp->clk_pix, clkp);
+
+                       res = clk_set_rate(gdp->clk_pix, rate);
+                       if (res < 0) {
+                               DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
+                                         rate);
+                               return;
+                       }
+
+                       if (clk_prepare_enable(gdp->clk_pix)) {
+                               DRM_ERROR("Failed to prepare/enable gdp\n");
+                               return;
+                       }
+               }
+       }
+
+       /* Update the NVN field of the 'right' field of the current GDP node
+        * (being used by the HW) with the address of the updated ('free') top
+        * field GDP node.
+        * - In interlaced mode the 'right' field is the bottom field as we
+        *   update frames starting from their top field
+        * - In progressive mode, we update both bottom and top fields which
+        *   are equal nodes.
+        * At the next VSYNC, the updated node list will be used by the HW.
+        */
+       curr_list = sti_gdp_get_current_nodes(gdp);
+       dma_updated_top = list->top_field_paddr;
+       dma_updated_btm = list->btm_field_paddr;
+
+       dev_dbg(gdp->dev, "Current NVN:0x%X\n",
+               readl(gdp->regs + GAM_GDP_NVN_OFFSET));
+       dev_dbg(gdp->dev, "Posted buff: %lx current buff: %x\n",
+               (unsigned long)cma_obj->paddr,
+               readl(gdp->regs + GAM_GDP_PML_OFFSET));
+
+       if (!curr_list) {
+               /* First update or invalid node should directly write in the
+                * hw register */
+               DRM_DEBUG_DRIVER("%s first update (or invalid node)",
+                                sti_plane_to_str(plane));
+
+               writel(gdp->is_curr_top ?
+                               dma_updated_btm : dma_updated_top,
+                               gdp->regs + GAM_GDP_NVN_OFFSET);
+               goto end;
+       }
+
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+               if (gdp->is_curr_top) {
+                       /* Do not update in the middle of the frame, but
+                        * postpone the update after the bottom field has
+                        * been displayed */
+                       curr_list->btm_field->gam_gdp_nvn = dma_updated_top;
+               } else {
+                       /* Direct update to avoid one frame delay */
+                       writel(dma_updated_top,
+                              gdp->regs + GAM_GDP_NVN_OFFSET);
+               }
+       } else {
+               /* Direct update for progressive to avoid one frame delay */
+               writel(dma_updated_top, gdp->regs + GAM_GDP_NVN_OFFSET);
+       }
+
+end:
+       plane->status = STI_PLANE_UPDATED;
+}
+
+static void sti_gdp_atomic_disable(struct drm_plane *drm_plane,
+                                  struct drm_plane_state *oldstate)
+{
+       struct sti_plane *plane = to_sti_plane(drm_plane);
+       struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
+
+       if (!drm_plane->crtc) {
+               DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
+                                drm_plane->base.id);
+               return;
+       }
+
+       DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+                        drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
+                        drm_plane->base.id, sti_plane_to_str(plane));
+
+       plane->status = STI_PLANE_DISABLING;
+}
+
+static const struct drm_plane_helper_funcs sti_gdp_helpers_funcs = {
+       .atomic_update = sti_gdp_atomic_update,
+       .atomic_disable = sti_gdp_atomic_disable,
 };
 
-struct sti_layer *sti_gdp_create(struct device *dev, int id)
+struct drm_plane *sti_gdp_create(struct drm_device *drm_dev,
+                                struct device *dev, int desc,
+                                void __iomem *baseaddr,
+                                unsigned int possible_crtcs,
+                                enum drm_plane_type type)
 {
        struct sti_gdp *gdp;
+       int res;
 
        gdp = devm_kzalloc(dev, sizeof(*gdp), GFP_KERNEL);
        if (!gdp) {
@@ -577,8 +616,33 @@ struct sti_layer *sti_gdp_create(struct device *dev, int id)
                return NULL;
        }
 
-       gdp->layer.ops = &gdp_ops;
+       gdp->dev = dev;
+       gdp->regs = baseaddr;
+       gdp->plane.desc = desc;
+       gdp->plane.status = STI_PLANE_DISABLED;
+
        gdp->vtg_field_nb.notifier_call = sti_gdp_field_cb;
 
-       return (struct sti_layer *)gdp;
+       sti_gdp_init(gdp);
+
+       res = drm_universal_plane_init(drm_dev, &gdp->plane.drm_plane,
+                                      possible_crtcs,
+                                      &sti_plane_helpers_funcs,
+                                      gdp_supported_formats,
+                                      ARRAY_SIZE(gdp_supported_formats),
+                                      type);
+       if (res) {
+               DRM_ERROR("Failed to initialize universal plane\n");
+               goto err;
+       }
+
+       drm_plane_helper_add(&gdp->plane.drm_plane, &sti_gdp_helpers_funcs);
+
+       sti_plane_init_property(&gdp->plane, type);
+
+       return &gdp->plane.drm_plane;
+
+err:
+       devm_kfree(dev, gdp);
+       return NULL;
 }
index 1dab68274ad3e542e770d993fbacf29d9f6b38d1..73947a4a800472f9aafa02fd5da73e42fb06cff5 100644 (file)
@@ -11,6 +11,9 @@
 
 #include <linux/types.h>
 
-struct sti_layer *sti_gdp_create(struct device *dev, int id);
-
+struct drm_plane *sti_gdp_create(struct drm_device *drm_dev,
+                                struct device *dev, int desc,
+                                void __iomem *baseaddr,
+                                unsigned int possible_crtcs,
+                                enum drm_plane_type type);
 #endif
index f28a4d54487c7636fee9e1a4f5ca80ecf73adcc6..09e29e43423e21e6326b54e159ed81ffc4114b86 100644 (file)
@@ -588,7 +588,7 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
        return count;
 
 fail:
-       DRM_ERROR("Can not read HDMI EDID\n");
+       DRM_ERROR("Can't read HDMI EDID\n");
        return 0;
 }
 
@@ -693,21 +693,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
        struct sti_hdmi_connector *connector;
        struct drm_connector *drm_connector;
        struct drm_bridge *bridge;
-       struct device_node *ddc;
        int err;
 
-       ddc = of_parse_phandle(dev->of_node, "ddc", 0);
-       if (ddc) {
-               hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc);
-               if (!hdmi->ddc_adapt) {
-                       err = -EPROBE_DEFER;
-                       of_node_put(ddc);
-                       return err;
-               }
-
-               of_node_put(ddc);
-       }
-
        /* Set the drm device handle */
        hdmi->drm_dev = drm_dev;
 
@@ -796,6 +783,7 @@ static int sti_hdmi_probe(struct platform_device *pdev)
        struct sti_hdmi *hdmi;
        struct device_node *np = dev->of_node;
        struct resource *res;
+       struct device_node *ddc;
        int ret;
 
        DRM_INFO("%s\n", __func__);
@@ -804,6 +792,17 @@ static int sti_hdmi_probe(struct platform_device *pdev)
        if (!hdmi)
                return -ENOMEM;
 
+       ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0);
+       if (ddc) {
+               hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc);
+               if (!hdmi->ddc_adapt) {
+                       of_node_put(ddc);
+                       return -EPROBE_DEFER;
+               }
+
+               of_node_put(ddc);
+       }
+
        hdmi->dev = pdev->dev;
 
        /* Get resources */
index b0eb62de1b2ecc7d4446de5b946e972649dd725d..7c8f9b8bfae10a27339b6693b462406500639c6c 100644 (file)
 #include <linux/reset.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
 
-#include "sti_drm_plane.h"
-#include "sti_hqvdp.h"
+#include "sti_compositor.h"
 #include "sti_hqvdp_lut.h"
-#include "sti_layer.h"
+#include "sti_plane.h"
 #include "sti_vtg.h"
 
 /* Firmware name */
@@ -322,8 +323,7 @@ struct sti_hqvdp_cmd {
  * @dev:               driver device
  * @drm_dev:           the drm device
  * @regs:              registers
- * @layer:             layer structure for hqvdp it self
- * @vid_plane:         VID plug used as link with compositor IP
+ * @plane:             plane structure for hqvdp it self
  * @clk:               IP clock
  * @clk_pix_main:      pix main clock
  * @reset:             reset control
@@ -334,13 +334,13 @@ struct sti_hqvdp_cmd {
  * @hqvdp_cmd:         buffer of commands
  * @hqvdp_cmd_paddr:   physical address of hqvdp_cmd
  * @vtg:               vtg for main data path
+ * @xp70_initialized:  true if xp70 is already initialized
  */
 struct sti_hqvdp {
        struct device *dev;
        struct drm_device *drm_dev;
        void __iomem *regs;
-       struct sti_layer layer;
-       struct drm_plane *vid_plane;
+       struct sti_plane plane;
        struct clk *clk;
        struct clk *clk_pix_main;
        struct reset_control *reset;
@@ -351,24 +351,15 @@ struct sti_hqvdp {
        void *hqvdp_cmd;
        dma_addr_t hqvdp_cmd_paddr;
        struct sti_vtg *vtg;
+       bool xp70_initialized;
 };
 
-#define to_sti_hqvdp(x) container_of(x, struct sti_hqvdp, layer)
+#define to_sti_hqvdp(x) container_of(x, struct sti_hqvdp, plane)
 
 static const uint32_t hqvdp_supported_formats[] = {
        DRM_FORMAT_NV12,
 };
 
-static const uint32_t *sti_hqvdp_get_formats(struct sti_layer *layer)
-{
-       return hqvdp_supported_formats;
-}
-
-static unsigned int sti_hqvdp_get_nb_formats(struct sti_layer *layer)
-{
-       return ARRAY_SIZE(hqvdp_supported_formats);
-}
-
 /**
  * sti_hqvdp_get_free_cmd
  * @hqvdp: hqvdp structure
@@ -484,7 +475,12 @@ static void sti_hqvdp_update_hvsrc(enum sti_hvsrc_orient orient, int scale,
 
 /**
  * sti_hqvdp_check_hw_scaling
- * @layer: hqvdp layer
+ * @hqvdp: hqvdp pointer
+ * @mode: display mode with timing constraints
+ * @src_w: source width
+ * @src_h: source height
+ * @dst_w: destination width
+ * @dst_h: destination height
  *
  * Check if the HW is able to perform the scaling request
  * The firmware scaling limitation is "CEIL(1/Zy) <= FLOOR(LFW)" where:
@@ -498,184 +494,36 @@ static void sti_hqvdp_update_hvsrc(enum sti_hvsrc_orient orient, int scale,
  * RETURNS:
  * True if the HW can scale.
  */
-static bool sti_hqvdp_check_hw_scaling(struct sti_layer *layer)
+static bool sti_hqvdp_check_hw_scaling(struct sti_hqvdp *hqvdp,
+                                      struct drm_display_mode *mode,
+                                      int src_w, int src_h,
+                                      int dst_w, int dst_h)
 {
-       struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
        unsigned long lfw;
        unsigned int inv_zy;
 
-       lfw = layer->mode->htotal * (clk_get_rate(hqvdp->clk) / 1000000);
-       lfw /= max(layer->src_w, layer->dst_w) * layer->mode->clock / 1000;
+       lfw = mode->htotal * (clk_get_rate(hqvdp->clk) / 1000000);
+       lfw /= max(src_w, dst_w) * mode->clock / 1000;
 
-       inv_zy = DIV_ROUND_UP(layer->src_h, layer->dst_h);
+       inv_zy = DIV_ROUND_UP(src_h, dst_h);
 
        return (inv_zy <= lfw) ? true : false;
 }
 
 /**
- * sti_hqvdp_prepare_layer
- * @layer: hqvdp layer
- * @first_prepare: true if it is the first time this function is called
+ * sti_hqvdp_disable
+ * @hqvdp: hqvdp pointer
  *
- * Prepares a command for the firmware
- *
- * RETURNS:
- * 0 on success.
+ * Disables the HQVDP plane
  */
-static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
-{
-       struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
-       struct sti_hqvdp_cmd *cmd;
-       int scale_h, scale_v;
-       int cmd_offset;
-
-       dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_layer_to_str(layer));
-
-       /* prepare and commit VID plane */
-       hqvdp->vid_plane->funcs->update_plane(hqvdp->vid_plane,
-                                       layer->crtc, layer->fb,
-                                       layer->dst_x, layer->dst_y,
-                                       layer->dst_w, layer->dst_h,
-                                       layer->src_x, layer->src_y,
-                                       layer->src_w, layer->src_h);
-
-       cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
-       if (cmd_offset == -1) {
-               DRM_ERROR("No available hqvdp_cmd now\n");
-               return -EBUSY;
-       }
-       cmd = hqvdp->hqvdp_cmd + cmd_offset;
-
-       if (!sti_hqvdp_check_hw_scaling(layer)) {
-               DRM_ERROR("Scaling beyond HW capabilities\n");
-               return -EINVAL;
-       }
-
-       /* Static parameters, defaulting to progressive mode */
-       cmd->top.config = TOP_CONFIG_PROGRESSIVE;
-       cmd->top.mem_format = TOP_MEM_FORMAT_DFLT;
-       cmd->hvsrc.param_ctrl = HVSRC_PARAM_CTRL_DFLT;
-       cmd->csdi.config = CSDI_CONFIG_PROG;
-
-       /* VC1RE, FMD bypassed : keep everything set to 0
-        * IQI/P2I bypassed */
-       cmd->iqi.config = IQI_CONFIG_DFLT;
-       cmd->iqi.con_bri = IQI_CON_BRI_DFLT;
-       cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT;
-       cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT;
-
-       /* Buffer planes address */
-       cmd->top.current_luma = (u32) layer->paddr + layer->offsets[0];
-       cmd->top.current_chroma = (u32) layer->paddr + layer->offsets[1];
-
-       /* Pitches */
-       cmd->top.luma_processed_pitch = cmd->top.luma_src_pitch =
-                       layer->pitches[0];
-       cmd->top.chroma_processed_pitch = cmd->top.chroma_src_pitch =
-                       layer->pitches[1];
-
-       /* Input / output size
-        * Align to upper even value */
-       layer->dst_w = ALIGN(layer->dst_w, 2);
-       layer->dst_h = ALIGN(layer->dst_h, 2);
-
-       if ((layer->src_w > MAX_WIDTH) || (layer->src_w < MIN_WIDTH) ||
-           (layer->src_h > MAX_HEIGHT) || (layer->src_h < MIN_HEIGHT) ||
-           (layer->dst_w > MAX_WIDTH) || (layer->dst_w < MIN_WIDTH) ||
-           (layer->dst_h > MAX_HEIGHT) || (layer->dst_h < MIN_HEIGHT)) {
-               DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n",
-                               layer->src_w, layer->src_h,
-                               layer->dst_w, layer->dst_h);
-               return -EINVAL;
-       }
-       cmd->top.input_viewport_size = cmd->top.input_frame_size =
-                       layer->src_h << 16 | layer->src_w;
-       cmd->hvsrc.output_picture_size = layer->dst_h << 16 | layer->dst_w;
-       cmd->top.input_viewport_ori = layer->src_y << 16 | layer->src_x;
-
-       /* Handle interlaced */
-       if (layer->fb->flags & DRM_MODE_FB_INTERLACED) {
-               /* Top field to display */
-               cmd->top.config = TOP_CONFIG_INTER_TOP;
-
-               /* Update pitches and vert size */
-               cmd->top.input_frame_size = (layer->src_h / 2) << 16 |
-                                            layer->src_w;
-               cmd->top.luma_processed_pitch *= 2;
-               cmd->top.luma_src_pitch *= 2;
-               cmd->top.chroma_processed_pitch *= 2;
-               cmd->top.chroma_src_pitch *= 2;
-
-               /* Enable directional deinterlacing processing */
-               cmd->csdi.config = CSDI_CONFIG_INTER_DIR;
-               cmd->csdi.config2 = CSDI_CONFIG2_DFLT;
-               cmd->csdi.dcdi_config = CSDI_DCDI_CONFIG_DFLT;
-       }
-
-       /* Update hvsrc lut coef */
-       scale_h = SCALE_FACTOR * layer->dst_w / layer->src_w;
-       sti_hqvdp_update_hvsrc(HVSRC_HORI, scale_h, &cmd->hvsrc);
-
-       scale_v = SCALE_FACTOR * layer->dst_h / layer->src_h;
-       sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
-
-       if (first_prepare) {
-               /* Prevent VTG shutdown */
-               if (clk_prepare_enable(hqvdp->clk_pix_main)) {
-                       DRM_ERROR("Failed to prepare/enable pix main clk\n");
-                       return -ENXIO;
-               }
-
-               /* Register VTG Vsync callback to handle bottom fields */
-               if ((layer->fb->flags & DRM_MODE_FB_INTERLACED) &&
-                               sti_vtg_register_client(hqvdp->vtg,
-                                       &hqvdp->vtg_nb, layer->mixer_id)) {
-                       DRM_ERROR("Cannot register VTG notifier\n");
-                       return -ENXIO;
-               }
-       }
-
-       return 0;
-}
-
-static int sti_hqvdp_commit_layer(struct sti_layer *layer)
+static void sti_hqvdp_disable(struct sti_hqvdp *hqvdp)
 {
-       struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
-       int cmd_offset;
-
-       dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_layer_to_str(layer));
-
-       cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
-       if (cmd_offset == -1) {
-               DRM_ERROR("No available hqvdp_cmd now\n");
-               return -EBUSY;
-       }
-
-       writel(hqvdp->hqvdp_cmd_paddr + cmd_offset,
-                       hqvdp->regs + HQVDP_MBX_NEXT_CMD);
-
-       hqvdp->curr_field_count++;
-
-       /* Interlaced : get ready to display the bottom field at next Vsync */
-       if (layer->fb->flags & DRM_MODE_FB_INTERLACED)
-               hqvdp->btm_field_pending = true;
-
-       dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n",
-                       __func__, hqvdp->hqvdp_cmd_paddr + cmd_offset);
-
-       return 0;
-}
-
-static int sti_hqvdp_disable_layer(struct sti_layer *layer)
-{
-       struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
        int i;
 
-       DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
+       DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(&hqvdp->plane));
 
        /* Unregister VTG Vsync callback */
-       if ((layer->fb->flags & DRM_MODE_FB_INTERLACED) &&
-               sti_vtg_unregister_client(hqvdp->vtg, &hqvdp->vtg_nb))
+       if (sti_vtg_unregister_client(hqvdp->vtg, &hqvdp->vtg_nb))
                DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
 
        /* Set next cmd to NULL */
@@ -691,15 +539,10 @@ static int sti_hqvdp_disable_layer(struct sti_layer *layer)
        /* VTG can stop now */
        clk_disable_unprepare(hqvdp->clk_pix_main);
 
-       if (i == POLL_MAX_ATTEMPT) {
+       if (i == POLL_MAX_ATTEMPT)
                DRM_ERROR("XP70 could not revert to idle\n");
-               return -ENXIO;
-       }
-
-       /* disable VID plane */
-       hqvdp->vid_plane->funcs->disable_plane(hqvdp->vid_plane);
 
-       return 0;
+       hqvdp->plane.status = STI_PLANE_DISABLED;
 }
 
 /**
@@ -724,6 +567,14 @@ int sti_hqvdp_vtg_cb(struct notifier_block *nb, unsigned long evt, void *data)
                return 0;
        }
 
+       if (hqvdp->plane.status == STI_PLANE_FLUSHING) {
+               /* disable need to be synchronize on vsync event */
+               DRM_DEBUG_DRIVER("Vsync event received => disable %s\n",
+                                sti_plane_to_str(&hqvdp->plane));
+
+               sti_hqvdp_disable(hqvdp);
+       }
+
        if (hqvdp->btm_field_pending) {
                /* Create the btm field command from the current one */
                btm_cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
@@ -758,32 +609,10 @@ int sti_hqvdp_vtg_cb(struct notifier_block *nb, unsigned long evt, void *data)
        return 0;
 }
 
-static struct drm_plane *sti_hqvdp_find_vid(struct drm_device *dev, int id)
+static void sti_hqvdp_init(struct sti_hqvdp *hqvdp)
 {
-       struct drm_plane *plane;
-
-       list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-               struct sti_layer *layer = to_sti_layer(plane);
-
-               if (layer->desc == id)
-                       return plane;
-       }
-
-       return NULL;
-}
-
-static void sti_hqvd_init(struct sti_layer *layer)
-{
-       struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer);
        int size;
 
-       /* find the plane macthing with vid 0 */
-       hqvdp->vid_plane = sti_hqvdp_find_vid(hqvdp->drm_dev, STI_VID_0);
-       if (!hqvdp->vid_plane) {
-               DRM_ERROR("Cannot find Main video layer\n");
-               return;
-       }
-
        hqvdp->vtg_nb.notifier_call = sti_hqvdp_vtg_cb;
 
        /* Allocate memory for the VDP commands */
@@ -799,24 +628,213 @@ static void sti_hqvd_init(struct sti_layer *layer)
        memset(hqvdp->hqvdp_cmd, 0, size);
 }
 
-static const struct sti_layer_funcs hqvdp_ops = {
-       .get_formats = sti_hqvdp_get_formats,
-       .get_nb_formats = sti_hqvdp_get_nb_formats,
-       .init = sti_hqvd_init,
-       .prepare = sti_hqvdp_prepare_layer,
-       .commit = sti_hqvdp_commit_layer,
-       .disable = sti_hqvdp_disable_layer,
+static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
+                                   struct drm_plane_state *oldstate)
+{
+       struct drm_plane_state *state = drm_plane->state;
+       struct sti_plane *plane = to_sti_plane(drm_plane);
+       struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
+       struct drm_crtc *crtc = state->crtc;
+       struct sti_mixer *mixer = to_sti_mixer(crtc);
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_display_mode *mode = &crtc->mode;
+       int dst_x = state->crtc_x;
+       int dst_y = state->crtc_y;
+       int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
+       int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
+       /* src_x are in 16.16 format */
+       int src_x = state->src_x >> 16;
+       int src_y = state->src_y >> 16;
+       int src_w = state->src_w >> 16;
+       int src_h = state->src_h >> 16;
+       bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
+       struct drm_gem_cma_object *cma_obj;
+       struct sti_hqvdp_cmd *cmd;
+       int scale_h, scale_v;
+       int cmd_offset;
+
+       DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
+                     crtc->base.id, sti_mixer_to_str(mixer),
+                     drm_plane->base.id, sti_plane_to_str(plane));
+       DRM_DEBUG_KMS("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
+                     sti_plane_to_str(plane),
+                     dst_w, dst_h, dst_x, dst_y,
+                     src_w, src_h, src_x, src_y);
+
+       cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
+       if (cmd_offset == -1) {
+               DRM_ERROR("No available hqvdp_cmd now\n");
+               return;
+       }
+       cmd = hqvdp->hqvdp_cmd + cmd_offset;
+
+       if (!sti_hqvdp_check_hw_scaling(hqvdp, mode,
+                                       src_w, src_h,
+                                       dst_w, dst_h)) {
+               DRM_ERROR("Scaling beyond HW capabilities\n");
+               return;
+       }
+
+       /* Static parameters, defaulting to progressive mode */
+       cmd->top.config = TOP_CONFIG_PROGRESSIVE;
+       cmd->top.mem_format = TOP_MEM_FORMAT_DFLT;
+       cmd->hvsrc.param_ctrl = HVSRC_PARAM_CTRL_DFLT;
+       cmd->csdi.config = CSDI_CONFIG_PROG;
+
+       /* VC1RE, FMD bypassed : keep everything set to 0
+        * IQI/P2I bypassed */
+       cmd->iqi.config = IQI_CONFIG_DFLT;
+       cmd->iqi.con_bri = IQI_CON_BRI_DFLT;
+       cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT;
+       cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT;
+
+       cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       if (!cma_obj) {
+               DRM_ERROR("Can't get CMA GEM object for fb\n");
+               return;
+       }
+
+       DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
+                        (char *)&fb->pixel_format,
+                        (unsigned long)cma_obj->paddr);
+
+       /* Buffer planes address */
+       cmd->top.current_luma = (u32)cma_obj->paddr + fb->offsets[0];
+       cmd->top.current_chroma = (u32)cma_obj->paddr + fb->offsets[1];
+
+       /* Pitches */
+       cmd->top.luma_processed_pitch = fb->pitches[0];
+       cmd->top.luma_src_pitch = fb->pitches[0];
+       cmd->top.chroma_processed_pitch = fb->pitches[1];
+       cmd->top.chroma_src_pitch = fb->pitches[1];
+
+       /* Input / output size
+        * Align to upper even value */
+       dst_w = ALIGN(dst_w, 2);
+       dst_h = ALIGN(dst_h, 2);
+
+       if ((src_w > MAX_WIDTH) || (src_w < MIN_WIDTH) ||
+           (src_h > MAX_HEIGHT) || (src_h < MIN_HEIGHT) ||
+           (dst_w > MAX_WIDTH) || (dst_w < MIN_WIDTH) ||
+           (dst_h > MAX_HEIGHT) || (dst_h < MIN_HEIGHT)) {
+               DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n",
+                         src_w, src_h,
+                         dst_w, dst_h);
+               return;
+       }
+
+       cmd->top.input_viewport_size = src_h << 16 | src_w;
+       cmd->top.input_frame_size = src_h << 16 | src_w;
+       cmd->hvsrc.output_picture_size = dst_h << 16 | dst_w;
+       cmd->top.input_viewport_ori = src_y << 16 | src_x;
+
+       /* Handle interlaced */
+       if (fb->flags & DRM_MODE_FB_INTERLACED) {
+               /* Top field to display */
+               cmd->top.config = TOP_CONFIG_INTER_TOP;
+
+               /* Update pitches and vert size */
+               cmd->top.input_frame_size = (src_h / 2) << 16 | src_w;
+               cmd->top.luma_processed_pitch *= 2;
+               cmd->top.luma_src_pitch *= 2;
+               cmd->top.chroma_processed_pitch *= 2;
+               cmd->top.chroma_src_pitch *= 2;
+
+               /* Enable directional deinterlacing processing */
+               cmd->csdi.config = CSDI_CONFIG_INTER_DIR;
+               cmd->csdi.config2 = CSDI_CONFIG2_DFLT;
+               cmd->csdi.dcdi_config = CSDI_DCDI_CONFIG_DFLT;
+       }
+
+       /* Update hvsrc lut coef */
+       scale_h = SCALE_FACTOR * dst_w / src_w;
+       sti_hqvdp_update_hvsrc(HVSRC_HORI, scale_h, &cmd->hvsrc);
+
+       scale_v = SCALE_FACTOR * dst_h / src_h;
+       sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
+
+       if (first_prepare) {
+               /* Prevent VTG shutdown */
+               if (clk_prepare_enable(hqvdp->clk_pix_main)) {
+                       DRM_ERROR("Failed to prepare/enable pix main clk\n");
+                       return;
+               }
+
+               /* Register VTG Vsync callback to handle bottom fields */
+               if (sti_vtg_register_client(hqvdp->vtg,
+                                           &hqvdp->vtg_nb,
+                                           mixer->id)) {
+                       DRM_ERROR("Cannot register VTG notifier\n");
+                       return;
+               }
+       }
+
+       writel(hqvdp->hqvdp_cmd_paddr + cmd_offset,
+              hqvdp->regs + HQVDP_MBX_NEXT_CMD);
+
+       hqvdp->curr_field_count++;
+
+       /* Interlaced : get ready to display the bottom field at next Vsync */
+       if (fb->flags & DRM_MODE_FB_INTERLACED)
+               hqvdp->btm_field_pending = true;
+
+       dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n",
+               __func__, hqvdp->hqvdp_cmd_paddr + cmd_offset);
+
+       plane->status = STI_PLANE_UPDATED;
+}
+
+static void sti_hqvdp_atomic_disable(struct drm_plane *drm_plane,
+                                    struct drm_plane_state *oldstate)
+{
+       struct sti_plane *plane = to_sti_plane(drm_plane);
+       struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
+
+       if (!drm_plane->crtc) {
+               DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
+                                drm_plane->base.id);
+               return;
+       }
+
+       DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+                        drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
+                        drm_plane->base.id, sti_plane_to_str(plane));
+
+       plane->status = STI_PLANE_DISABLING;
+}
+
+static const struct drm_plane_helper_funcs sti_hqvdp_helpers_funcs = {
+       .atomic_update = sti_hqvdp_atomic_update,
+       .atomic_disable = sti_hqvdp_atomic_disable,
 };
 
-struct sti_layer *sti_hqvdp_create(struct device *dev)
+static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
+                                         struct device *dev, int desc)
 {
        struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
+       int res;
+
+       hqvdp->plane.desc = desc;
+       hqvdp->plane.status = STI_PLANE_DISABLED;
 
-       hqvdp->layer.ops = &hqvdp_ops;
+       sti_hqvdp_init(hqvdp);
 
-       return &hqvdp->layer;
+       res = drm_universal_plane_init(drm_dev, &hqvdp->plane.drm_plane, 1,
+                                      &sti_plane_helpers_funcs,
+                                      hqvdp_supported_formats,
+                                      ARRAY_SIZE(hqvdp_supported_formats),
+                                      DRM_PLANE_TYPE_OVERLAY);
+       if (res) {
+               DRM_ERROR("Failed to initialize universal plane\n");
+               return NULL;
+       }
+
+       drm_plane_helper_add(&hqvdp->plane.drm_plane, &sti_hqvdp_helpers_funcs);
+
+       sti_plane_init_property(&hqvdp->plane, DRM_PLANE_TYPE_OVERLAY);
+
+       return &hqvdp->plane.drm_plane;
 }
-EXPORT_SYMBOL(sti_hqvdp_create);
 
 static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
 {
@@ -859,6 +877,12 @@ static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt)
        } *header;
 
        DRM_DEBUG_DRIVER("\n");
+
+       if (hqvdp->xp70_initialized) {
+               DRM_INFO("HQVDP XP70 already initialized\n");
+               return;
+       }
+
        /* Check firmware parts */
        if (!firmware) {
                DRM_ERROR("Firmware not available\n");
@@ -946,7 +970,10 @@ static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt)
        /* Launch Vsync */
        writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
 
-       DRM_INFO("HQVDP XP70 started\n");
+       DRM_INFO("HQVDP XP70 initialized\n");
+
+       hqvdp->xp70_initialized = true;
+
 out:
        release_firmware(firmware);
 }
@@ -955,7 +982,7 @@ int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
 {
        struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
-       struct sti_layer *layer;
+       struct drm_plane *plane;
        int err;
 
        DRM_DEBUG_DRIVER("\n");
@@ -971,13 +998,10 @@ int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
                return err;
        }
 
-       layer = sti_layer_create(hqvdp->dev, STI_HQVDP_0, hqvdp->regs);
-       if (!layer) {
+       /* Create HQVDP plane once xp70 is initialized */
+       plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0);
+       if (!plane)
                DRM_ERROR("Can't create HQVDP plane\n");
-               return -ENOMEM;
-       }
-
-       sti_drm_plane_init(drm_dev, layer, 1, DRM_PLANE_TYPE_OVERLAY);
 
        return 0;
 }
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.h b/drivers/gpu/drm/sti/sti_hqvdp.h
deleted file mode 100644 (file)
index cd5ecd0..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#ifndef _STI_HQVDP_H_
-#define _STI_HQVDP_H_
-
-struct sti_layer *sti_hqvdp_create(struct device *dev);
-
-#endif
diff --git a/drivers/gpu/drm/sti/sti_layer.c b/drivers/gpu/drm/sti/sti_layer.c
deleted file mode 100644 (file)
index 899104f..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
- *          Fabien Dessenne <fabien.dessenne@st.com>
- *          for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "sti_compositor.h"
-#include "sti_cursor.h"
-#include "sti_gdp.h"
-#include "sti_hqvdp.h"
-#include "sti_layer.h"
-#include "sti_vid.h"
-
-const char *sti_layer_to_str(struct sti_layer *layer)
-{
-       switch (layer->desc) {
-       case STI_GDP_0:
-               return "GDP0";
-       case STI_GDP_1:
-               return "GDP1";
-       case STI_GDP_2:
-               return "GDP2";
-       case STI_GDP_3:
-               return "GDP3";
-       case STI_VID_0:
-               return "VID0";
-       case STI_VID_1:
-               return "VID1";
-       case STI_CURSOR:
-               return "CURSOR";
-       case STI_HQVDP_0:
-               return "HQVDP0";
-       default:
-               return "<UNKNOWN LAYER>";
-       }
-}
-EXPORT_SYMBOL(sti_layer_to_str);
-
-struct sti_layer *sti_layer_create(struct device *dev, int desc,
-                                  void __iomem *baseaddr)
-{
-
-       struct sti_layer *layer = NULL;
-
-       switch (desc & STI_LAYER_TYPE_MASK) {
-       case STI_GDP:
-               layer = sti_gdp_create(dev, desc);
-               break;
-       case STI_VID:
-               layer = sti_vid_create(dev);
-               break;
-       case STI_CUR:
-               layer = sti_cursor_create(dev);
-               break;
-       case STI_VDP:
-               layer = sti_hqvdp_create(dev);
-               break;
-       }
-
-       if (!layer) {
-               DRM_ERROR("Failed to create layer\n");
-               return NULL;
-       }
-
-       layer->desc = desc;
-       layer->dev = dev;
-       layer->regs = baseaddr;
-
-       layer->ops->init(layer);
-
-       DRM_DEBUG_DRIVER("%s created\n", sti_layer_to_str(layer));
-
-       return layer;
-}
-EXPORT_SYMBOL(sti_layer_create);
-
-int sti_layer_prepare(struct sti_layer *layer,
-                     struct drm_crtc *crtc,
-                     struct drm_framebuffer *fb,
-                     struct drm_display_mode *mode, int mixer_id,
-                     int dest_x, int dest_y, int dest_w, int dest_h,
-                     int src_x, int src_y, int src_w, int src_h)
-{
-       int ret;
-       unsigned int i;
-       struct drm_gem_cma_object *cma_obj;
-
-       if (!layer || !fb || !mode) {
-               DRM_ERROR("Null fb, layer or mode\n");
-               return 1;
-       }
-
-       cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-       if (!cma_obj) {
-               DRM_ERROR("Can't get CMA GEM object for fb\n");
-               return 1;
-       }
-
-       layer->crtc = crtc;
-       layer->fb = fb;
-       layer->mode = mode;
-       layer->mixer_id = mixer_id;
-       layer->dst_x = dest_x;
-       layer->dst_y = dest_y;
-       layer->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x);
-       layer->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y);
-       layer->src_x = src_x;
-       layer->src_y = src_y;
-       layer->src_w = src_w;
-       layer->src_h = src_h;
-       layer->format = fb->pixel_format;
-       layer->vaddr = cma_obj->vaddr;
-       layer->paddr = cma_obj->paddr;
-       for (i = 0; i < 4; i++) {
-               layer->pitches[i] = fb->pitches[i];
-               layer->offsets[i] = fb->offsets[i];
-       }
-
-       DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n",
-                        sti_layer_to_str(layer),
-                        layer->mixer_id);
-       DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
-                        sti_layer_to_str(layer),
-                        layer->dst_w, layer->dst_h, layer->dst_x, layer->dst_y,
-                        layer->src_w, layer->src_h, layer->src_x,
-                        layer->src_y);
-
-       DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
-                        (char *)&layer->format, (unsigned long)layer->paddr);
-
-       if (!layer->ops->prepare)
-               goto err_no_prepare;
-
-       ret = layer->ops->prepare(layer, !layer->enabled);
-       if (!ret)
-               layer->enabled = true;
-
-       return ret;
-
-err_no_prepare:
-       DRM_ERROR("Cannot prepare\n");
-       return 1;
-}
-
-int sti_layer_commit(struct sti_layer *layer)
-{
-       if (!layer)
-               return 1;
-
-       if (!layer->ops->commit)
-               goto err_no_commit;
-
-       return layer->ops->commit(layer);
-
-err_no_commit:
-       DRM_ERROR("Cannot commit\n");
-       return 1;
-}
-
-int sti_layer_disable(struct sti_layer *layer)
-{
-       int ret;
-
-       DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
-       if (!layer)
-               return 1;
-
-       if (!layer->enabled)
-               return 0;
-
-       if (!layer->ops->disable)
-               goto err_no_disable;
-
-       ret = layer->ops->disable(layer);
-       if (!ret)
-               layer->enabled = false;
-       else
-               DRM_ERROR("Disable failed\n");
-
-       return ret;
-
-err_no_disable:
-       DRM_ERROR("Cannot disable\n");
-       return 1;
-}
-
-const uint32_t *sti_layer_get_formats(struct sti_layer *layer)
-{
-       if (!layer)
-               return NULL;
-
-       if (!layer->ops->get_formats)
-               return NULL;
-
-       return layer->ops->get_formats(layer);
-}
-
-unsigned int sti_layer_get_nb_formats(struct sti_layer *layer)
-{
-       if (!layer)
-               return 0;
-
-       if (!layer->ops->get_nb_formats)
-               return 0;
-
-       return layer->ops->get_nb_formats(layer);
-}
diff --git a/drivers/gpu/drm/sti/sti_layer.h b/drivers/gpu/drm/sti/sti_layer.h
deleted file mode 100644 (file)
index ceff497..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics SA 2014
- * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
- *          Fabien Dessenne <fabien.dessenne@st.com>
- *          for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
- */
-
-#ifndef _STI_LAYER_H_
-#define _STI_LAYER_H_
-
-#include <drm/drmP.h>
-
-#define to_sti_layer(x) container_of(x, struct sti_layer, plane)
-
-#define STI_LAYER_TYPE_SHIFT 8
-#define STI_LAYER_TYPE_MASK (~((1<<STI_LAYER_TYPE_SHIFT)-1))
-
-struct sti_layer;
-
-enum sti_layer_type {
-       STI_GDP = 1 << STI_LAYER_TYPE_SHIFT,
-       STI_VID = 2 << STI_LAYER_TYPE_SHIFT,
-       STI_CUR = 3 << STI_LAYER_TYPE_SHIFT,
-       STI_BCK = 4 << STI_LAYER_TYPE_SHIFT,
-       STI_VDP = 5 << STI_LAYER_TYPE_SHIFT
-};
-
-enum sti_layer_id_of_type {
-       STI_ID_0 = 0,
-       STI_ID_1 = 1,
-       STI_ID_2 = 2,
-       STI_ID_3 = 3
-};
-
-enum sti_layer_desc {
-       STI_GDP_0       = STI_GDP | STI_ID_0,
-       STI_GDP_1       = STI_GDP | STI_ID_1,
-       STI_GDP_2       = STI_GDP | STI_ID_2,
-       STI_GDP_3       = STI_GDP | STI_ID_3,
-       STI_VID_0       = STI_VID | STI_ID_0,
-       STI_VID_1       = STI_VID | STI_ID_1,
-       STI_HQVDP_0     = STI_VDP | STI_ID_0,
-       STI_CURSOR      = STI_CUR,
-       STI_BACK        = STI_BCK
-};
-
-/**
- * STI layer functions structure
- *
- * @get_formats:       get layer supported formats
- * @get_nb_formats:    get number of format supported
- * @init:               initialize the layer
- * @prepare:           prepare layer before rendering
- * @commit:            set layer for rendering
- * @disable:           disable layer
- */
-struct sti_layer_funcs {
-       const uint32_t* (*get_formats)(struct sti_layer *layer);
-       unsigned int (*get_nb_formats)(struct sti_layer *layer);
-       void (*init)(struct sti_layer *layer);
-       int (*prepare)(struct sti_layer *layer, bool first_prepare);
-       int (*commit)(struct sti_layer *layer);
-       int (*disable)(struct sti_layer *layer);
-};
-
-/**
- * STI layer structure
- *
- * @plane:              drm plane it is bound to (if any)
- * @fb:                 drm fb it is bound to
- * @crtc:               crtc it is bound to
- * @mode:               display mode
- * @desc:               layer type & id
- * @device:            driver device
- * @regs:              layer registers
- * @ops:                layer functions
- * @zorder:             layer z-order
- * @mixer_id:           id of the mixer used to display the layer
- * @enabled:            to know if the layer is active or not
- * @src_x src_y:        coordinates of the input (fb) area
- * @src_w src_h:        size of the input (fb) area
- * @dst_x dst_y:        coordinates of the output (crtc) area
- * @dst_w dst_h:        size of the output (crtc) area
- * @format:             format
- * @pitches:            pitch of 'planes' (eg: Y, U, V)
- * @offsets:            offset of 'planes'
- * @vaddr:              virtual address of the input buffer
- * @paddr:              physical address of the input buffer
- */
-struct sti_layer {
-       struct drm_plane plane;
-       struct drm_framebuffer *fb;
-       struct drm_crtc *crtc;
-       struct drm_display_mode *mode;
-       enum sti_layer_desc desc;
-       struct device *dev;
-       void __iomem *regs;
-       const struct sti_layer_funcs *ops;
-       int zorder;
-       int mixer_id;
-       bool enabled;
-       int src_x, src_y;
-       int src_w, src_h;
-       int dst_x, dst_y;
-       int dst_w, dst_h;
-       uint32_t format;
-       unsigned int pitches[4];
-       unsigned int offsets[4];
-       void *vaddr;
-       dma_addr_t paddr;
-};
-
-struct sti_layer *sti_layer_create(struct device *dev, int desc,
-                       void __iomem *baseaddr);
-int sti_layer_prepare(struct sti_layer *layer,
-                       struct drm_crtc *crtc,
-                       struct drm_framebuffer *fb,
-                       struct drm_display_mode *mode,
-                       int mixer_id,
-                       int dest_x, int dest_y,
-                       int dest_w, int dest_h,
-                       int src_x, int src_y,
-                       int src_w, int src_h);
-int sti_layer_commit(struct sti_layer *layer);
-int sti_layer_disable(struct sti_layer *layer);
-const uint32_t *sti_layer_get_formats(struct sti_layer *layer);
-unsigned int sti_layer_get_nb_formats(struct sti_layer *layer);
-const char *sti_layer_to_str(struct sti_layer *layer);
-
-#endif
index 13a4b84deab69104f82f3c341877e2e2aa6e3fbb..0182e936500427e8fd798251c6dccdd340b87495 100644 (file)
@@ -58,6 +58,7 @@ const char *sti_mixer_to_str(struct sti_mixer *mixer)
                return "<UNKNOWN MIXER>";
        }
 }
+EXPORT_SYMBOL(sti_mixer_to_str);
 
 static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id)
 {
@@ -101,52 +102,57 @@ static void sti_mixer_set_background_area(struct sti_mixer *mixer,
        sti_mixer_reg_write(mixer, GAM_MIXER_BCS, yds << 16 | xds);
 }
 
-int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer)
+int sti_mixer_set_plane_depth(struct sti_mixer *mixer, struct sti_plane *plane)
 {
-       int layer_id = 0, depth = layer->zorder;
+       int plane_id, depth = plane->zorder;
+       unsigned int i;
        u32 mask, val;
 
-       if (depth >= GAM_MIXER_NB_DEPTH_LEVEL)
+       if ((depth < 1) || (depth > GAM_MIXER_NB_DEPTH_LEVEL))
                return 1;
 
-       switch (layer->desc) {
+       switch (plane->desc) {
        case STI_GDP_0:
-               layer_id = GAM_DEPTH_GDP0_ID;
+               plane_id = GAM_DEPTH_GDP0_ID;
                break;
        case STI_GDP_1:
-               layer_id = GAM_DEPTH_GDP1_ID;
+               plane_id = GAM_DEPTH_GDP1_ID;
                break;
        case STI_GDP_2:
-               layer_id = GAM_DEPTH_GDP2_ID;
+               plane_id = GAM_DEPTH_GDP2_ID;
                break;
        case STI_GDP_3:
-               layer_id = GAM_DEPTH_GDP3_ID;
+               plane_id = GAM_DEPTH_GDP3_ID;
                break;
-       case STI_VID_0:
        case STI_HQVDP_0:
-               layer_id = GAM_DEPTH_VID0_ID;
-               break;
-       case STI_VID_1:
-               layer_id = GAM_DEPTH_VID1_ID;
+               plane_id = GAM_DEPTH_VID0_ID;
                break;
        case STI_CURSOR:
                /* no need to set depth for cursor */
                return 0;
        default:
-               DRM_ERROR("Unknown layer %d\n", layer->desc);
+               DRM_ERROR("Unknown plane %d\n", plane->desc);
                return 1;
        }
-       mask = GAM_DEPTH_MASK_ID << (3 * depth);
-       layer_id = layer_id << (3 * depth);
+
+       /* Search if a previous depth was already assigned to the plane */
+       val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
+       for (i = 0; i < GAM_MIXER_NB_DEPTH_LEVEL; i++) {
+               mask = GAM_DEPTH_MASK_ID << (3 * i);
+               if ((val & mask) == plane_id << (3 * i))
+                       break;
+       }
+
+       mask |= GAM_DEPTH_MASK_ID << (3 * (depth - 1));
+       plane_id = plane_id << (3 * (depth - 1));
 
        DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),
-                        sti_layer_to_str(layer), depth);
+                        sti_plane_to_str(plane), depth);
        dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n",
-               layer_id, mask);
+               plane_id, mask);
 
-       val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
        val &= ~mask;
-       val |= layer_id;
+       val |= plane_id;
        sti_mixer_reg_write(mixer, GAM_MIXER_CRB, val);
 
        dev_dbg(mixer->dev, "Read GAM_MIXER_CRB 0x%x\n",
@@ -176,9 +182,9 @@ int sti_mixer_active_video_area(struct sti_mixer *mixer,
        return 0;
 }
 
-static u32 sti_mixer_get_layer_mask(struct sti_layer *layer)
+static u32 sti_mixer_get_plane_mask(struct sti_plane *plane)
 {
-       switch (layer->desc) {
+       switch (plane->desc) {
        case STI_BACK:
                return GAM_CTL_BACK_MASK;
        case STI_GDP_0:
@@ -189,11 +195,8 @@ static u32 sti_mixer_get_layer_mask(struct sti_layer *layer)
                return GAM_CTL_GDP2_MASK;
        case STI_GDP_3:
                return GAM_CTL_GDP3_MASK;
-       case STI_VID_0:
        case STI_HQVDP_0:
                return GAM_CTL_VID0_MASK;
-       case STI_VID_1:
-               return GAM_CTL_VID1_MASK;
        case STI_CURSOR:
                return GAM_CTL_CURSOR_MASK;
        default:
@@ -201,17 +204,17 @@ static u32 sti_mixer_get_layer_mask(struct sti_layer *layer)
        }
 }
 
-int sti_mixer_set_layer_status(struct sti_mixer *mixer,
-                              struct sti_layer *layer, bool status)
+int sti_mixer_set_plane_status(struct sti_mixer *mixer,
+                              struct sti_plane *plane, bool status)
 {
        u32 mask, val;
 
        DRM_DEBUG_DRIVER("%s %s %s\n", status ? "enable" : "disable",
-                        sti_mixer_to_str(mixer), sti_layer_to_str(layer));
+                        sti_mixer_to_str(mixer), sti_plane_to_str(plane));
 
-       mask = sti_mixer_get_layer_mask(layer);
+       mask = sti_mixer_get_plane_mask(plane);
        if (!mask) {
-               DRM_ERROR("Can not find layer mask\n");
+               DRM_ERROR("Can't find layer mask\n");
                return -EINVAL;
        }
 
@@ -223,15 +226,6 @@ int sti_mixer_set_layer_status(struct sti_mixer *mixer,
        return 0;
 }
 
-void sti_mixer_clear_all_layers(struct sti_mixer *mixer)
-{
-       u32 val;
-
-       DRM_DEBUG_DRIVER("%s clear all layer\n", sti_mixer_to_str(mixer));
-       val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL) & 0xFFFF0000;
-       sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);
-}
-
 void sti_mixer_set_matrix(struct sti_mixer *mixer)
 {
        unsigned int i;
index b97282182908f0cf77589e3e39b94c5b977a9bed..efb1a9a5ba86b8c71bec36f7509a8373ee0cb3e0 100644 (file)
 
 #include <drm/drmP.h>
 
-#include "sti_layer.h"
+#include "sti_plane.h"
 
 #define to_sti_mixer(x) container_of(x, struct sti_mixer, drm_crtc)
 
+enum sti_mixer_status {
+       STI_MIXER_READY,
+       STI_MIXER_DISABLING,
+       STI_MIXER_DISABLED,
+};
+
 /**
  * STI Mixer subdevice structure
  *
  * @id: id of the mixer
  * @drm_crtc: crtc object link to the mixer
  * @pending_event: set if a flip event is pending on crtc
- * @enabled: to know if the mixer is active or not
+ * @status: to know the status of the mixer
  */
 struct sti_mixer {
        struct device *dev;
        void __iomem *regs;
        int id;
-       struct drm_crtc drm_crtc;
+       struct drm_crtc drm_crtc;
        struct drm_pending_vblank_event *pending_event;
-       bool enabled;
+       enum sti_mixer_status status;
 };
 
 const char *sti_mixer_to_str(struct sti_mixer *mixer);
 
 struct sti_mixer *sti_mixer_create(struct device *dev, int id,
-               void __iomem *baseaddr);
+                                  void __iomem *baseaddr);
 
-int sti_mixer_set_layer_status(struct sti_mixer *mixer,
-               struct sti_layer *layer, bool status);
-void sti_mixer_clear_all_layers(struct sti_mixer *mixer);
-int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer);
+int sti_mixer_set_plane_status(struct sti_mixer *mixer,
+                              struct sti_plane *plane, bool status);
+int sti_mixer_set_plane_depth(struct sti_mixer *mixer, struct sti_plane *plane);
 int sti_mixer_active_video_area(struct sti_mixer *mixer,
-               struct drm_display_mode *mode);
+                               struct drm_display_mode *mode);
 
 void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable);
 
 /* depth in Cross-bar control = z order */
-#define GAM_MIXER_NB_DEPTH_LEVEL 7
+#define GAM_MIXER_NB_DEPTH_LEVEL 6
 
 #define STI_MIXER_MAIN 0
 #define STI_MIXER_AUX  1
diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c
new file mode 100644 (file)
index 0000000..d5c5e91
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ *          Fabien Dessenne <fabien.dessenne@st.com>
+ *          for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "sti_compositor.h"
+#include "sti_drv.h"
+#include "sti_plane.h"
+
+/* (Background) < GDP0 < GDP1 < HQVDP0 < GDP2 < GDP3 < (ForeGround) */
+enum sti_plane_desc sti_plane_default_zorder[] = {
+       STI_GDP_0,
+       STI_GDP_1,
+       STI_HQVDP_0,
+       STI_GDP_2,
+       STI_GDP_3,
+};
+
+const char *sti_plane_to_str(struct sti_plane *plane)
+{
+       switch (plane->desc) {
+       case STI_GDP_0:
+               return "GDP0";
+       case STI_GDP_1:
+               return "GDP1";
+       case STI_GDP_2:
+               return "GDP2";
+       case STI_GDP_3:
+               return "GDP3";
+       case STI_HQVDP_0:
+               return "HQVDP0";
+       case STI_CURSOR:
+               return "CURSOR";
+       default:
+               return "<UNKNOWN PLANE>";
+       }
+}
+EXPORT_SYMBOL(sti_plane_to_str);
+
+static void sti_plane_destroy(struct drm_plane *drm_plane)
+{
+       DRM_DEBUG_DRIVER("\n");
+
+       drm_plane_helper_disable(drm_plane);
+       drm_plane_cleanup(drm_plane);
+}
+
+static int sti_plane_set_property(struct drm_plane *drm_plane,
+                                 struct drm_property *property,
+                                 uint64_t val)
+{
+       struct drm_device *dev = drm_plane->dev;
+       struct sti_private *private = dev->dev_private;
+       struct sti_plane *plane = to_sti_plane(drm_plane);
+
+       DRM_DEBUG_DRIVER("\n");
+
+       if (property == private->plane_zorder_property) {
+               plane->zorder = val;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane)
+{
+       struct drm_device *dev = drm_plane->dev;
+       struct sti_private *private = dev->dev_private;
+       struct sti_plane *plane = to_sti_plane(drm_plane);
+       struct drm_property *prop;
+
+       prop = private->plane_zorder_property;
+       if (!prop) {
+               prop = drm_property_create_range(dev, 0, "zpos", 1,
+                                                GAM_MIXER_NB_DEPTH_LEVEL);
+               if (!prop)
+                       return;
+
+               private->plane_zorder_property = prop;
+       }
+
+       drm_object_attach_property(&drm_plane->base, prop, plane->zorder);
+}
+
+void sti_plane_init_property(struct sti_plane *plane,
+                            enum drm_plane_type type)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(sti_plane_default_zorder); i++)
+               if (sti_plane_default_zorder[i] == plane->desc)
+                       break;
+
+       plane->zorder = i + 1;
+
+       if (type == DRM_PLANE_TYPE_OVERLAY)
+               sti_plane_attach_zorder_property(&plane->drm_plane);
+
+       DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%d\n",
+                        plane->drm_plane.base.id,
+                        sti_plane_to_str(plane), plane->zorder);
+}
+EXPORT_SYMBOL(sti_plane_init_property);
+
+struct drm_plane_funcs sti_plane_helpers_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = sti_plane_destroy,
+       .set_property = sti_plane_set_property,
+       .reset = drm_atomic_helper_plane_reset,
+       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+EXPORT_SYMBOL(sti_plane_helpers_funcs);
diff --git a/drivers/gpu/drm/sti/sti_plane.h b/drivers/gpu/drm/sti/sti_plane.h
new file mode 100644 (file)
index 0000000..86f1e6f
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_PLANE_H_
+#define _STI_PLANE_H_
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+
+extern struct drm_plane_funcs sti_plane_helpers_funcs;
+
+#define to_sti_plane(x) container_of(x, struct sti_plane, drm_plane)
+
+#define STI_PLANE_TYPE_SHIFT 8
+#define STI_PLANE_TYPE_MASK (~((1 << STI_PLANE_TYPE_SHIFT) - 1))
+
+enum sti_plane_type {
+       STI_GDP = 1 << STI_PLANE_TYPE_SHIFT,
+       STI_VDP = 2 << STI_PLANE_TYPE_SHIFT,
+       STI_CUR = 3 << STI_PLANE_TYPE_SHIFT,
+       STI_BCK = 4 << STI_PLANE_TYPE_SHIFT
+};
+
+enum sti_plane_id_of_type {
+       STI_ID_0 = 0,
+       STI_ID_1 = 1,
+       STI_ID_2 = 2,
+       STI_ID_3 = 3
+};
+
+enum sti_plane_desc {
+       STI_GDP_0       = STI_GDP | STI_ID_0,
+       STI_GDP_1       = STI_GDP | STI_ID_1,
+       STI_GDP_2       = STI_GDP | STI_ID_2,
+       STI_GDP_3       = STI_GDP | STI_ID_3,
+       STI_HQVDP_0     = STI_VDP | STI_ID_0,
+       STI_CURSOR      = STI_CUR,
+       STI_BACK        = STI_BCK
+};
+
+enum sti_plane_status {
+       STI_PLANE_READY,
+       STI_PLANE_UPDATED,
+       STI_PLANE_DISABLING,
+       STI_PLANE_FLUSHING,
+       STI_PLANE_DISABLED,
+};
+
+/**
+ * STI plane structure
+ *
+ * @plane:              drm plane it is bound to (if any)
+ * @desc:               plane type & id
+ * @status:             to know the status of the plane
+ * @zorder:             plane z-order
+ */
+struct sti_plane {
+       struct drm_plane drm_plane;
+       enum sti_plane_desc desc;
+       enum sti_plane_status status;
+       int zorder;
+};
+
+const char *sti_plane_to_str(struct sti_plane *plane);
+void sti_plane_init_property(struct sti_plane *plane,
+                            enum drm_plane_type type);
+#endif
index 5cc53116508ebac4ecd469b76785a4b1bd033374..c1aac8e66fb5024a626aa5a37bf99264beb0d870 100644 (file)
@@ -16,7 +16,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
-#include "sti_drm_crtc.h"
+#include "sti_crtc.h"
 
 /* glue registers */
 #define TVO_CSC_MAIN_M0                  0x000
@@ -473,7 +473,7 @@ static void sti_dvo_encoder_commit(struct drm_encoder *encoder)
 {
        struct sti_tvout *tvout = to_sti_tvout(encoder);
 
-       tvout_dvo_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
+       tvout_dvo_start(tvout, sti_crtc_is_main(encoder->crtc));
 }
 
 static void sti_dvo_encoder_disable(struct drm_encoder *encoder)
@@ -523,7 +523,7 @@ static void sti_hda_encoder_commit(struct drm_encoder *encoder)
 {
        struct sti_tvout *tvout = to_sti_tvout(encoder);
 
-       tvout_hda_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
+       tvout_hda_start(tvout, sti_crtc_is_main(encoder->crtc));
 }
 
 static void sti_hda_encoder_disable(struct drm_encoder *encoder)
@@ -575,7 +575,7 @@ static void sti_hdmi_encoder_commit(struct drm_encoder *encoder)
 {
        struct sti_tvout *tvout = to_sti_tvout(encoder);
 
-       tvout_hdmi_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
+       tvout_hdmi_start(tvout, sti_crtc_is_main(encoder->crtc));
 }
 
 static void sti_hdmi_encoder_disable(struct drm_encoder *encoder)
@@ -644,7 +644,6 @@ static int sti_tvout_bind(struct device *dev, struct device *master, void *data)
        struct sti_tvout *tvout = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
        unsigned int i;
-       int ret;
 
        tvout->drm_dev = drm_dev;
 
@@ -658,17 +657,15 @@ static int sti_tvout_bind(struct device *dev, struct device *master, void *data)
 
        sti_tvout_create_encoders(drm_dev, tvout);
 
-       ret = component_bind_all(dev, drm_dev);
-       if (ret)
-               sti_tvout_destroy_encoders(tvout);
-
-       return ret;
+       return 0;
 }
 
 static void sti_tvout_unbind(struct device *dev, struct device *master,
        void *data)
 {
-       /* do nothing */
+       struct sti_tvout *tvout = dev_get_drvdata(dev);
+
+       sti_tvout_destroy_encoders(tvout);
 }
 
 static const struct component_ops sti_tvout_ops = {
@@ -676,34 +673,12 @@ static const struct component_ops sti_tvout_ops = {
        .unbind = sti_tvout_unbind,
 };
 
-static int compare_of(struct device *dev, void *data)
-{
-       return dev->of_node == data;
-}
-
-static int sti_tvout_master_bind(struct device *dev)
-{
-       return 0;
-}
-
-static void sti_tvout_master_unbind(struct device *dev)
-{
-       /* do nothing */
-}
-
-static const struct component_master_ops sti_tvout_master_ops = {
-       .bind = sti_tvout_master_bind,
-       .unbind = sti_tvout_master_unbind,
-};
-
 static int sti_tvout_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct device_node *node = dev->of_node;
        struct sti_tvout *tvout;
        struct resource *res;
-       struct device_node *child_np;
-       struct component_match *match = NULL;
 
        DRM_INFO("%s\n", __func__);
 
@@ -734,24 +709,11 @@ static int sti_tvout_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, tvout);
 
-       of_platform_populate(node, NULL, NULL, dev);
-
-       child_np = of_get_next_available_child(node, NULL);
-
-       while (child_np) {
-               component_match_add(dev, &match, compare_of, child_np);
-               of_node_put(child_np);
-               child_np = of_get_next_available_child(node, child_np);
-       }
-
-       component_master_add_with_match(dev, &sti_tvout_master_ops, match);
-
        return component_add(dev, &sti_tvout_ops);
 }
 
 static int sti_tvout_remove(struct platform_device *pdev)
 {
-       component_master_del(&pdev->dev, &sti_tvout_master_ops);
        component_del(&pdev->dev, &sti_tvout_ops);
        return 0;
 }
index 10ced6a479f42fb8cb1235a7409ad336097894ab..a8254cc362a1eddf2e9d9516e15e2fbc7514b705 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <drm/drmP.h>
 
-#include "sti_layer.h"
+#include "sti_plane.h"
 #include "sti_vid.h"
 #include "sti_vtg.h"
 
 #define VID_MPR2_BT709          0x07150545
 #define VID_MPR3_BT709          0x00000AE8
 
-static int sti_vid_prepare_layer(struct sti_layer *vid, bool first_prepare)
+void sti_vid_commit(struct sti_vid *vid,
+                   struct drm_plane_state *state)
 {
-       u32 val;
+       struct drm_crtc *crtc = state->crtc;
+       struct drm_display_mode *mode = &crtc->mode;
+       int dst_x = state->crtc_x;
+       int dst_y = state->crtc_y;
+       int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
+       int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
+       u32 val, ydo, xdo, yds, xds;
+
+       /* Input / output size
+        * Align to upper even value */
+       dst_w = ALIGN(dst_w, 2);
+       dst_h = ALIGN(dst_h, 2);
 
        /* Unmask */
        val = readl(vid->regs + VID_CTL);
        val &= ~VID_CTL_IGNORE;
        writel(val, vid->regs + VID_CTL);
 
-       return 0;
-}
-
-static int sti_vid_commit_layer(struct sti_layer *vid)
-{
-       struct drm_display_mode *mode = vid->mode;
-       u32 ydo, xdo, yds, xds;
-
-       ydo = sti_vtg_get_line_number(*mode, vid->dst_y);
-       yds = sti_vtg_get_line_number(*mode, vid->dst_y + vid->dst_h - 1);
-       xdo = sti_vtg_get_pixel_number(*mode, vid->dst_x);
-       xds = sti_vtg_get_pixel_number(*mode, vid->dst_x + vid->dst_w - 1);
+       ydo = sti_vtg_get_line_number(*mode, dst_y);
+       yds = sti_vtg_get_line_number(*mode, dst_y + dst_h - 1);
+       xdo = sti_vtg_get_pixel_number(*mode, dst_x);
+       xds = sti_vtg_get_pixel_number(*mode, dst_x + dst_w - 1);
 
        writel((ydo << 16) | xdo, vid->regs + VID_VPO);
        writel((yds << 16) | xds, vid->regs + VID_VPS);
-
-       return 0;
 }
 
-static int sti_vid_disable_layer(struct sti_layer *vid)
+void sti_vid_disable(struct sti_vid *vid)
 {
        u32 val;
 
@@ -79,21 +81,9 @@ static int sti_vid_disable_layer(struct sti_layer *vid)
        val = readl(vid->regs + VID_CTL);
        val |= VID_CTL_IGNORE;
        writel(val, vid->regs + VID_CTL);
-
-       return 0;
 }
 
-static const uint32_t *sti_vid_get_formats(struct sti_layer *layer)
-{
-       return NULL;
-}
-
-static unsigned int sti_vid_get_nb_formats(struct sti_layer *layer)
-{
-       return 0;
-}
-
-static void sti_vid_init(struct sti_layer *vid)
+static void sti_vid_init(struct sti_vid *vid)
 {
        /* Enable PSI, Mask layer */
        writel(VID_CTL_PSI_ENABLE | VID_CTL_IGNORE, vid->regs + VID_CTL);
@@ -113,18 +103,10 @@ static void sti_vid_init(struct sti_layer *vid)
        writel(VID_CSAT_DFLT, vid->regs + VID_CSAT);
 }
 
-static const struct sti_layer_funcs vid_ops = {
-       .get_formats = sti_vid_get_formats,
-       .get_nb_formats = sti_vid_get_nb_formats,
-       .init = sti_vid_init,
-       .prepare = sti_vid_prepare_layer,
-       .commit = sti_vid_commit_layer,
-       .disable = sti_vid_disable_layer,
-};
-
-struct sti_layer *sti_vid_create(struct device *dev)
+struct sti_vid *sti_vid_create(struct device *dev, int id,
+                              void __iomem *baseaddr)
 {
-       struct sti_layer *vid;
+       struct sti_vid *vid;
 
        vid = devm_kzalloc(dev, sizeof(*vid), GFP_KERNEL);
        if (!vid) {
@@ -132,7 +114,11 @@ struct sti_layer *sti_vid_create(struct device *dev)
                return NULL;
        }
 
-       vid->ops = &vid_ops;
+       vid->dev = dev;
+       vid->regs = baseaddr;
+       vid->id = id;
+
+       sti_vid_init(vid);
 
        return vid;
 }
index 2c0aecd632945011993e51e4e812483a102e1fe3..5dea4791f1d62bc04206186507987f3aa35835aa 100644 (file)
@@ -7,6 +7,23 @@
 #ifndef _STI_VID_H_
 #define _STI_VID_H_
 
-struct sti_layer *sti_vid_create(struct device *dev);
+/**
+ * STI VID structure
+ *
+ * @dev:   driver device
+ * @regs:  vid registers
+ * @id:    id of the vid
+ */
+struct sti_vid {
+       struct device *dev;
+       void __iomem *regs;
+       int id;
+};
+
+void sti_vid_commit(struct sti_vid *vid,
+                   struct drm_plane_state *state);
+void sti_vid_disable(struct sti_vid *vid);
+struct sti_vid *sti_vid_create(struct device *dev, int id,
+                              void __iomem *baseaddr);
 
 #endif
index a287e4fec8653d91e55bb2765e2379984b65bef5..bf8ef3133e5bb929e2fa9d644a89bf7311d2472f 100644 (file)
@@ -1277,7 +1277,8 @@ static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
        return 0;
 }
 
-static void tegra_crtc_atomic_begin(struct drm_crtc *crtc)
+static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
+                                   struct drm_crtc_state *old_crtc_state)
 {
        struct tegra_dc *dc = to_tegra_dc(crtc);
 
@@ -1291,7 +1292,8 @@ static void tegra_crtc_atomic_begin(struct drm_crtc *crtc)
        }
 }
 
-static void tegra_crtc_atomic_flush(struct drm_crtc *crtc)
+static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
+                                   struct drm_crtc_state *old_crtc_state)
 {
        struct tegra_dc_state *state = to_dc_state(crtc->state);
        struct tegra_dc *dc = to_tegra_dc(crtc);
index ed970f62290306e5c78158f9600211d51251dc78..dc97c0b3681d95d60c6b983c29afd036c7aa14f5 100644 (file)
@@ -726,8 +726,9 @@ static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
                tegra_dsi_soft_reset(dsi->slave);
 }
 
-static void tegra_dsi_connector_dpms(struct drm_connector *connector, int mode)
+static int tegra_dsi_connector_dpms(struct drm_connector *connector, int mode)
 {
+       return 0;
 }
 
 static void tegra_dsi_connector_reset(struct drm_connector *connector)
index 397fb34d5d5bdd842012f0842450b05e9d7139d1..07c844b746b446f89bc5de7933bdc607baee7940 100644 (file)
@@ -184,9 +184,9 @@ unreference:
 #ifdef CONFIG_DRM_TEGRA_FBDEV
 static struct fb_ops tegra_fb_ops = {
        .owner = THIS_MODULE,
-       .fb_fillrect = sys_fillrect,
-       .fb_copyarea = sys_copyarea,
-       .fb_imageblit = sys_imageblit,
+       .fb_fillrect = drm_fb_helper_sys_fillrect,
+       .fb_copyarea = drm_fb_helper_sys_copyarea,
+       .fb_imageblit = drm_fb_helper_sys_imageblit,
        .fb_check_var = drm_fb_helper_check_var,
        .fb_set_par = drm_fb_helper_set_par,
        .fb_blank = drm_fb_helper_blank,
@@ -224,11 +224,11 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
        if (IS_ERR(bo))
                return PTR_ERR(bo);
 
-       info = framebuffer_alloc(0, drm->dev);
-       if (!info) {
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info)) {
                dev_err(drm->dev, "failed to allocate framebuffer info\n");
                drm_gem_object_unreference_unlocked(&bo->gem);
-               return -ENOMEM;
+               return PTR_ERR(info);
        }
 
        fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1);
@@ -248,12 +248,6 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
        info->flags = FBINFO_FLAG_DEFAULT;
        info->fbops = &tegra_fb_ops;
 
-       err = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (err < 0) {
-               dev_err(drm->dev, "failed to allocate color map: %d\n", err);
-               goto destroy;
-       }
-
        drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(info, helper, fb->width, fb->height);
 
@@ -282,7 +276,7 @@ destroy:
        drm_framebuffer_unregister_private(fb);
        tegra_fb_destroy(fb);
 release:
-       framebuffer_release(info);
+       drm_fb_helper_release_fbi(helper);
        return err;
 }
 
@@ -347,20 +341,9 @@ fini:
 
 static void tegra_fbdev_exit(struct tegra_fbdev *fbdev)
 {
-       struct fb_info *info = fbdev->base.fbdev;
-
-       if (info) {
-               int err;
 
-               err = unregister_framebuffer(info);
-               if (err < 0)
-                       DRM_DEBUG_KMS("failed to unregister framebuffer\n");
-
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&fbdev->base);
+       drm_fb_helper_release_fbi(&fbdev->base);
 
        if (fbdev->fb) {
                drm_framebuffer_unregister_private(&fbdev->fb->base);
index 06ab1783bba11e7b1299e3d950accf1547e20285..fe4008a7ddba56695439bafd5c3e185e34d766ad 100644 (file)
@@ -772,9 +772,10 @@ static bool tegra_output_is_hdmi(struct tegra_output *output)
        return drm_detect_hdmi_monitor(edid);
 }
 
-static void tegra_hdmi_connector_dpms(struct drm_connector *connector,
-                                     int mode)
+static int tegra_hdmi_connector_dpms(struct drm_connector *connector,
+                                    int mode)
 {
+       return 0;
 }
 
 static const struct drm_connector_funcs tegra_hdmi_connector_funcs = {
index 7cd833f5b5b591257da40c04efc209057ec62549..9a99d213e1b1e8aeb2481771aac46c4a3fa2b3b6 100644 (file)
@@ -88,9 +88,10 @@ static void tegra_dc_write_regs(struct tegra_dc *dc,
                tegra_dc_writel(dc, table[i].value, table[i].offset);
 }
 
-static void tegra_rgb_connector_dpms(struct drm_connector *connector,
-                                    int mode)
+static int tegra_rgb_connector_dpms(struct drm_connector *connector,
+                                   int mode)
 {
+       return 0;
 }
 
 static const struct drm_connector_funcs tegra_rgb_connector_funcs = {
index 7591d8901f9a24ddd61d035500116c617e4df3f6..ee8ad0d4a0f28700ab54d663716cc37889ef7034 100644 (file)
@@ -866,8 +866,9 @@ static void tegra_sor_debugfs_exit(struct tegra_sor *sor)
        sor->debugfs_files = NULL;
 }
 
-static void tegra_sor_connector_dpms(struct drm_connector *connector, int mode)
+static int tegra_sor_connector_dpms(struct drm_connector *connector, int mode)
 {
+       return 0;
 }
 
 static enum drm_connector_status
index bf080abc86d12c9bdcb8947d1d1d637d0b2a4bb7..4e19d0f9cc3094ae9585eef447c2439589a4a304 100644 (file)
@@ -340,7 +340,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
                swap_storage = shmem_file_setup("ttm swap",
                                                ttm->num_pages << PAGE_SHIFT,
                                                0);
-               if (unlikely(IS_ERR(swap_storage))) {
+               if (IS_ERR(swap_storage)) {
                        pr_err("Failed allocating swap storage\n");
                        return PTR_ERR(swap_storage);
                }
@@ -354,7 +354,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
                if (unlikely(from_page == NULL))
                        continue;
                to_page = shmem_read_mapping_page(swap_space, i);
-               if (unlikely(IS_ERR(to_page))) {
+               if (IS_ERR(to_page)) {
                        ret = PTR_ERR(to_page);
                        goto out_err;
                }
index 5fc16cecd3ba595584f01f5f9a7e0b729f125341..62c7b1dafaa4ba6f4c573fd6d631b86b3b83ce45 100644 (file)
@@ -288,7 +288,7 @@ static void udl_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
 {
        struct udl_fbdev *ufbdev = info->par;
 
-       sys_fillrect(info, rect);
+       drm_fb_helper_sys_fillrect(info, rect);
 
        udl_handle_damage(&ufbdev->ufb, rect->dx, rect->dy, rect->width,
                          rect->height);
@@ -298,7 +298,7 @@ static void udl_fb_copyarea(struct fb_info *info, const struct fb_copyarea *regi
 {
        struct udl_fbdev *ufbdev = info->par;
 
-       sys_copyarea(info, region);
+       drm_fb_helper_sys_copyarea(info, region);
 
        udl_handle_damage(&ufbdev->ufb, region->dx, region->dy, region->width,
                          region->height);
@@ -308,7 +308,7 @@ static void udl_fb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
        struct udl_fbdev *ufbdev = info->par;
 
-       sys_imageblit(info, image);
+       drm_fb_helper_sys_imageblit(info, image);
 
        udl_handle_damage(&ufbdev->ufb, image->dx, image->dy, image->width,
                          image->height);
@@ -476,7 +476,6 @@ static int udlfb_create(struct drm_fb_helper *helper,
                container_of(helper, struct udl_fbdev, helper);
        struct drm_device *dev = ufbdev->helper.dev;
        struct fb_info *info;
-       struct device *device = dev->dev;
        struct drm_framebuffer *fb;
        struct drm_mode_fb_cmd2 mode_cmd;
        struct udl_gem_object *obj;
@@ -506,21 +505,20 @@ static int udlfb_create(struct drm_fb_helper *helper,
                goto out_gfree;
        }
 
-       info = framebuffer_alloc(0, device);
-       if (!info) {
-               ret = -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
                goto out_gfree;
        }
        info->par = ufbdev;
 
        ret = udl_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, obj);
        if (ret)
-               goto out_gfree;
+               goto out_destroy_fbi;
 
        fb = &ufbdev->ufb.base;
 
        ufbdev->helper.fb = fb;
-       ufbdev->helper.fbdev = info;
 
        strcpy(info->fix.id, "udldrmfb");
 
@@ -533,18 +531,13 @@ static int udlfb_create(struct drm_fb_helper *helper,
        drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(info, &ufbdev->helper, sizes->fb_width, sizes->fb_height);
 
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto out_gfree;
-       }
-
-
        DRM_DEBUG_KMS("allocated %dx%d vmal %p\n",
                      fb->width, fb->height,
                      ufbdev->ufb.obj->vmapping);
 
        return ret;
+out_destroy_fbi:
+       drm_fb_helper_release_fbi(helper);
 out_gfree:
        drm_gem_object_unreference(&ufbdev->ufb.obj->base);
 out:
@@ -558,14 +551,8 @@ static const struct drm_fb_helper_funcs udl_fb_helper_funcs = {
 static void udl_fbdev_destroy(struct drm_device *dev,
                              struct udl_fbdev *ufbdev)
 {
-       struct fb_info *info;
-       if (ufbdev->helper.fbdev) {
-               info = ufbdev->helper.fbdev;
-               unregister_framebuffer(info);
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
+       drm_fb_helper_unregister_fbi(&ufbdev->helper);
+       drm_fb_helper_release_fbi(&ufbdev->helper);
        drm_fb_helper_fini(&ufbdev->helper);
        drm_framebuffer_unregister_private(&ufbdev->ufb.base);
        drm_framebuffer_cleanup(&ufbdev->ufb.base);
@@ -631,11 +618,7 @@ void udl_fbdev_unplug(struct drm_device *dev)
                return;
 
        ufbdev = udl->fbdev;
-       if (ufbdev->helper.fbdev) {
-               struct fb_info *info;
-               info = ufbdev->helper.fbdev;
-               unlink_framebuffer(info);
-       }
+       drm_fb_helper_unlink_fbi(&ufbdev->helper);
 }
 
 struct drm_framebuffer *
index df198d9e770c2f61882c9a1bdae771f8c9378f54..6a81e084593bde8539197f417cb72e56498ced22 100644 (file)
@@ -173,7 +173,7 @@ static void virtio_gpu_3d_fillrect(struct fb_info *info,
                                   const struct fb_fillrect *rect)
 {
        struct virtio_gpu_fbdev *vfbdev = info->par;
-       sys_fillrect(info, rect);
+       drm_fb_helper_sys_fillrect(info, rect);
        virtio_gpu_dirty_update(&vfbdev->vgfb, true, rect->dx, rect->dy,
                             rect->width, rect->height);
        schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD);
@@ -183,7 +183,7 @@ static void virtio_gpu_3d_copyarea(struct fb_info *info,
                                   const struct fb_copyarea *area)
 {
        struct virtio_gpu_fbdev *vfbdev = info->par;
-       sys_copyarea(info, area);
+       drm_fb_helper_sys_copyarea(info, area);
        virtio_gpu_dirty_update(&vfbdev->vgfb, true, area->dx, area->dy,
                           area->width, area->height);
        schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD);
@@ -193,7 +193,7 @@ static void virtio_gpu_3d_imageblit(struct fb_info *info,
                                    const struct fb_image *image)
 {
        struct virtio_gpu_fbdev *vfbdev = info->par;
-       sys_imageblit(info, image);
+       drm_fb_helper_sys_imageblit(info, image);
        virtio_gpu_dirty_update(&vfbdev->vgfb, true, image->dx, image->dy,
                             image->width, image->height);
        schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD);
@@ -230,7 +230,6 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
        struct drm_framebuffer *fb;
        struct drm_mode_fb_cmd2 mode_cmd = {};
        struct virtio_gpu_object *obj;
-       struct device *device = vgdev->dev;
        uint32_t resid, format, size;
        int ret;
 
@@ -317,18 +316,12 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
        if (ret)
                goto err_obj_attach;
 
-       info = framebuffer_alloc(0, device);
-       if (!info) {
-               ret = -ENOMEM;
+       info = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
                goto err_fb_alloc;
        }
 
-       ret = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (ret) {
-               ret = -ENOMEM;
-               goto err_fb_alloc_cmap;
-       }
-
        info->par = helper;
 
        ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb,
@@ -339,7 +332,6 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
        fb = &vfbdev->vgfb.base;
 
        vfbdev->helper.fb = fb;
-       vfbdev->helper.fbdev = info;
 
        strcpy(info->fix.id, "virtiodrmfb");
        info->flags = FBINFO_DEFAULT;
@@ -357,9 +349,7 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
        return 0;
 
 err_fb_init:
-       fb_dealloc_cmap(&info->cmap);
-err_fb_alloc_cmap:
-       framebuffer_release(info);
+       drm_fb_helper_release_fbi(helper);
 err_fb_alloc:
        virtio_gpu_cmd_resource_inval_backing(vgdev, resid);
 err_obj_attach:
@@ -371,15 +361,11 @@ err_obj_vmap:
 static int virtio_gpu_fbdev_destroy(struct drm_device *dev,
                                    struct virtio_gpu_fbdev *vgfbdev)
 {
-       struct fb_info *info;
        struct virtio_gpu_framebuffer *vgfb = &vgfbdev->vgfb;
 
-       if (vgfbdev->helper.fbdev) {
-               info = vgfbdev->helper.fbdev;
+       drm_fb_helper_unregister_fbi(&vgfbdev->helper);
+       drm_fb_helper_release_fbi(&vgfbdev->helper);
 
-               unregister_framebuffer(info);
-               framebuffer_release(info);
-       }
        if (vgfb->obj)
                vgfb->obj = NULL;
        drm_fb_helper_fini(&vgfbdev->helper);
index 5ac92874404d60a6497c423f6e200bc35b922bf9..44e6ecba3de72fefb5b5b8d65eb62f3c3795ba7f 100644 (file)
@@ -159,7 +159,7 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv,
 
        if (dev_priv->has_mob) {
                uctx->man = vmw_cmdbuf_res_man_create(dev_priv);
-               if (unlikely(IS_ERR(uctx->man))) {
+               if (IS_ERR(uctx->man)) {
                        ret = PTR_ERR(uctx->man);
                        uctx->man = NULL;
                        goto out_err;
index 620bb5cf617c9689a9113e989d585346f420de3d..6218a36cf01a2143cf94f9aae7ea6f7788091495 100644 (file)
@@ -1054,7 +1054,7 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
                return -EINVAL;
 
        vmaster = vmw_master_check(dev, file_priv, flags);
-       if (unlikely(IS_ERR(vmaster))) {
+       if (IS_ERR(vmaster)) {
                ret = PTR_ERR(vmaster);
 
                if (ret != -ERESTARTSYS)
index 07cda8cbbddbcb5e6f56127c57dac0e683541fb9..2adc11bc09209cee810eae29b807c7c0e89be2bd 100644 (file)
@@ -1808,8 +1808,9 @@ void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
        }
 }
 
-void vmw_du_connector_dpms(struct drm_connector *connector, int mode)
+int vmw_du_connector_dpms(struct drm_connector *connector, int mode)
 {
+       return 0;
 }
 
 void vmw_du_connector_save(struct drm_connector *connector)
index 8d038c36bd57599b311f129532a768e9d39fdfa0..f1a324cfb4c3008b1b8ad9db8a17604fa683ea3d 100644 (file)
@@ -133,7 +133,7 @@ void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
 int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
                           uint32_t handle, uint32_t width, uint32_t height);
 int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
-void vmw_du_connector_dpms(struct drm_connector *connector, int mode);
+int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
 void vmw_du_connector_save(struct drm_connector *connector);
 void vmw_du_connector_restore(struct drm_connector *connector);
 enum drm_connector_status
index 37ac7b5dbd066025c90009d6b44a1c08fffcc800..21060668fd25ba59b514c6a5a915a542ef8da159 100644 (file)
@@ -6,17 +6,19 @@
  * Licensed under GPLv2
  *
  * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
-
- Switcher interface - methods require for ATPX and DCM
- - switchto - this throws the output MUX switch
- - discrete_set_power - sets the power state for the discrete card
-
- GPU driver interface
- - set_gpu_state - this should do the equiv of s/r for the card
-                 - this should *not* set the discrete power state
- - switch_check  - check if the device is in a position to switch now
+ *
Switcher interface - methods require for ATPX and DCM
- switchto - this throws the output MUX switch
- discrete_set_power - sets the power state for the discrete card
+ *
GPU driver interface
- set_gpu_state - this should do the equiv of s/r for the card
                - this should *not* set the discrete power state
- switch_check  - check if the device is in a position to switch now
  */
 
+#define pr_fmt(fmt) "vga_switcheroo: " fmt
+
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
@@ -111,7 +113,7 @@ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
 
        vgasr_priv.handler = handler;
        if (vga_switcheroo_ready()) {
-               printk(KERN_INFO "vga_switcheroo: enabled\n");
+               pr_info("enabled\n");
                vga_switcheroo_enable();
        }
        mutex_unlock(&vgasr_mutex);
@@ -124,7 +126,7 @@ void vga_switcheroo_unregister_handler(void)
        mutex_lock(&vgasr_mutex);
        vgasr_priv.handler = NULL;
        if (vgasr_priv.active) {
-               pr_info("vga_switcheroo: disabled\n");
+               pr_info("disabled\n");
                vga_switcheroo_debugfs_fini(&vgasr_priv);
                vgasr_priv.active = false;
        }
@@ -155,7 +157,7 @@ static int register_client(struct pci_dev *pdev,
                vgasr_priv.registered_clients++;
 
        if (vga_switcheroo_ready()) {
-               printk(KERN_INFO "vga_switcheroo: enabled\n");
+               pr_info("enabled\n");
                vga_switcheroo_enable();
        }
        mutex_unlock(&vgasr_mutex);
@@ -167,7 +169,8 @@ int vga_switcheroo_register_client(struct pci_dev *pdev,
                                   bool driver_power_control)
 {
        return register_client(pdev, ops, -1,
-                              pdev == vga_default_device(), driver_power_control);
+                              pdev == vga_default_device(),
+                              driver_power_control);
 }
 EXPORT_SYMBOL(vga_switcheroo_register_client);
 
@@ -183,6 +186,7 @@ static struct vga_switcheroo_client *
 find_client_from_pci(struct list_head *head, struct pci_dev *pdev)
 {
        struct vga_switcheroo_client *client;
+
        list_for_each_entry(client, head, list)
                if (client->pdev == pdev)
                        return client;
@@ -193,6 +197,7 @@ static struct vga_switcheroo_client *
 find_client_from_id(struct list_head *head, int client_id)
 {
        struct vga_switcheroo_client *client;
+
        list_for_each_entry(client, head, list)
                if (client->id == client_id)
                        return client;
@@ -203,6 +208,7 @@ static struct vga_switcheroo_client *
 find_active_client(struct list_head *head)
 {
        struct vga_switcheroo_client *client;
+
        list_for_each_entry(client, head, list)
                if (client->active && client_is_vga(client))
                        return client;
@@ -235,7 +241,7 @@ void vga_switcheroo_unregister_client(struct pci_dev *pdev)
                kfree(client);
        }
        if (vgasr_priv.active && vgasr_priv.registered_clients < 2) {
-               printk(KERN_INFO "vga_switcheroo: disabled\n");
+               pr_info("disabled\n");
                vga_switcheroo_debugfs_fini(&vgasr_priv);
                vgasr_priv.active = false;
        }
@@ -260,10 +266,12 @@ static int vga_switcheroo_show(struct seq_file *m, void *v)
 {
        struct vga_switcheroo_client *client;
        int i = 0;
+
        mutex_lock(&vgasr_mutex);
        list_for_each_entry(client, &vgasr_priv.clients, list) {
                seq_printf(m, "%d:%s%s:%c:%s%s:%s\n", i,
-                          client_id(client) == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
+                          client_id(client) == VGA_SWITCHEROO_DIS ? "DIS" :
+                                                                    "IGD",
                           client_is_vga(client) ? "" : "-Audio",
                           client->active ? '+' : ' ',
                           client->driver_power_control ? "Dyn" : "",
@@ -347,6 +355,7 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 
        if (new_client->fb_info) {
                struct fb_event event;
+
                console_lock();
                event.info = new_client->fb_info;
                fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
@@ -375,7 +384,7 @@ static bool check_can_switch(void)
 
        list_for_each_entry(client, &vgasr_priv.clients, list) {
                if (!client->ops->can_switch(client->pdev)) {
-                       printk(KERN_ERR "vga_switcheroo: client %x refused switch\n", client->id);
+                       pr_err("client %x refused switch\n", client->id);
                        return false;
                }
        }
@@ -484,20 +493,20 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
        if (can_switch) {
                ret = vga_switchto_stage1(client);
                if (ret)
-                       printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret);
+                       pr_err("switching failed stage 1 %d\n", ret);
 
                ret = vga_switchto_stage2(client);
                if (ret)
-                       printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret);
+                       pr_err("switching failed stage 2 %d\n", ret);
 
        } else {
-               printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id);
+               pr_info("setting delayed switch to client %d\n", client->id);
                vgasr_priv.delayed_switch_active = true;
                vgasr_priv.delayed_client_id = client_id;
 
                ret = vga_switchto_stage1(client);
                if (ret)
-                       printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret);
+                       pr_err("delayed switching stage 1 failed %d\n", ret);
        }
 
 out:
@@ -516,32 +525,32 @@ static const struct file_operations vga_switcheroo_debugfs_fops = {
 
 static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv)
 {
-       if (priv->switch_file) {
-               debugfs_remove(priv->switch_file);
-               priv->switch_file = NULL;
-       }
-       if (priv->debugfs_root) {
-               debugfs_remove(priv->debugfs_root);
-               priv->debugfs_root = NULL;
-       }
+       debugfs_remove(priv->switch_file);
+       priv->switch_file = NULL;
+
+       debugfs_remove(priv->debugfs_root);
+       priv->debugfs_root = NULL;
 }
 
 static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv)
 {
+       static const char mp[] = "/sys/kernel/debug";
+
        /* already initialised */
        if (priv->debugfs_root)
                return 0;
        priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL);
 
        if (!priv->debugfs_root) {
-               printk(KERN_ERR "vga_switcheroo: Cannot create /sys/kernel/debug/vgaswitcheroo\n");
+               pr_err("Cannot create %s/vgaswitcheroo\n", mp);
                goto fail;
        }
 
        priv->switch_file = debugfs_create_file("switch", 0644,
-                                               priv->debugfs_root, NULL, &vga_switcheroo_debugfs_fops);
+                                               priv->debugfs_root, NULL,
+                                               &vga_switcheroo_debugfs_fops);
        if (!priv->switch_file) {
-               printk(KERN_ERR "vga_switcheroo: cannot create /sys/kernel/debug/vgaswitcheroo/switch\n");
+               pr_err("cannot create %s/vgaswitcheroo/switch\n", mp);
                goto fail;
        }
        return 0;
@@ -560,7 +569,8 @@ int vga_switcheroo_process_delayed_switch(void)
        if (!vgasr_priv.delayed_switch_active)
                goto err;
 
-       printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id);
+       pr_info("processing delayed switch to %d\n",
+               vgasr_priv.delayed_client_id);
 
        client = find_client_from_id(&vgasr_priv.clients,
                                     vgasr_priv.delayed_client_id);
@@ -569,7 +579,7 @@ int vga_switcheroo_process_delayed_switch(void)
 
        ret = vga_switchto_stage2(client);
        if (ret)
-               printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret);
+               pr_err("delayed switching failed stage 2 %d\n", ret);
 
        vgasr_priv.delayed_switch_active = false;
        err = 0;
@@ -579,7 +589,8 @@ err:
 }
 EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
 
-static void vga_switcheroo_power_switch(struct pci_dev *pdev, enum vga_switcheroo_state state)
+static void vga_switcheroo_power_switch(struct pci_dev *pdev,
+                                       enum vga_switcheroo_state state)
 {
        struct vga_switcheroo_client *client;
 
@@ -598,7 +609,8 @@ static void vga_switcheroo_power_switch(struct pci_dev *pdev, enum vga_switchero
 
 /* force a PCI device to a certain state - mainly to turn off audio clients */
 
-void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic)
+void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev,
+                                      enum vga_switcheroo_state dynamic)
 {
        struct vga_switcheroo_client *client;
 
@@ -644,7 +656,8 @@ static int vga_switcheroo_runtime_resume(struct device *dev)
 
 /* this version is for the case where the power switch is separate
    to the device being powered down. */
-int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain)
+int vga_switcheroo_init_domain_pm_ops(struct device *dev,
+                                     struct dev_pm_domain *domain)
 {
        /* copy over all the bus versions */
        if (dev->bus && dev->bus->pm) {
@@ -675,7 +688,8 @@ static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
        /* we need to check if we have to switch back on the video
           device so the audio device can come back */
        list_for_each_entry(client, &vgasr_priv.clients, list) {
-               if (PCI_SLOT(client->pdev->devfn) == PCI_SLOT(pdev->devfn) && client_is_vga(client)) {
+               if (PCI_SLOT(client->pdev->devfn) == PCI_SLOT(pdev->devfn) &&
+                   client_is_vga(client)) {
                        found = client;
                        ret = pm_runtime_get_sync(&client->pdev->dev);
                        if (ret) {
@@ -695,12 +709,15 @@ static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
        return ret;
 }
 
-int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain)
+int
+vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev,
+                                                struct dev_pm_domain *domain)
 {
        /* copy over all the bus versions */
        if (dev->bus && dev->bus->pm) {
                domain->ops = *dev->bus->pm;
-               domain->ops.runtime_resume = vga_switcheroo_runtime_resume_hdmi_audio;
+               domain->ops.runtime_resume =
+                       vga_switcheroo_runtime_resume_hdmi_audio;
 
                dev->pm_domain = domain;
                return 0;
index 7bcbf863656ec6f2c1e76d6156365fc0548230ff..a0b4334561078bbd0a2d10a1a2816a372c26f33b 100644 (file)
@@ -29,6 +29,8 @@
  *
  */
 
+#define pr_fmt(fmt) "vgaarb: " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -134,7 +136,6 @@ struct pci_dev *vga_default_device(void)
 {
        return vga_default;
 }
-
 EXPORT_SYMBOL_GPL(vga_default_device);
 
 void vga_set_default_device(struct pci_dev *pdev)
@@ -298,9 +299,9 @@ enable_them:
 
        pci_set_vga_state(vgadev->pdev, true, pci_bits, flags);
 
-       if (!vgadev->bridge_has_one_vga) {
+       if (!vgadev->bridge_has_one_vga)
                vga_irq_set_state(vgadev, true);
-       }
+
        vgadev->owns |= wants;
 lock_them:
        vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK);
@@ -452,15 +453,15 @@ bail:
 }
 EXPORT_SYMBOL(vga_put);
 
-/* Rules for using a bridge to control a VGA descendant decoding:
-   if a bridge has only one VGA descendant then it can be used
-   to control the VGA routing for that device.
-   It should always use the bridge closest to the device to control it.
-   If a bridge has a direct VGA descendant, but also have a sub-bridge
-   VGA descendant then we cannot use that bridge to control the direct VGA descendant.
-   So for every device we register, we need to iterate all its parent bridges
  so we can invalidate any devices using them properly.
-*/
+/*
+ * Rules for using a bridge to control a VGA descendant decoding: if a bridge
+ * has only one VGA descendant then it can be used to control the VGA routing
+ * for that device. It should always use the bridge closest to the device to
+ * control it. If a bridge has a direct VGA descendant, but also have a sub-
+ * bridge VGA descendant then we cannot use that bridge to control the direct
+ * VGA descendant. So for every device we register, we need to iterate all
* its parent bridges so we can invalidate any devices using them properly.
+ */
 static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev)
 {
        struct vga_device *same_bridge_vgadev;
@@ -484,21 +485,26 @@ static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev)
 
                        /* see if the share a bridge with this device */
                        if (new_bridge == bridge) {
-                               /* if their direct parent bridge is the same
-                                  as any bridge of this device then it can't be used
-                                  for that device */
+                               /*
+                                * If their direct parent bridge is the same
+                                * as any bridge of this device then it can't
+                                * be used for that device.
+                                */
                                same_bridge_vgadev->bridge_has_one_vga = false;
                        }
 
-                       /* now iterate the previous devices bridge hierarchy */
-                       /* if the new devices parent bridge is in the other devices
-                          hierarchy then we can't use it to control this device */
+                       /*
+                        * Now iterate the previous devices bridge hierarchy.
+                        * If the new devices parent bridge is in the other
+                        * devices hierarchy then we can't use it to control
+                        * this device
+                        */
                        while (bus) {
                                bridge = bus->self;
-                               if (bridge) {
-                                       if (bridge == vgadev->pdev->bus->self)
-                                               vgadev->bridge_has_one_vga = false;
-                               }
+
+                               if (bridge && bridge == vgadev->pdev->bus->self)
+                                       vgadev->bridge_has_one_vga = false;
+
                                bus = bus->parent;
                        }
                }
@@ -527,10 +533,10 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
        /* Allocate structure */
        vgadev = kmalloc(sizeof(struct vga_device), GFP_KERNEL);
        if (vgadev == NULL) {
-               pr_err("vgaarb: failed to allocate pci device\n");
-               /* What to do on allocation failure ? For now, let's
-                * just do nothing, I'm not sure there is anything saner
-                * to be done
+               pr_err("failed to allocate pci device\n");
+               /*
+                * What to do on allocation failure ? For now, let's just do
+                * nothing, I'm not sure there is anything saner to be done.
                 */
                return false;
        }
@@ -566,8 +572,8 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
                bridge = bus->self;
                if (bridge) {
                        u16 l;
-                       pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
-                                            &l);
+
+                       pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &l);
                        if (!(l & PCI_BRIDGE_CTL_VGA)) {
                                vgadev->owns = 0;
                                break;
@@ -581,8 +587,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
         */
        if (vga_default == NULL &&
            ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
-               pr_info("vgaarb: setting as boot device: PCI:%s\n",
-                       pci_name(pdev));
+               pr_info("setting as boot device: PCI:%s\n", pci_name(pdev));
                vga_set_default_device(pdev);
        }
 
@@ -591,7 +596,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
        /* Add to the list */
        list_add(&vgadev->list, &vga_list);
        vga_count++;
-       pr_info("vgaarb: device added: PCI:%s,decodes=%s,owns=%s,locks=%s\n",
+       pr_info("device added: PCI:%s,decodes=%s,owns=%s,locks=%s\n",
                pci_name(pdev),
                vga_iostate_to_str(vgadev->decodes),
                vga_iostate_to_str(vgadev->owns),
@@ -651,7 +656,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
        decodes_unlocked = vgadev->locks & decodes_removed;
        vgadev->decodes = new_decodes;
 
-       pr_info("vgaarb: device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
+       pr_info("device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
                pci_name(vgadev->pdev),
                vga_iostate_to_str(old_decodes),
                vga_iostate_to_str(vgadev->decodes),
@@ -673,10 +678,12 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
        if (!(old_decodes & VGA_RSRC_LEGACY_MASK) &&
            new_decodes & VGA_RSRC_LEGACY_MASK)
                vga_decode_count++;
-       pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
+       pr_debug("decoding count now is: %d\n", vga_decode_count);
 }
 
-static void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace)
+static void __vga_set_legacy_decoding(struct pci_dev *pdev,
+                                     unsigned int decodes,
+                                     bool userspace)
 {
        struct vga_device *vgadev;
        unsigned long flags;
@@ -712,7 +719,8 @@ EXPORT_SYMBOL(vga_set_legacy_decoding);
 /* call with NULL to unregister */
 int vga_client_register(struct pci_dev *pdev, void *cookie,
                        void (*irq_set_state)(void *cookie, bool state),
-                       unsigned int (*set_vga_decode)(void *cookie, bool decode))
+                       unsigned int (*set_vga_decode)(void *cookie,
+                                                      bool decode))
 {
        int ret = -ENODEV;
        struct vga_device *vgadev;
@@ -832,7 +840,7 @@ static int vga_pci_str_to_vars(char *buf, int count, unsigned int *domain,
        return 1;
 }
 
-static ssize_t vga_arb_read(struct file *file, char __user * buf,
+static ssize_t vga_arb_read(struct file *file, char __user *buf,
                            size_t count, loff_t *ppos)
 {
        struct vga_arb_private *priv = file->private_data;
@@ -899,7 +907,7 @@ done:
  * TODO: To avoid parsing inside kernel and to improve the speed we may
  * consider use ioctl here
  */
-static ssize_t vga_arb_write(struct file *file, const char __user * buf,
+static ssize_t vga_arb_write(struct file *file, const char __user *buf,
                             size_t count, loff_t *ppos)
 {
        struct vga_arb_private *priv = file->private_data;
@@ -1075,13 +1083,13 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                                ret_val = -EPROTO;
                                goto done;
                        }
-                       pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
+                       pr_debug("%s ==> %x:%x:%x.%x\n", curr_pos,
                                domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
 
                        pdev = pci_get_domain_bus_and_slot(domain, bus, devfn);
-                       pr_debug("vgaarb: pdev %p\n", pdev);
+                       pr_debug("pdev %p\n", pdev);
                        if (!pdev) {
-                               pr_err("vgaarb: invalid PCI address %x:%x:%x\n",
+                               pr_err("invalid PCI address %x:%x:%x\n",
                                        domain, bus, devfn);
                                ret_val = -ENODEV;
                                goto done;
@@ -1089,10 +1097,13 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                }
 
                vgadev = vgadev_find(pdev);
-               pr_debug("vgaarb: vgadev %p\n", vgadev);
+               pr_debug("vgadev %p\n", vgadev);
                if (vgadev == NULL) {
-                       pr_err("vgaarb: this pci device is not a vga device\n");
-                       pci_dev_put(pdev);
+                       if (pdev) {
+                               pr_err("this pci device is not a vga device\n");
+                               pci_dev_put(pdev);
+                       }
+
                        ret_val = -ENODEV;
                        goto done;
                }
@@ -1109,7 +1120,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                        }
                }
                if (i == MAX_USER_CARDS) {
-                       pr_err("vgaarb: maximum user cards (%d) number reached!\n",
+                       pr_err("maximum user cards (%d) number reached!\n",
                                MAX_USER_CARDS);
                        pci_dev_put(pdev);
                        /* XXX: which value to return? */
@@ -1125,7 +1136,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
        } else if (strncmp(curr_pos, "decodes ", 8) == 0) {
                curr_pos += 8;
                remaining -= 8;
-               pr_debug("vgaarb: client 0x%p called 'decodes'\n", priv);
+               pr_debug("client 0x%p called 'decodes'\n", priv);
 
                if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
                        ret_val = -EPROTO;
@@ -1150,7 +1161,7 @@ done:
        return ret_val;
 }
 
-static unsigned int vga_arb_fpoll(struct file *file, poll_table * wait)
+static unsigned int vga_arb_fpoll(struct file *file, poll_table *wait)
 {
        struct vga_arb_private *priv = file->private_data;
 
@@ -1246,7 +1257,8 @@ static void vga_arbiter_notify_clients(void)
                else
                        new_state = true;
                if (vgadev->set_vga_decode) {
-                       new_decodes = vgadev->set_vga_decode(vgadev->cookie, new_state);
+                       new_decodes = vgadev->set_vga_decode(vgadev->cookie,
+                                                            new_state);
                        vga_update_device_decodes(vgadev, new_decodes);
                }
        }
@@ -1300,7 +1312,7 @@ static int __init vga_arb_device_init(void)
 
        rc = misc_register(&vga_arb_device);
        if (rc < 0)
-               pr_err("vgaarb: error %d registering device\n", rc);
+               pr_err("error %d registering device\n", rc);
 
        bus_register_notifier(&pci_bus_type, &pci_notifier);
 
@@ -1312,21 +1324,29 @@ static int __init vga_arb_device_init(void)
                               PCI_ANY_ID, pdev)) != NULL)
                vga_arbiter_add_pci_device(pdev);
 
-       pr_info("vgaarb: loaded\n");
+       pr_info("loaded\n");
 
        list_for_each_entry(vgadev, &vga_list, list) {
 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
-               /* Override I/O based detection done by vga_arbiter_add_pci_device()
-                * as it may take the wrong device (e.g. on Apple system under EFI).
+               /*
+                * Override vga_arbiter_add_pci_device()'s I/O based detection
+                * as it may take the wrong device (e.g. on Apple system under
+                * EFI).
                 *
-                * Select the device owning the boot framebuffer if there is one.
+                * Select the device owning the boot framebuffer if there is
+                * one.
                 */
-               resource_size_t start, end;
+               resource_size_t start, end, limit;
+               unsigned long flags;
                int i;
 
+               limit = screen_info.lfb_base + screen_info.lfb_size;
+
                /* Does firmware framebuffer belong to us? */
                for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-                       if (!(pci_resource_flags(vgadev->pdev, i) & IORESOURCE_MEM))
+                       flags = pci_resource_flags(vgadev->pdev, i);
+
+                       if ((flags & IORESOURCE_MEM) == 0)
                                continue;
 
                        start = pci_resource_start(vgadev->pdev, i);
@@ -1335,22 +1355,24 @@ static int __init vga_arb_device_init(void)
                        if (!start || !end)
                                continue;
 
-                       if (screen_info.lfb_base < start ||
-                           (screen_info.lfb_base + screen_info.lfb_size) >= end)
+                       if (screen_info.lfb_base < start || limit >= end)
                                continue;
+
                        if (!vga_default_device())
-                               pr_info("vgaarb: setting as boot device: PCI:%s\n",
+                               pr_info("setting as boot device: PCI:%s\n",
                                        pci_name(vgadev->pdev));
                        else if (vgadev->pdev != vga_default_device())
-                               pr_info("vgaarb: overriding boot device: PCI:%s\n",
+                               pr_info("overriding boot device: PCI:%s\n",
                                        pci_name(vgadev->pdev));
                        vga_set_default_device(vgadev->pdev);
                }
 #endif
                if (vgadev->bridge_has_one_vga)
-                       pr_info("vgaarb: bridge control possible %s\n", pci_name(vgadev->pdev));
+                       pr_info("bridge control possible %s\n",
+                               pci_name(vgadev->pdev));
                else
-                       pr_info("vgaarb: no bridge control possible %s\n", pci_name(vgadev->pdev));
+                       pr_info("no bridge control possible %s\n",
+                               pci_name(vgadev->pdev));
        }
        return rc;
 }
index 8bf495ffb020789811358eef574b6aba446cb141..e0606c01e8ac7166d88d2ad20028c166ebef625e 100644 (file)
@@ -22,9 +22,7 @@ source "drivers/gpu/vga/Kconfig"
 source "drivers/gpu/host1x/Kconfig"
 source "drivers/gpu/ipu-v3/Kconfig"
 
-menu "Direct Rendering Manager"
 source "drivers/gpu/drm/Kconfig"
-endmenu
 
 menu "Frame buffer Devices"
 source "drivers/video/fbdev/Kconfig"
index 4717449d6aa90be0fa24f7f8e9cecc03e2489439..1a9791ea1cf0ca5c88a9fdf0b6c099b7d59ccc1e 100644 (file)
@@ -681,7 +681,7 @@ struct drm_minor {
 
 struct drm_pending_vblank_event {
        struct drm_pending_event base;
-       int pipe;
+       unsigned int pipe;
        struct drm_event_vblank event;
 };
 
@@ -700,7 +700,7 @@ struct drm_vblank_crtc {
                                        /* for wraparound handling */
        u32 last_wait;                  /* Last vblank seqno waited per CRTC */
        unsigned int inmodeset;         /* Display driver is setting mode */
-       int crtc;                       /* crtc index */
+       unsigned int pipe;              /* crtc index */
        bool enabled;                   /* so we don't call enable more than
                                           once per disable */
 };
@@ -920,34 +920,34 @@ void drm_clflush_virt_range(void *addr, unsigned long length);
 extern int drm_irq_install(struct drm_device *dev, int irq);
 extern int drm_irq_uninstall(struct drm_device *dev);
 
-extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
+extern int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
 extern int drm_wait_vblank(struct drm_device *dev, void *data,
                           struct drm_file *filp);
-extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
+extern u32 drm_vblank_count(struct drm_device *dev, int pipe);
 extern u32 drm_crtc_vblank_count(struct drm_crtc *crtc);
-extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
+extern u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
                                     struct timeval *vblanktime);
-extern void drm_send_vblank_event(struct drm_device *dev, int crtc,
-                                    struct drm_pending_vblank_event *e);
+extern void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe,
+                                 struct drm_pending_vblank_event *e);
 extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
                                       struct drm_pending_vblank_event *e);
-extern bool drm_handle_vblank(struct drm_device *dev, int crtc);
+extern bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe);
 extern bool drm_crtc_handle_vblank(struct drm_crtc *crtc);
-extern int drm_vblank_get(struct drm_device *dev, int crtc);
-extern void drm_vblank_put(struct drm_device *dev, int crtc);
+extern int drm_vblank_get(struct drm_device *dev, unsigned int pipe);
+extern void drm_vblank_put(struct drm_device *dev, unsigned int pipe);
 extern int drm_crtc_vblank_get(struct drm_crtc *crtc);
 extern void drm_crtc_vblank_put(struct drm_crtc *crtc);
-extern void drm_wait_one_vblank(struct drm_device *dev, int crtc);
+extern void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe);
 extern void drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
-extern void drm_vblank_off(struct drm_device *dev, int crtc);
-extern void drm_vblank_on(struct drm_device *dev, int crtc);
+extern void drm_vblank_off(struct drm_device *dev, unsigned int pipe);
+extern void drm_vblank_on(struct drm_device *dev, unsigned int pipe);
 extern void drm_crtc_vblank_off(struct drm_crtc *crtc);
 extern void drm_crtc_vblank_reset(struct drm_crtc *crtc);
 extern void drm_crtc_vblank_on(struct drm_crtc *crtc);
 extern void drm_vblank_cleanup(struct drm_device *dev);
 
 extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
-                                                int crtc, int *max_error,
+                                                unsigned int pipe, int *max_error,
                                                 struct timeval *vblank_time,
                                                 unsigned flags,
                                                 const struct drm_crtc *refcrtc,
@@ -968,8 +968,8 @@ static inline wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc
 }
 
 /* Modesetting support */
-extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
-extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
+extern void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe);
+extern void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe);
 
                                /* Stub support (drm_stub.h) */
 extern struct drm_master *drm_master_get(struct drm_master *master);
index 8a3a913320ebb10647fea413430a3871f1f34eb1..e67aeac2aee05c077eec5a47abc9d73eef6831d6 100644 (file)
@@ -166,7 +166,8 @@ int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
 static inline bool
 drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state)
 {
-       return state->mode_changed || state->active_changed;
+       return state->mode_changed || state->active_changed ||
+              state->connectors_changed;
 }
 
 
index cc1fee8a12d0a5e71babb3626644604618b987ba..11266d147a29409b12718a1b575520579d588fde 100644 (file)
@@ -87,8 +87,8 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
                                struct drm_framebuffer *fb,
                                struct drm_pending_vblank_event *event,
                                uint32_t flags);
-void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
-                                     int mode);
+int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
+                                    int mode);
 
 /* default implementations for state handling */
 void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
index 3071319ea19406190a566b3c1daf84a42d2003f9..6e5afc30b59672b8a2f6c6b5e0256bd8be04593d 100644 (file)
@@ -255,12 +255,13 @@ struct drm_atomic_state;
  * @crtc: backpointer to the CRTC
  * @enable: whether the CRTC should be enabled, gates all other state
  * @active: whether the CRTC is actively displaying (used for DPMS)
- * @mode_changed: for use by helpers and drivers when computing state updates
- * @active_changed: for use by helpers and drivers when computing state updates
+ * @planes_changed: planes on this crtc are updated
+ * @mode_changed: crtc_state->mode or crtc_state->enable has been changed
+ * @active_changed: crtc_state->active has been toggled.
+ * @connectors_changed: connectors to this crtc have been updated
  * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
  * @last_vblank_count: for helpers and drivers to capture the vblank of the
  *     update to ensure framebuffer cleanup isn't done too early
- * @planes_changed: for use by helpers and drivers when computing state updates
  * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
  * @mode: current mode timings
  * @event: optional pointer to a DRM event to signal upon completion of the
@@ -283,6 +284,7 @@ struct drm_crtc_state {
        bool planes_changed : 1;
        bool mode_changed : 1;
        bool active_changed : 1;
+       bool connectors_changed : 1;
 
        /* attached planes bitmask:
         * WARNING: transitional helpers do not maintain plane_mask so
@@ -525,7 +527,7 @@ struct drm_connector_state {
  * etc.
  */
 struct drm_connector_funcs {
-       void (*dpms)(struct drm_connector *connector, int mode);
+       int (*dpms)(struct drm_connector *connector, int mode);
        void (*save)(struct drm_connector *connector);
        void (*restore)(struct drm_connector *connector);
        void (*reset)(struct drm_connector *connector);
@@ -863,7 +865,7 @@ struct drm_plane {
 
        uint32_t possible_crtcs;
        uint32_t *format_types;
-       uint32_t format_count;
+       unsigned int format_count;
        bool format_default;
 
        struct drm_crtc *crtc;
@@ -1268,13 +1270,13 @@ extern int drm_universal_plane_init(struct drm_device *dev,
                                    unsigned long possible_crtcs,
                                    const struct drm_plane_funcs *funcs,
                                    const uint32_t *formats,
-                                   uint32_t format_count,
+                                   unsigned int format_count,
                                    enum drm_plane_type type);
 extern int drm_plane_init(struct drm_device *dev,
                          struct drm_plane *plane,
                          unsigned long possible_crtcs,
                          const struct drm_plane_funcs *funcs,
-                         const uint32_t *formats, uint32_t format_count,
+                         const uint32_t *formats, unsigned int format_count,
                          bool is_primary);
 extern void drm_plane_cleanup(struct drm_plane *plane);
 extern unsigned int drm_plane_index(struct drm_plane *plane);
index c8fc187061de5fbd9fc8545f602a62baaa45b8cc..800e0d1cf32c2a397932a7597384350fd08a2f94 100644 (file)
@@ -108,8 +108,10 @@ struct drm_crtc_helper_funcs {
        /* atomic helpers */
        int (*atomic_check)(struct drm_crtc *crtc,
                            struct drm_crtc_state *state);
-       void (*atomic_begin)(struct drm_crtc *crtc);
-       void (*atomic_flush)(struct drm_crtc *crtc);
+       void (*atomic_begin)(struct drm_crtc *crtc,
+                            struct drm_crtc_state *old_crtc_state);
+       void (*atomic_flush)(struct drm_crtc *crtc,
+                            struct drm_crtc_state *old_crtc_state);
 };
 
 /**
@@ -187,7 +189,7 @@ extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
 extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
 
-extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode);
+extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
 
 extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
 
index 2e86f642fc3390f5909a87d2edeb6bdb97a626f6..94898f6ea02af17d84dbbe46f0c8e8818b5b9124 100644 (file)
 
 #define DP_TEST_SINK_MISC                  0x246
 # define DP_TEST_CRC_SUPPORTED             (1 << 5)
-# define DP_TEST_COUNT_MASK                0x7
+# define DP_TEST_COUNT_MASK                0xf
 
 #define DP_TEST_RESPONSE                   0x260
 # define DP_TEST_ACK                       (1 << 0)
index 0dfd94def593526eaa7d5e414a85634f37509385..dbab4622b58f7195b089d8fcadd27f31aec36e02 100644 (file)
@@ -122,6 +122,7 @@ struct drm_fb_helper {
        bool delayed_hotplug;
 };
 
+#ifdef CONFIG_DRM_FBDEV_EMULATION
 void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
                           const struct drm_fb_helper_funcs *funcs);
 int drm_fb_helper_init(struct drm_device *dev,
@@ -136,11 +137,38 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
                            struct fb_info *info);
 
 bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
+
+struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper);
+void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper);
+void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper);
 void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
                            uint32_t fb_width, uint32_t fb_height);
 void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
                            uint32_t depth);
 
+void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper);
+
+ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
+                              size_t count, loff_t *ppos);
+ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
+                               size_t count, loff_t *ppos);
+
+void drm_fb_helper_sys_fillrect(struct fb_info *info,
+                               const struct fb_fillrect *rect);
+void drm_fb_helper_sys_copyarea(struct fb_info *info,
+                               const struct fb_copyarea *area);
+void drm_fb_helper_sys_imageblit(struct fb_info *info,
+                                const struct fb_image *image);
+
+void drm_fb_helper_cfb_fillrect(struct fb_info *info,
+                               const struct fb_fillrect *rect);
+void drm_fb_helper_cfb_copyarea(struct fb_info *info,
+                               const struct fb_copyarea *area);
+void drm_fb_helper_cfb_imageblit(struct fb_info *info,
+                                const struct fb_image *image);
+
+void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state);
+
 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
 
 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
@@ -158,4 +186,188 @@ drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
 int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
                                       struct drm_connector *connector);
+#else
+static inline void drm_fb_helper_prepare(struct drm_device *dev,
+                                       struct drm_fb_helper *helper,
+                                       const struct drm_fb_helper_funcs *funcs)
+{
+}
+
+static inline int drm_fb_helper_init(struct drm_device *dev,
+                      struct drm_fb_helper *helper, int crtc_count,
+                      int max_conn)
+{
+       return 0;
+}
+
+static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)
+{
+}
+
+static inline int drm_fb_helper_blank(int blank, struct fb_info *info)
+{
+       return 0;
+}
+
+static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
+                                           struct fb_info *info)
+{
+       return 0;
+}
+
+static inline int drm_fb_helper_set_par(struct fb_info *info)
+{
+       return 0;
+}
+
+static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
+                                         struct fb_info *info)
+{
+       return 0;
+}
+
+static inline bool
+drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
+{
+       return true;
+}
+
+static inline struct fb_info *
+drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
+{
+       return NULL;
+}
+
+static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
+{
+}
+static inline void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper)
+{
+}
+
+static inline void drm_fb_helper_fill_var(struct fb_info *info,
+                                         struct drm_fb_helper *fb_helper,
+                                         uint32_t fb_width, uint32_t fb_height)
+{
+}
+
+static inline void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
+                                         uint32_t depth)
+{
+}
+
+static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap,
+                                       struct fb_info *info)
+{
+       return 0;
+}
+
+static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
+{
+}
+
+static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
+                                            char __user *buf, size_t count,
+                                            loff_t *ppos)
+{
+       return -ENODEV;
+}
+
+static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info,
+                                             const char __user *buf,
+                                             size_t count, loff_t *ppos)
+{
+       return -ENODEV;
+}
+
+static inline void drm_fb_helper_sys_fillrect(struct fb_info *info,
+                                             const struct fb_fillrect *rect)
+{
+}
+
+static inline void drm_fb_helper_sys_copyarea(struct fb_info *info,
+                                             const struct fb_copyarea *area)
+{
+}
+
+static inline void drm_fb_helper_sys_imageblit(struct fb_info *info,
+                                              const struct fb_image *image)
+{
+}
+
+static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info,
+                                             const struct fb_fillrect *rect)
+{
+}
+
+static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info,
+                                             const struct fb_copyarea *area)
+{
+}
+
+static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
+                                              const struct fb_image *image)
+{
+}
+
+static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
+                                            int state)
+{
+}
+
+static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
+{
+       return 0;
+}
+
+static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
+                                              int bpp_sel)
+{
+       return 0;
+}
+
+static inline int
+drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
+{
+       return 0;
+}
+
+static inline int drm_fb_helper_debug_enter(struct fb_info *info)
+{
+       return 0;
+}
+
+static inline int drm_fb_helper_debug_leave(struct fb_info *info)
+{
+       return 0;
+}
+
+static inline struct drm_display_mode *
+drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
+                      int width, int height)
+{
+       return NULL;
+}
+
+static inline struct drm_display_mode *
+drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
+                     int width, int height)
+{
+       return NULL;
+}
+
+static inline int
+drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
+                               struct drm_connector *connector)
+{
+       return 0;
+}
+
+static inline int
+drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
+                                  struct drm_connector *connector)
+{
+       return 0;
+}
+#endif
 #endif
index 70595ff565baa45190faaae5c42630fe04a1beff..5dd18bfdf6017daed071135d5cbbc20111f16b34 100644 (file)
@@ -130,7 +130,6 @@ struct drm_crtc;
 struct drm_plane;
 
 void drm_modeset_lock_all(struct drm_device *dev);
-int __drm_modeset_lock_all(struct drm_device *dev, bool trylock);
 void drm_modeset_unlock_all(struct drm_device *dev);
 void drm_modeset_lock_crtc(struct drm_crtc *crtc,
                           struct drm_plane *plane);
index 96e16283afb96ca3227a96733e6e6ff57acaac2a..dda401bf910e1eace1dbecbb7db92ca342ace306 100644 (file)
@@ -43,9 +43,8 @@
  * planes.
  */
 
-extern int drm_crtc_init(struct drm_device *dev,
-                        struct drm_crtc *crtc,
-                        const struct drm_crtc_funcs *funcs);
+int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+                 const struct drm_crtc_funcs *funcs);
 
 /**
  * drm_plane_helper_funcs - helper operations for CRTCs
@@ -79,26 +78,26 @@ static inline void drm_plane_helper_add(struct drm_plane *plane,
        plane->helper_private = funcs;
 }
 
-extern int drm_plane_helper_check_update(struct drm_plane *plane,
-                                        struct drm_crtc *crtc,
-                                        struct drm_framebuffer *fb,
-                                        struct drm_rect *src,
-                                        struct drm_rect *dest,
-                                        const struct drm_rect *clip,
-                                        int min_scale,
-                                        int max_scale,
-                                        bool can_position,
-                                        bool can_update_disabled,
-                                        bool *visible);
-extern int drm_primary_helper_update(struct drm_plane *plane,
-                                    struct drm_crtc *crtc,
-                                    struct drm_framebuffer *fb,
-                                    int crtc_x, int crtc_y,
-                                    unsigned int crtc_w, unsigned int crtc_h,
-                                    uint32_t src_x, uint32_t src_y,
-                                    uint32_t src_w, uint32_t src_h);
-extern int drm_primary_helper_disable(struct drm_plane *plane);
-extern void drm_primary_helper_destroy(struct drm_plane *plane);
+int drm_plane_helper_check_update(struct drm_plane *plane,
+                                 struct drm_crtc *crtc,
+                                 struct drm_framebuffer *fb,
+                                 struct drm_rect *src,
+                                 struct drm_rect *dest,
+                                 const struct drm_rect *clip,
+                                 int min_scale,
+                                 int max_scale,
+                                 bool can_position,
+                                 bool can_update_disabled,
+                                 bool *visible);
+int drm_primary_helper_update(struct drm_plane *plane,
+                             struct drm_crtc *crtc,
+                             struct drm_framebuffer *fb,
+                             int crtc_x, int crtc_y,
+                             unsigned int crtc_w, unsigned int crtc_h,
+                             uint32_t src_x, uint32_t src_y,
+                             uint32_t src_w, uint32_t src_h);
+int drm_primary_helper_disable(struct drm_plane *plane);
+void drm_primary_helper_destroy(struct drm_plane *plane);
 extern const struct drm_plane_funcs drm_primary_helper_funcs;
 
 int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,