]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Feb 2013 00:46:44 +0000 (16:46 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Feb 2013 00:46:44 +0000 (16:46 -0800)
Pull drm merge from Dave Airlie:
 "Highlights:

   - TI LCD controller KMS driver

   - TI OMAP KMS driver merged from staging

   - drop gma500 stub driver

   - the fbcon locking fixes

   - the vgacon dirty like zebra fix.

   - open firmware videomode and hdmi common code helpers

   - major locking rework for kms object handling - pageflip/cursor
     won't block on polling anymore!

   - fbcon helper and prime helper cleanups

   - i915: all over the map, haswell power well enhancements, valleyview
     macro horrors cleaned up, killing lots of legacy GTT code,

   - radeon: CS ioctl unification, deprecated UMS support, gpu reset
     rework, VM fixes

   - nouveau: reworked thermal code, external dp/tmds encoder support
     (anx9805), fences sleep instead of polling,

   - exynos: all over the driver fixes."

Lovely conflict in radeon/evergreen_cs.c between commit de0babd60d8d
("drm/radeon: enforce use of radeon_get_ib_value when reading user cmd")
and the new changes that modified that evergreen_dma_cs_parse()
function.

* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (508 commits)
  drm/tilcdc: only build on arm
  drm/i915: Revert hdmi HDP pin checks
  drm/tegra: Add list of framebuffers to debugfs
  drm/tegra: Fix color expansion
  drm/tegra: Split DC_CMD_STATE_CONTROL register write
  drm/tegra: Implement page-flipping support
  drm/tegra: Implement VBLANK support
  drm/tegra: Implement .mode_set_base()
  drm/tegra: Add plane support
  drm/tegra: Remove bogus tegra_framebuffer structure
  drm: Add consistency check for page-flipping
  drm/radeon: Use generic HDMI infoframe helpers
  drm/tegra: Use generic HDMI infoframe helpers
  drm: Add EDID helper documentation
  drm: Add HDMI infoframe helpers
  video: Add generic HDMI infoframe helpers
  drm: Add some missing forward declarations
  drm: Move mode tables to drm_edid.c
  drm: Remove duplicate drm_mode_cea_vic()
  gma500: Fix n, m1 and m2 clock limits for sdvo and lvds
  ...

30 files changed:
1  2 
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/nouveau/core/include/core/object.h
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/omapdrm/Kconfig
drivers/gpu/drm/omapdrm/omap_connector.c
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/omapdrm/omap_encoder.c
drivers/gpu/drm/omapdrm/omap_fb.c
drivers/gpu/drm/omapdrm/omap_fbdev.c
drivers/gpu/drm/omapdrm/omap_gem.c
drivers/gpu/drm/omapdrm/omap_plane.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/hdmi.c
drivers/iommu/intel-iommu.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/tty/vt/vt.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/console/fbcon.c
include/linux/console.h
kernel/printk.c

index fb2f81b8063dfcf08f9c1cf47a5dfb097ecb2b0c,0fcfbe4660bb969ca99171f3b3a94f2a75fb4baa..3b0da0378acf509976361d85322dc1fbc5c6779f
@@@ -19,6 -19,7 +19,7 @@@
  #include <linux/workqueue.h>
  #include <linux/dma-mapping.h>
  #include <linux/dma-attrs.h>
+ #include <linux/of.h>
  
  #include <drm/drmP.h>
  #include <drm/exynos_drm.h>
@@@ -429,7 -430,7 +430,7 @@@ static dma_addr_t *g2d_userptr_get_dma_
  
        g2d_userptr->pages = pages;
  
-       sgt = kzalloc(sizeof *sgt, GFP_KERNEL);
+       sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
        if (!sgt) {
                DRM_ERROR("failed to allocate sg table.\n");
                ret = -ENOMEM;
@@@ -1136,9 -1137,10 +1137,9 @@@ static int g2d_probe(struct platform_de
  
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  
 -      g2d->regs = devm_request_and_ioremap(&pdev->dev, res);
 -      if (!g2d->regs) {
 -              dev_err(dev, "failed to remap I/O memory\n");
 -              ret = -ENXIO;
 +      g2d->regs = devm_ioremap_resource(&pdev->dev, res);
 +      if (IS_ERR(g2d->regs)) {
 +              ret = PTR_ERR(g2d->regs);
                goto err_put_clk;
        }
  
@@@ -1239,6 -1241,14 +1240,14 @@@ static int g2d_resume(struct device *de
  
  static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);
  
+ #ifdef CONFIG_OF
+ static const struct of_device_id exynos_g2d_match[] = {
+       { .compatible = "samsung,exynos5250-g2d" },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, exynos_g2d_match);
+ #endif
  struct platform_driver g2d_driver = {
        .probe          = g2d_probe,
        .remove         = g2d_remove,
                .name   = "s5p-g2d",
                .owner  = THIS_MODULE,
                .pm     = &g2d_pm_ops,
+               .of_match_table = of_match_ptr(exynos_g2d_match),
        },
  };
index 233247505ff8096cb21cbdadbdaf1a9be3bf3ae6,6d63f9090f943161072399fdd97d8aaaad4b0284..2c5f266154ad4b459dd5296d4a72fdc3fea10035
@@@ -87,6 -87,73 +87,73 @@@ struct hdmi_resources 
        int                             regul_count;
  };
  
+ struct hdmi_tg_regs {
+       u8 cmd[1];
+       u8 h_fsz[2];
+       u8 hact_st[2];
+       u8 hact_sz[2];
+       u8 v_fsz[2];
+       u8 vsync[2];
+       u8 vsync2[2];
+       u8 vact_st[2];
+       u8 vact_sz[2];
+       u8 field_chg[2];
+       u8 vact_st2[2];
+       u8 vact_st3[2];
+       u8 vact_st4[2];
+       u8 vsync_top_hdmi[2];
+       u8 vsync_bot_hdmi[2];
+       u8 field_top_hdmi[2];
+       u8 field_bot_hdmi[2];
+       u8 tg_3d[1];
+ };
+ struct hdmi_core_regs {
+       u8 h_blank[2];
+       u8 v2_blank[2];
+       u8 v1_blank[2];
+       u8 v_line[2];
+       u8 h_line[2];
+       u8 hsync_pol[1];
+       u8 vsync_pol[1];
+       u8 int_pro_mode[1];
+       u8 v_blank_f0[2];
+       u8 v_blank_f1[2];
+       u8 h_sync_start[2];
+       u8 h_sync_end[2];
+       u8 v_sync_line_bef_2[2];
+       u8 v_sync_line_bef_1[2];
+       u8 v_sync_line_aft_2[2];
+       u8 v_sync_line_aft_1[2];
+       u8 v_sync_line_aft_pxl_2[2];
+       u8 v_sync_line_aft_pxl_1[2];
+       u8 v_blank_f2[2]; /* for 3D mode */
+       u8 v_blank_f3[2]; /* for 3D mode */
+       u8 v_blank_f4[2]; /* for 3D mode */
+       u8 v_blank_f5[2]; /* for 3D mode */
+       u8 v_sync_line_aft_3[2];
+       u8 v_sync_line_aft_4[2];
+       u8 v_sync_line_aft_5[2];
+       u8 v_sync_line_aft_6[2];
+       u8 v_sync_line_aft_pxl_3[2];
+       u8 v_sync_line_aft_pxl_4[2];
+       u8 v_sync_line_aft_pxl_5[2];
+       u8 v_sync_line_aft_pxl_6[2];
+       u8 vact_space_1[2];
+       u8 vact_space_2[2];
+       u8 vact_space_3[2];
+       u8 vact_space_4[2];
+       u8 vact_space_5[2];
+       u8 vact_space_6[2];
+ };
+ struct hdmi_v14_conf {
+       int pixel_clock;
+       struct hdmi_core_regs core;
+       struct hdmi_tg_regs tg;
+       int cea_video_id;
+ };
  struct hdmi_context {
        struct device                   *dev;
        struct drm_device               *drm_dev;
  
        /* current hdmiphy conf index */
        int cur_conf;
+       struct hdmi_v14_conf            mode_conf;
  
        struct hdmi_resources           res;
  
@@@ -392,586 -460,132 +460,132 @@@ static const struct hdmi_v13_conf hdmi_
  };
  
  /* HDMI Version 1.4 */
- static const u8 hdmiphy_conf27_027[32] = {
-       0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
-       0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
-       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
-       0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
- };
- static const u8 hdmiphy_conf74_176[32] = {
-       0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08,
-       0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80,
-       0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
-       0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
- };
- static const u8 hdmiphy_conf74_25[32] = {
-       0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
-       0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
-       0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
-       0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
- };
- static const u8 hdmiphy_conf148_5[32] = {
-       0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
-       0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
-       0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
-       0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
+ struct hdmiphy_config {
+       int pixel_clock;
+       u8 conf[32];
  };
  
- struct hdmi_tg_regs {
-       u8 cmd;
-       u8 h_fsz_l;
-       u8 h_fsz_h;
-       u8 hact_st_l;
-       u8 hact_st_h;
-       u8 hact_sz_l;
-       u8 hact_sz_h;
-       u8 v_fsz_l;
-       u8 v_fsz_h;
-       u8 vsync_l;
-       u8 vsync_h;
-       u8 vsync2_l;
-       u8 vsync2_h;
-       u8 vact_st_l;
-       u8 vact_st_h;
-       u8 vact_sz_l;
-       u8 vact_sz_h;
-       u8 field_chg_l;
-       u8 field_chg_h;
-       u8 vact_st2_l;
-       u8 vact_st2_h;
-       u8 vact_st3_l;
-       u8 vact_st3_h;
-       u8 vact_st4_l;
-       u8 vact_st4_h;
-       u8 vsync_top_hdmi_l;
-       u8 vsync_top_hdmi_h;
-       u8 vsync_bot_hdmi_l;
-       u8 vsync_bot_hdmi_h;
-       u8 field_top_hdmi_l;
-       u8 field_top_hdmi_h;
-       u8 field_bot_hdmi_l;
-       u8 field_bot_hdmi_h;
-       u8 tg_3d;
- };
- struct hdmi_core_regs {
-       u8 h_blank[2];
-       u8 v2_blank[2];
-       u8 v1_blank[2];
-       u8 v_line[2];
-       u8 h_line[2];
-       u8 hsync_pol[1];
-       u8 vsync_pol[1];
-       u8 int_pro_mode[1];
-       u8 v_blank_f0[2];
-       u8 v_blank_f1[2];
-       u8 h_sync_start[2];
-       u8 h_sync_end[2];
-       u8 v_sync_line_bef_2[2];
-       u8 v_sync_line_bef_1[2];
-       u8 v_sync_line_aft_2[2];
-       u8 v_sync_line_aft_1[2];
-       u8 v_sync_line_aft_pxl_2[2];
-       u8 v_sync_line_aft_pxl_1[2];
-       u8 v_blank_f2[2]; /* for 3D mode */
-       u8 v_blank_f3[2]; /* for 3D mode */
-       u8 v_blank_f4[2]; /* for 3D mode */
-       u8 v_blank_f5[2]; /* for 3D mode */
-       u8 v_sync_line_aft_3[2];
-       u8 v_sync_line_aft_4[2];
-       u8 v_sync_line_aft_5[2];
-       u8 v_sync_line_aft_6[2];
-       u8 v_sync_line_aft_pxl_3[2];
-       u8 v_sync_line_aft_pxl_4[2];
-       u8 v_sync_line_aft_pxl_5[2];
-       u8 v_sync_line_aft_pxl_6[2];
-       u8 vact_space_1[2];
-       u8 vact_space_2[2];
-       u8 vact_space_3[2];
-       u8 vact_space_4[2];
-       u8 vact_space_5[2];
-       u8 vact_space_6[2];
- };
- struct hdmi_preset_conf {
-       struct hdmi_core_regs core;
-       struct hdmi_tg_regs tg;
- };
- struct hdmi_conf {
-       int width;
-       int height;
-       int vrefresh;
-       bool interlace;
-       int cea_video_id;
-       const u8 *hdmiphy_data;
-       const struct hdmi_preset_conf *conf;
- };
- static const struct hdmi_preset_conf hdmi_conf_480p60 = {
-       .core = {
-               .h_blank = {0x8a, 0x00},
-               .v2_blank = {0x0d, 0x02},
-               .v1_blank = {0x2d, 0x00},
-               .v_line = {0x0d, 0x02},
-               .h_line = {0x5a, 0x03},
-               .hsync_pol = {0x01},
-               .vsync_pol = {0x01},
-               .int_pro_mode = {0x00},
-               .v_blank_f0 = {0xff, 0xff},
-               .v_blank_f1 = {0xff, 0xff},
-               .h_sync_start = {0x0e, 0x00},
-               .h_sync_end = {0x4c, 0x00},
-               .v_sync_line_bef_2 = {0x0f, 0x00},
-               .v_sync_line_bef_1 = {0x09, 0x00},
-               .v_sync_line_aft_2 = {0xff, 0xff},
-               .v_sync_line_aft_1 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_2 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_1 = {0xff, 0xff},
-               .v_blank_f2 = {0xff, 0xff},
-               .v_blank_f3 = {0xff, 0xff},
-               .v_blank_f4 = {0xff, 0xff},
-               .v_blank_f5 = {0xff, 0xff},
-               .v_sync_line_aft_3 = {0xff, 0xff},
-               .v_sync_line_aft_4 = {0xff, 0xff},
-               .v_sync_line_aft_5 = {0xff, 0xff},
-               .v_sync_line_aft_6 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_3 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_4 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_5 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_6 = {0xff, 0xff},
-               .vact_space_1 = {0xff, 0xff},
-               .vact_space_2 = {0xff, 0xff},
-               .vact_space_3 = {0xff, 0xff},
-               .vact_space_4 = {0xff, 0xff},
-               .vact_space_5 = {0xff, 0xff},
-               .vact_space_6 = {0xff, 0xff},
-               /* other don't care */
+ /* list of all required phy config settings */
+ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
+       {
+               .pixel_clock = 25200000,
+               .conf = {
+                       0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
+                       0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+               },
        },
-       .tg = {
-               0x00, /* cmd */
-               0x5a, 0x03, /* h_fsz */
-               0x8a, 0x00, 0xd0, 0x02, /* hact */
-               0x0d, 0x02, /* v_fsz */
-               0x01, 0x00, 0x33, 0x02, /* vsync */
-               0x2d, 0x00, 0xe0, 0x01, /* vact */
-               0x33, 0x02, /* field_chg */
-               0x48, 0x02, /* vact_st2 */
-               0x00, 0x00, /* vact_st3 */
-               0x00, 0x00, /* vact_st4 */
-               0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
-               0x01, 0x00, 0x33, 0x02, /* field top/bot */
-               0x00, /* 3d FP */
-       },
- };
- static const struct hdmi_preset_conf hdmi_conf_720p50 = {
-       .core = {
-               .h_blank = {0xbc, 0x02},
-               .v2_blank = {0xee, 0x02},
-               .v1_blank = {0x1e, 0x00},
-               .v_line = {0xee, 0x02},
-               .h_line = {0xbc, 0x07},
-               .hsync_pol = {0x00},
-               .vsync_pol = {0x00},
-               .int_pro_mode = {0x00},
-               .v_blank_f0 = {0xff, 0xff},
-               .v_blank_f1 = {0xff, 0xff},
-               .h_sync_start = {0xb6, 0x01},
-               .h_sync_end = {0xde, 0x01},
-               .v_sync_line_bef_2 = {0x0a, 0x00},
-               .v_sync_line_bef_1 = {0x05, 0x00},
-               .v_sync_line_aft_2 = {0xff, 0xff},
-               .v_sync_line_aft_1 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_2 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_1 = {0xff, 0xff},
-               .v_blank_f2 = {0xff, 0xff},
-               .v_blank_f3 = {0xff, 0xff},
-               .v_blank_f4 = {0xff, 0xff},
-               .v_blank_f5 = {0xff, 0xff},
-               .v_sync_line_aft_3 = {0xff, 0xff},
-               .v_sync_line_aft_4 = {0xff, 0xff},
-               .v_sync_line_aft_5 = {0xff, 0xff},
-               .v_sync_line_aft_6 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_3 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_4 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_5 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_6 = {0xff, 0xff},
-               .vact_space_1 = {0xff, 0xff},
-               .vact_space_2 = {0xff, 0xff},
-               .vact_space_3 = {0xff, 0xff},
-               .vact_space_4 = {0xff, 0xff},
-               .vact_space_5 = {0xff, 0xff},
-               .vact_space_6 = {0xff, 0xff},
-               /* other don't care */
+       {
+               .pixel_clock = 27000000,
+               .conf = {
+                       0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
+                       0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
+                       0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+               },
        },
-       .tg = {
-               0x00, /* cmd */
-               0xbc, 0x07, /* h_fsz */
-               0xbc, 0x02, 0x00, 0x05, /* hact */
-               0xee, 0x02, /* v_fsz */
-               0x01, 0x00, 0x33, 0x02, /* vsync */
-               0x1e, 0x00, 0xd0, 0x02, /* vact */
-               0x33, 0x02, /* field_chg */
-               0x48, 0x02, /* vact_st2 */
-               0x00, 0x00, /* vact_st3 */
-               0x00, 0x00, /* vact_st4 */
-               0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
-               0x01, 0x00, 0x33, 0x02, /* field top/bot */
-               0x00, /* 3d FP */
-       },
- };
- static const struct hdmi_preset_conf hdmi_conf_720p60 = {
-       .core = {
-               .h_blank = {0x72, 0x01},
-               .v2_blank = {0xee, 0x02},
-               .v1_blank = {0x1e, 0x00},
-               .v_line = {0xee, 0x02},
-               .h_line = {0x72, 0x06},
-               .hsync_pol = {0x00},
-               .vsync_pol = {0x00},
-               .int_pro_mode = {0x00},
-               .v_blank_f0 = {0xff, 0xff},
-               .v_blank_f1 = {0xff, 0xff},
-               .h_sync_start = {0x6c, 0x00},
-               .h_sync_end = {0x94, 0x00},
-               .v_sync_line_bef_2 = {0x0a, 0x00},
-               .v_sync_line_bef_1 = {0x05, 0x00},
-               .v_sync_line_aft_2 = {0xff, 0xff},
-               .v_sync_line_aft_1 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_2 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_1 = {0xff, 0xff},
-               .v_blank_f2 = {0xff, 0xff},
-               .v_blank_f3 = {0xff, 0xff},
-               .v_blank_f4 = {0xff, 0xff},
-               .v_blank_f5 = {0xff, 0xff},
-               .v_sync_line_aft_3 = {0xff, 0xff},
-               .v_sync_line_aft_4 = {0xff, 0xff},
-               .v_sync_line_aft_5 = {0xff, 0xff},
-               .v_sync_line_aft_6 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_3 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_4 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_5 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_6 = {0xff, 0xff},
-               .vact_space_1 = {0xff, 0xff},
-               .vact_space_2 = {0xff, 0xff},
-               .vact_space_3 = {0xff, 0xff},
-               .vact_space_4 = {0xff, 0xff},
-               .vact_space_5 = {0xff, 0xff},
-               .vact_space_6 = {0xff, 0xff},
-               /* other don't care */
-       },
-       .tg = {
-               0x00, /* cmd */
-               0x72, 0x06, /* h_fsz */
-               0x72, 0x01, 0x00, 0x05, /* hact */
-               0xee, 0x02, /* v_fsz */
-               0x01, 0x00, 0x33, 0x02, /* vsync */
-               0x1e, 0x00, 0xd0, 0x02, /* vact */
-               0x33, 0x02, /* field_chg */
-               0x48, 0x02, /* vact_st2 */
-               0x00, 0x00, /* vact_st3 */
-               0x00, 0x00, /* vact_st4 */
-               0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
-               0x01, 0x00, 0x33, 0x02, /* field top/bot */
-               0x00, /* 3d FP */
+       {
+               .pixel_clock = 27027000,
+               .conf = {
+                       0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
+                       0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
+               },
        },
- };
- static const struct hdmi_preset_conf hdmi_conf_1080i50 = {
-       .core = {
-               .h_blank = {0xd0, 0x02},
-               .v2_blank = {0x32, 0x02},
-               .v1_blank = {0x16, 0x00},
-               .v_line = {0x65, 0x04},
-               .h_line = {0x50, 0x0a},
-               .hsync_pol = {0x00},
-               .vsync_pol = {0x00},
-               .int_pro_mode = {0x01},
-               .v_blank_f0 = {0x49, 0x02},
-               .v_blank_f1 = {0x65, 0x04},
-               .h_sync_start = {0x0e, 0x02},
-               .h_sync_end = {0x3a, 0x02},
-               .v_sync_line_bef_2 = {0x07, 0x00},
-               .v_sync_line_bef_1 = {0x02, 0x00},
-               .v_sync_line_aft_2 = {0x39, 0x02},
-               .v_sync_line_aft_1 = {0x34, 0x02},
-               .v_sync_line_aft_pxl_2 = {0x38, 0x07},
-               .v_sync_line_aft_pxl_1 = {0x38, 0x07},
-               .v_blank_f2 = {0xff, 0xff},
-               .v_blank_f3 = {0xff, 0xff},
-               .v_blank_f4 = {0xff, 0xff},
-               .v_blank_f5 = {0xff, 0xff},
-               .v_sync_line_aft_3 = {0xff, 0xff},
-               .v_sync_line_aft_4 = {0xff, 0xff},
-               .v_sync_line_aft_5 = {0xff, 0xff},
-               .v_sync_line_aft_6 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_3 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_4 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_5 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_6 = {0xff, 0xff},
-               .vact_space_1 = {0xff, 0xff},
-               .vact_space_2 = {0xff, 0xff},
-               .vact_space_3 = {0xff, 0xff},
-               .vact_space_4 = {0xff, 0xff},
-               .vact_space_5 = {0xff, 0xff},
-               .vact_space_6 = {0xff, 0xff},
-               /* other don't care */
+       {
+               .pixel_clock = 36000000,
+               .conf = {
+                       0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
+                       0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+               },
        },
-       .tg = {
-               0x00, /* cmd */
-               0x50, 0x0a, /* h_fsz */
-               0xd0, 0x02, 0x80, 0x07, /* hact */
-               0x65, 0x04, /* v_fsz */
-               0x01, 0x00, 0x33, 0x02, /* vsync */
-               0x16, 0x00, 0x1c, 0x02, /* vact */
-               0x33, 0x02, /* field_chg */
-               0x49, 0x02, /* vact_st2 */
-               0x00, 0x00, /* vact_st3 */
-               0x00, 0x00, /* vact_st4 */
-               0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
-               0x01, 0x00, 0x33, 0x02, /* field top/bot */
-               0x00, /* 3d FP */
+       {
+               .pixel_clock = 40000000,
+               .conf = {
+                       0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
+                       0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+               },
        },
- };
- static const struct hdmi_preset_conf hdmi_conf_1080i60 = {
-       .core = {
-               .h_blank = {0x18, 0x01},
-               .v2_blank = {0x32, 0x02},
-               .v1_blank = {0x16, 0x00},
-               .v_line = {0x65, 0x04},
-               .h_line = {0x98, 0x08},
-               .hsync_pol = {0x00},
-               .vsync_pol = {0x00},
-               .int_pro_mode = {0x01},
-               .v_blank_f0 = {0x49, 0x02},
-               .v_blank_f1 = {0x65, 0x04},
-               .h_sync_start = {0x56, 0x00},
-               .h_sync_end = {0x82, 0x00},
-               .v_sync_line_bef_2 = {0x07, 0x00},
-               .v_sync_line_bef_1 = {0x02, 0x00},
-               .v_sync_line_aft_2 = {0x39, 0x02},
-               .v_sync_line_aft_1 = {0x34, 0x02},
-               .v_sync_line_aft_pxl_2 = {0xa4, 0x04},
-               .v_sync_line_aft_pxl_1 = {0xa4, 0x04},
-               .v_blank_f2 = {0xff, 0xff},
-               .v_blank_f3 = {0xff, 0xff},
-               .v_blank_f4 = {0xff, 0xff},
-               .v_blank_f5 = {0xff, 0xff},
-               .v_sync_line_aft_3 = {0xff, 0xff},
-               .v_sync_line_aft_4 = {0xff, 0xff},
-               .v_sync_line_aft_5 = {0xff, 0xff},
-               .v_sync_line_aft_6 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_3 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_4 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_5 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_6 = {0xff, 0xff},
-               .vact_space_1 = {0xff, 0xff},
-               .vact_space_2 = {0xff, 0xff},
-               .vact_space_3 = {0xff, 0xff},
-               .vact_space_4 = {0xff, 0xff},
-               .vact_space_5 = {0xff, 0xff},
-               .vact_space_6 = {0xff, 0xff},
-               /* other don't care */
+       {
+               .pixel_clock = 65000000,
+               .conf = {
+                       0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
+                       0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+               },
        },
-       .tg = {
-               0x00, /* cmd */
-               0x98, 0x08, /* h_fsz */
-               0x18, 0x01, 0x80, 0x07, /* hact */
-               0x65, 0x04, /* v_fsz */
-               0x01, 0x00, 0x33, 0x02, /* vsync */
-               0x16, 0x00, 0x1c, 0x02, /* vact */
-               0x33, 0x02, /* field_chg */
-               0x49, 0x02, /* vact_st2 */
-               0x00, 0x00, /* vact_st3 */
-               0x00, 0x00, /* vact_st4 */
-               0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
-               0x01, 0x00, 0x33, 0x02, /* field top/bot */
-               0x00, /* 3d FP */
+       {
+               .pixel_clock = 74176000,
+               .conf = {
+                       0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
+                       0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+               },
        },
- };
- static const struct hdmi_preset_conf hdmi_conf_1080p30 = {
-       .core = {
-               .h_blank = {0x18, 0x01},
-               .v2_blank = {0x65, 0x04},
-               .v1_blank = {0x2d, 0x00},
-               .v_line = {0x65, 0x04},
-               .h_line = {0x98, 0x08},
-               .hsync_pol = {0x00},
-               .vsync_pol = {0x00},
-               .int_pro_mode = {0x00},
-               .v_blank_f0 = {0xff, 0xff},
-               .v_blank_f1 = {0xff, 0xff},
-               .h_sync_start = {0x56, 0x00},
-               .h_sync_end = {0x82, 0x00},
-               .v_sync_line_bef_2 = {0x09, 0x00},
-               .v_sync_line_bef_1 = {0x04, 0x00},
-               .v_sync_line_aft_2 = {0xff, 0xff},
-               .v_sync_line_aft_1 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_2 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_1 = {0xff, 0xff},
-               .v_blank_f2 = {0xff, 0xff},
-               .v_blank_f3 = {0xff, 0xff},
-               .v_blank_f4 = {0xff, 0xff},
-               .v_blank_f5 = {0xff, 0xff},
-               .v_sync_line_aft_3 = {0xff, 0xff},
-               .v_sync_line_aft_4 = {0xff, 0xff},
-               .v_sync_line_aft_5 = {0xff, 0xff},
-               .v_sync_line_aft_6 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_3 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_4 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_5 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_6 = {0xff, 0xff},
-               .vact_space_1 = {0xff, 0xff},
-               .vact_space_2 = {0xff, 0xff},
-               .vact_space_3 = {0xff, 0xff},
-               .vact_space_4 = {0xff, 0xff},
-               .vact_space_5 = {0xff, 0xff},
-               .vact_space_6 = {0xff, 0xff},
-               /* other don't care */
+       {
+               .pixel_clock = 74250000,
+               .conf = {
+                       0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
+                       0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
+                       0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
+               },
        },
-       .tg = {
-               0x00, /* cmd */
-               0x98, 0x08, /* h_fsz */
-               0x18, 0x01, 0x80, 0x07, /* hact */
-               0x65, 0x04, /* v_fsz */
-               0x01, 0x00, 0x33, 0x02, /* vsync */
-               0x2d, 0x00, 0x38, 0x04, /* vact */
-               0x33, 0x02, /* field_chg */
-               0x48, 0x02, /* vact_st2 */
-               0x00, 0x00, /* vact_st3 */
-               0x00, 0x00, /* vact_st4 */
-               0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
-               0x01, 0x00, 0x33, 0x02, /* field top/bot */
-               0x00, /* 3d FP */
+       {
+               .pixel_clock = 83500000,
+               .conf = {
+                       0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
+                       0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+               },
        },
- };
- static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
-       .core = {
-               .h_blank = {0xd0, 0x02},
-               .v2_blank = {0x65, 0x04},
-               .v1_blank = {0x2d, 0x00},
-               .v_line = {0x65, 0x04},
-               .h_line = {0x50, 0x0a},
-               .hsync_pol = {0x00},
-               .vsync_pol = {0x00},
-               .int_pro_mode = {0x00},
-               .v_blank_f0 = {0xff, 0xff},
-               .v_blank_f1 = {0xff, 0xff},
-               .h_sync_start = {0x0e, 0x02},
-               .h_sync_end = {0x3a, 0x02},
-               .v_sync_line_bef_2 = {0x09, 0x00},
-               .v_sync_line_bef_1 = {0x04, 0x00},
-               .v_sync_line_aft_2 = {0xff, 0xff},
-               .v_sync_line_aft_1 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_2 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_1 = {0xff, 0xff},
-               .v_blank_f2 = {0xff, 0xff},
-               .v_blank_f3 = {0xff, 0xff},
-               .v_blank_f4 = {0xff, 0xff},
-               .v_blank_f5 = {0xff, 0xff},
-               .v_sync_line_aft_3 = {0xff, 0xff},
-               .v_sync_line_aft_4 = {0xff, 0xff},
-               .v_sync_line_aft_5 = {0xff, 0xff},
-               .v_sync_line_aft_6 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_3 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_4 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_5 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_6 = {0xff, 0xff},
-               .vact_space_1 = {0xff, 0xff},
-               .vact_space_2 = {0xff, 0xff},
-               .vact_space_3 = {0xff, 0xff},
-               .vact_space_4 = {0xff, 0xff},
-               .vact_space_5 = {0xff, 0xff},
-               .vact_space_6 = {0xff, 0xff},
-               /* other don't care */
+       {
+               .pixel_clock = 106500000,
+               .conf = {
+                       0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
+                       0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+               },
        },
-       .tg = {
-               0x00, /* cmd */
-               0x50, 0x0a, /* h_fsz */
-               0xd0, 0x02, 0x80, 0x07, /* hact */
-               0x65, 0x04, /* v_fsz */
-               0x01, 0x00, 0x33, 0x02, /* vsync */
-               0x2d, 0x00, 0x38, 0x04, /* vact */
-               0x33, 0x02, /* field_chg */
-               0x48, 0x02, /* vact_st2 */
-               0x00, 0x00, /* vact_st3 */
-               0x00, 0x00, /* vact_st4 */
-               0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
-               0x01, 0x00, 0x33, 0x02, /* field top/bot */
-               0x00, /* 3d FP */
+       {
+               .pixel_clock = 108000000,
+               .conf = {
+                       0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
+                       0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
+               },
        },
- };
- static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
-       .core = {
-               .h_blank = {0x18, 0x01},
-               .v2_blank = {0x65, 0x04},
-               .v1_blank = {0x2d, 0x00},
-               .v_line = {0x65, 0x04},
-               .h_line = {0x98, 0x08},
-               .hsync_pol = {0x00},
-               .vsync_pol = {0x00},
-               .int_pro_mode = {0x00},
-               .v_blank_f0 = {0xff, 0xff},
-               .v_blank_f1 = {0xff, 0xff},
-               .h_sync_start = {0x56, 0x00},
-               .h_sync_end = {0x82, 0x00},
-               .v_sync_line_bef_2 = {0x09, 0x00},
-               .v_sync_line_bef_1 = {0x04, 0x00},
-               .v_sync_line_aft_2 = {0xff, 0xff},
-               .v_sync_line_aft_1 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_2 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_1 = {0xff, 0xff},
-               .v_blank_f2 = {0xff, 0xff},
-               .v_blank_f3 = {0xff, 0xff},
-               .v_blank_f4 = {0xff, 0xff},
-               .v_blank_f5 = {0xff, 0xff},
-               .v_sync_line_aft_3 = {0xff, 0xff},
-               .v_sync_line_aft_4 = {0xff, 0xff},
-               .v_sync_line_aft_5 = {0xff, 0xff},
-               .v_sync_line_aft_6 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_3 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_4 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_5 = {0xff, 0xff},
-               .v_sync_line_aft_pxl_6 = {0xff, 0xff},
-               /* other don't care */
+       {
+               .pixel_clock = 146250000,
+               .conf = {
+                       0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
+                       0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
+                       0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
+               },
        },
-       .tg = {
-               0x00, /* cmd */
-               0x98, 0x08, /* h_fsz */
-               0x18, 0x01, 0x80, 0x07, /* hact */
-               0x65, 0x04, /* v_fsz */
-               0x01, 0x00, 0x33, 0x02, /* vsync */
-               0x2d, 0x00, 0x38, 0x04, /* vact */
-               0x33, 0x02, /* field_chg */
-               0x48, 0x02, /* vact_st2 */
-               0x00, 0x00, /* vact_st3 */
-               0x00, 0x00, /* vact_st4 */
-               0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
-               0x01, 0x00, 0x33, 0x02, /* field top/bot */
-               0x00, /* 3d FP */
+       {
+               .pixel_clock = 148500000,
+               .conf = {
+                       0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
+                       0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
+                       0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
+                       0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
+               },
        },
  };
  
- static const struct hdmi_conf hdmi_confs[] = {
-       { 720, 480, 60, false, 3, hdmiphy_conf27_027, &hdmi_conf_480p60 },
-       { 1280, 720, 50, false, 19, hdmiphy_conf74_25, &hdmi_conf_720p50 },
-       { 1280, 720, 60, false, 4, hdmiphy_conf74_25, &hdmi_conf_720p60 },
-       { 1920, 1080, 50, true, 20, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
-       { 1920, 1080, 60, true, 5, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
-       { 1920, 1080, 30, false, 34, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
-       { 1920, 1080, 50, false, 31, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
-       { 1920, 1080, 60, false, 16, hdmiphy_conf148_5, &hdmi_conf_1080p60 },
- };
  struct hdmi_infoframe {
        enum HDMI_PACKET_TYPE type;
        u8 ver;
@@@ -1275,31 -889,6 +889,6 @@@ static int hdmi_v13_conf_index(struct d
        return -EINVAL;
  }
  
- static int hdmi_v14_conf_index(struct drm_display_mode *mode)
- {
-       int i;
-       for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i)
-               if (hdmi_confs[i].width == mode->hdisplay &&
-                               hdmi_confs[i].height == mode->vdisplay &&
-                               hdmi_confs[i].vrefresh == mode->vrefresh &&
-                               hdmi_confs[i].interlace ==
-                               ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
-                                true : false))
-                       return i;
-       return -EINVAL;
- }
- static int hdmi_conf_index(struct hdmi_context *hdata,
-                          struct drm_display_mode *mode)
- {
-       if (hdata->type == HDMI_TYPE13)
-               return hdmi_v13_conf_index(mode);
-       return hdmi_v14_conf_index(mode);
- }
  static u8 hdmi_chksum(struct hdmi_context *hdata,
                        u32 start, u8 len, u32 hdr_sum)
  {
@@@ -1357,7 -946,7 +946,7 @@@ static void hdmi_reg_infoframe(struct h
                if (hdata->type == HDMI_TYPE13)
                        vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id;
                else
-                       vic = hdmi_confs[hdata->cur_conf].cea_video_id;
+                       vic = hdata->mode_conf.cea_video_id;
  
                hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
  
@@@ -1434,44 -1023,51 +1023,51 @@@ static int hdmi_v13_check_timing(struc
        return -EINVAL;
  }
  
+ static int hdmi_v14_find_phy_conf(int pixel_clock)
+ {
+       int i;
+       for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++) {
+               if (hdmiphy_v14_configs[i].pixel_clock == pixel_clock)
+                       return i;
+       }
+       DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
+       return -EINVAL;
+ }
  static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
  {
        int i;
  
-       DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
+       DRM_DEBUG_KMS("mode: xres=%d, yres=%d, refresh=%d, clock=%d, intl=%d\n",
                        check_timing->xres, check_timing->yres,
-                       check_timing->refresh, (check_timing->vmode &
-                       FB_VMODE_INTERLACED) ? true : false);
+                       check_timing->refresh, check_timing->pixclock,
+                       (check_timing->vmode & FB_VMODE_INTERLACED) ?
+                       true : false);
  
-       for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++)
-               if (hdmi_confs[i].width == check_timing->xres &&
-                       hdmi_confs[i].height == check_timing->yres &&
-                       hdmi_confs[i].vrefresh == check_timing->refresh &&
-                       hdmi_confs[i].interlace ==
-                       ((check_timing->vmode & FB_VMODE_INTERLACED) ?
-                        true : false))
-                               return 0;
-       /* TODO */
+       for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++)
+               if (hdmiphy_v14_configs[i].pixel_clock ==
+                       check_timing->pixclock)
+                       return 0;
  
        return -EINVAL;
  }
  
- static int hdmi_check_timing(void *ctx, void *timing)
+ static int hdmi_check_timing(void *ctx, struct fb_videomode *timing)
  {
        struct hdmi_context *hdata = ctx;
-       struct fb_videomode *check_timing = timing;
  
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
  
-       DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres,
-                       check_timing->yres, check_timing->refresh,
-                       check_timing->vmode);
+       DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", timing->xres,
+                       timing->yres, timing->refresh,
+                       timing->vmode);
  
        if (hdata->type == HDMI_TYPE13)
-               return hdmi_v13_check_timing(check_timing);
+               return hdmi_v13_check_timing(timing);
        else
-               return hdmi_v14_check_timing(check_timing);
+               return hdmi_v14_check_timing(timing);
  }
  
  static void hdmi_set_acr(u32 freq, u8 *acr)
@@@ -1795,9 -1391,8 +1391,8 @@@ static void hdmi_v13_timing_apply(struc
  
  static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
  {
-       const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf;
-       const struct hdmi_core_regs *core = &conf->core;
-       const struct hdmi_tg_regs *tg = &conf->tg;
+       struct hdmi_core_regs *core = &hdata->mode_conf.core;
+       struct hdmi_tg_regs *tg = &hdata->mode_conf.tg;
        int tries;
  
        /* setting core registers */
        hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
  
        /* Timing generator registers */
-       hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
-       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
-       hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d);
+       hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
+       hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
+       hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]);
  
        /* waiting for HDMIPHY's PLL to get to steady state */
        for (tries = 100; tries; --tries) {
@@@ -2029,10 -1624,17 +1624,17 @@@ static void hdmiphy_conf_apply(struct h
        }
  
        /* pixel clock */
-       if (hdata->type == HDMI_TYPE13)
+       if (hdata->type == HDMI_TYPE13) {
                hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
-       else
-               hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data;
+       } else {
+               i = hdmi_v14_find_phy_conf(hdata->mode_conf.pixel_clock);
+               if (i < 0) {
+                       DRM_ERROR("failed to find hdmiphy conf\n");
+                       return;
+               }
+               hdmiphy_data = hdmiphy_v14_configs[i].conf;
+       }
  
        memcpy(buffer, hdmiphy_data, 32);
        ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
@@@ -2100,7 -1702,7 +1702,7 @@@ static void hdmi_mode_fixup(void *ctx, 
        if (hdata->type == HDMI_TYPE13)
                index = hdmi_v13_conf_index(adjusted_mode);
        else
-               index = hdmi_v14_conf_index(adjusted_mode);
+               index = hdmi_v14_find_phy_conf(adjusted_mode->clock * 1000);
  
        /* just return if user desired mode exists. */
        if (index >= 0)
                if (hdata->type == HDMI_TYPE13)
                        index = hdmi_v13_conf_index(m);
                else
-                       index = hdmi_v14_conf_index(m);
+                       index = hdmi_v14_find_phy_conf(m->clock * 1000);
  
                if (index >= 0) {
                        struct drm_mode_object base;
                        DRM_INFO("desired mode doesn't exist so\n");
                        DRM_INFO("use the most suitable mode among modes.\n");
  
+                       DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
+                               m->hdisplay, m->vdisplay, m->vrefresh);
                        /* preserve display mode header while copying. */
                        head = adjusted_mode->head;
                        base = adjusted_mode->base;
        }
  }
  
+ static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
+ {
+       int i;
+       BUG_ON(num_bytes > 4);
+       for (i = 0; i < num_bytes; i++)
+               reg_pair[i] = (value >> (8 * i)) & 0xff;
+ }
+ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
+                       struct drm_display_mode *m)
+ {
+       struct hdmi_core_regs *core = &hdata->mode_conf.core;
+       struct hdmi_tg_regs *tg = &hdata->mode_conf.tg;
+       hdata->mode_conf.cea_video_id = drm_match_cea_mode(m);
+       hdata->mode_conf.pixel_clock = m->clock * 1000;
+       hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
+       hdmi_set_reg(core->v_line, 2, m->vtotal);
+       hdmi_set_reg(core->h_line, 2, m->htotal);
+       hdmi_set_reg(core->hsync_pol, 1,
+                       (m->flags & DRM_MODE_FLAG_NHSYNC)  ? 1 : 0);
+       hdmi_set_reg(core->vsync_pol, 1,
+                       (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
+       hdmi_set_reg(core->int_pro_mode, 1,
+                       (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
+       /*
+        * Quirk requirement for exynos 5 HDMI IP design,
+        * 2 pixels less than the actual calculation for hsync_start
+        * and end.
+        */
+       /* Following values & calculations differ for different type of modes */
+       if (m->flags & DRM_MODE_FLAG_INTERLACE) {
+               /* Interlaced Mode */
+               hdmi_set_reg(core->v_sync_line_bef_2, 2,
+                       (m->vsync_end - m->vdisplay) / 2);
+               hdmi_set_reg(core->v_sync_line_bef_1, 2,
+                       (m->vsync_start - m->vdisplay) / 2);
+               hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
+               hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
+               hdmi_set_reg(core->v_blank_f0, 2, (m->vtotal +
+                       ((m->vsync_end - m->vsync_start) * 4) + 5) / 2);
+               hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
+               hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
+               hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
+               hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2,
+                       (m->htotal / 2) + (m->hsync_start - m->hdisplay));
+               hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2,
+                       (m->htotal / 2) + (m->hsync_start - m->hdisplay));
+               hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
+               hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
+               hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
+               hdmi_set_reg(tg->vact_st3, 2, 0x0);
+               hdmi_set_reg(tg->vact_st4, 2, 0x0);
+       } else {
+               /* Progressive Mode */
+               hdmi_set_reg(core->v_sync_line_bef_2, 2,
+                       m->vsync_end - m->vdisplay);
+               hdmi_set_reg(core->v_sync_line_bef_1, 2,
+                       m->vsync_start - m->vdisplay);
+               hdmi_set_reg(core->v2_blank, 2, m->vtotal);
+               hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay);
+               hdmi_set_reg(core->v_blank_f0, 2, 0xffff);
+               hdmi_set_reg(core->v_blank_f1, 2, 0xffff);
+               hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff);
+               hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff);
+               hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff);
+               hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff);
+               hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
+               hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
+               hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
+               hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
+               hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
+       }
+       /* Following values & calculations are same irrespective of mode type */
+       hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2);
+       hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2);
+       hdmi_set_reg(core->vact_space_1, 2, 0xffff);
+       hdmi_set_reg(core->vact_space_2, 2, 0xffff);
+       hdmi_set_reg(core->vact_space_3, 2, 0xffff);
+       hdmi_set_reg(core->vact_space_4, 2, 0xffff);
+       hdmi_set_reg(core->vact_space_5, 2, 0xffff);
+       hdmi_set_reg(core->vact_space_6, 2, 0xffff);
+       hdmi_set_reg(core->v_blank_f2, 2, 0xffff);
+       hdmi_set_reg(core->v_blank_f3, 2, 0xffff);
+       hdmi_set_reg(core->v_blank_f4, 2, 0xffff);
+       hdmi_set_reg(core->v_blank_f5, 2, 0xffff);
+       hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff);
+       hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff);
+       hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff);
+       hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff);
+       hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff);
+       hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff);
+       hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff);
+       hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff);
+       /* Timing generator registers */
+       hdmi_set_reg(tg->cmd, 1, 0x0);
+       hdmi_set_reg(tg->h_fsz, 2, m->htotal);
+       hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
+       hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
+       hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
+       hdmi_set_reg(tg->vsync, 2, 0x1);
+       hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
+       hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
+       hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
+       hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
+       hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
+       hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
+       hdmi_set_reg(tg->tg_3d, 1, 0x0);
+ }
  static void hdmi_mode_set(void *ctx, void *mode)
  {
        struct hdmi_context *hdata = ctx;
  
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
  
-       conf_idx = hdmi_conf_index(hdata, mode);
-       if (conf_idx >= 0)
-               hdata->cur_conf = conf_idx;
-       else
-               DRM_DEBUG_KMS("not supported mode\n");
+       if (hdata->type == HDMI_TYPE13) {
+               conf_idx = hdmi_v13_conf_index(mode);
+               if (conf_idx >= 0)
+                       hdata->cur_conf = conf_idx;
+               else
+                       DRM_DEBUG_KMS("not supported mode\n");
+       } else {
+               hdmi_v14_mode_set(hdata, mode);
+       }
  }
  
  static void hdmi_get_max_resol(void *ctx, unsigned int *width,
@@@ -2501,9 -2226,11 +2226,9 @@@ static int hdmi_probe(struct platform_d
                return -ENOENT;
        }
  
 -      hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
 -      if (!hdata->regs) {
 -              DRM_ERROR("failed to map registers\n");
 -              return -ENXIO;
 -      }
 +      hdata->regs = devm_ioremap_resource(&pdev->dev, res);
 +      if (IS_ERR(hdata->regs))
 +              return PTR_ERR(hdata->regs);
  
        ret = devm_gpio_request(&pdev->dev, hdata->hpd_gpio, "HPD");
        if (ret) {
index 32158d21c6328e63bb7b7964e31808617a44afbd,7c65ab83914a0ce50274797b708f2b5ba35b27ee..aae31489c89304f8d79ad2319bbb0ecb97897cef
@@@ -103,7 -103,7 +103,7 @@@ static const char *cache_level_str(int 
  static void
  describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
  {
-       seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d %d%s%s%s",
+       seq_printf(m, "%p: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s",
                   &obj->base,
                   get_pin_flag(obj),
                   get_tiling_flag(obj),
        if (obj->gtt_space != NULL)
                seq_printf(m, " (gtt offset: %08x, size: %08x)",
                           obj->gtt_offset, (unsigned int)obj->gtt_space->size);
+       if (obj->stolen)
+               seq_printf(m, " (stolen: %08lx)", obj->stolen->start);
        if (obj->pin_mappable || obj->fault_mappable) {
                char s[3], *t = s;
                if (obj->pin_mappable)
@@@ -257,8 -259,9 +259,9 @@@ static int i915_gem_object_info(struct 
        seq_printf(m, "%u fault mappable objects, %zu bytes\n",
                   count, size);
  
-       seq_printf(m, "%zu [%zu] gtt total\n",
-                  dev_priv->mm.gtt_total, dev_priv->mm.mappable_gtt_total);
+       seq_printf(m, "%zu [%lu] gtt total\n",
+                  dev_priv->gtt.total,
+                  dev_priv->gtt.mappable_end - dev_priv->gtt.start);
  
        mutex_unlock(&dev->struct_mutex);
  
@@@ -388,7 -391,7 +391,7 @@@ static void i915_ring_seqno_info(struc
                                 struct intel_ring_buffer *ring)
  {
        if (ring->get_seqno) {
-               seq_printf(m, "Current sequence (%s): %d\n",
+               seq_printf(m, "Current sequence (%s): %u\n",
                           ring->name, ring->get_seqno(ring, false));
        }
  }
@@@ -545,11 -548,11 +548,11 @@@ static int i915_hws_info(struct seq_fil
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring;
-       const volatile u32 __iomem *hws;
+       const u32 *hws;
        int i;
  
        ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
-       hws = (volatile u32 __iomem *)ring->status_page.page_addr;
+       hws = ring->status_page.page_addr;
        if (hws == NULL)
                return 0;
  
@@@ -609,7 -612,7 +612,7 @@@ static void print_error_buffers(struct 
        seq_printf(m, "%s [%d]:\n", name, count);
  
        while (count--) {
-               seq_printf(m, "  %08x %8u %04x %04x %x %x%s%s%s%s%s%s%s",
+               seq_printf(m, "  %08x %8u %02x %02x %x %x%s%s%s%s%s%s%s",
                           err->gtt_offset,
                           err->size,
                           err->read_domains,
@@@ -691,7 -694,7 +694,7 @@@ static int i915_error_state(struct seq_
  
        seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
                   error->time.tv_usec);
-       seq_printf(m, "Kernel: " UTS_RELEASE);
+       seq_printf(m, "Kernel: " UTS_RELEASE "\n");
        seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
        seq_printf(m, "EIR: 0x%08x\n", error->eir);
        seq_printf(m, "IER: 0x%08x\n", error->ier);
@@@ -816,11 -819,11 +819,11 @@@ static int i915_error_state_open(struc
  
        error_priv->dev = dev;
  
-       spin_lock_irqsave(&dev_priv->error_lock, flags);
-       error_priv->error = dev_priv->first_error;
+       spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
+       error_priv->error = dev_priv->gpu_error.first_error;
        if (error_priv->error)
                kref_get(&error_priv->error->ref);
-       spin_unlock_irqrestore(&dev_priv->error_lock, flags);
+       spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
  
        return single_open(file, i915_error_state, error_priv);
  }
@@@ -846,6 -849,77 +849,77 @@@ static const struct file_operations i91
        .release = i915_error_state_release,
  };
  
+ static ssize_t
+ i915_next_seqno_read(struct file *filp,
+                char __user *ubuf,
+                size_t max,
+                loff_t *ppos)
+ {
+       struct drm_device *dev = filp->private_data;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       char buf[80];
+       int len;
+       int ret;
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+       len = snprintf(buf, sizeof(buf),
+                      "next_seqno :  0x%x\n",
+                      dev_priv->next_seqno);
+       mutex_unlock(&dev->struct_mutex);
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+       return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+ }
+ static ssize_t
+ i915_next_seqno_write(struct file *filp,
+                     const char __user *ubuf,
+                     size_t cnt,
+                     loff_t *ppos)
+ {
+       struct drm_device *dev = filp->private_data;
+       char buf[20];
+       u32 val = 1;
+       int ret;
+       if (cnt > 0) {
+               if (cnt > sizeof(buf) - 1)
+                       return -EINVAL;
+               if (copy_from_user(buf, ubuf, cnt))
+                       return -EFAULT;
+               buf[cnt] = 0;
+               ret = kstrtouint(buf, 0, &val);
+               if (ret < 0)
+                       return ret;
+       }
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+       ret = i915_gem_set_seqno(dev, val);
+       mutex_unlock(&dev->struct_mutex);
+       return ret ?: cnt;
+ }
+ static const struct file_operations i915_next_seqno_fops = {
+       .owner = THIS_MODULE,
+       .open = simple_open,
+       .read = i915_next_seqno_read,
+       .write = i915_next_seqno_write,
+       .llseek = default_llseek,
+ };
  static int i915_rstdby_delays(struct seq_file *m, void *unused)
  {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
@@@ -888,7 -962,7 +962,7 @@@ static int i915_cur_delayinfo(struct se
                u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
                u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
                u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-               u32 rpstat;
+               u32 rpstat, cagf;
                u32 rpupei, rpcurup, rpprevup;
                u32 rpdownei, rpcurdown, rpprevdown;
                int max_freq;
                rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI);
                rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
                rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
+               if (IS_HASWELL(dev))
+                       cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
+               else
+                       cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
+               cagf *= GT_FREQUENCY_MULTIPLIER;
  
                gen6_gt_force_wake_put(dev_priv);
                mutex_unlock(&dev->struct_mutex);
                           gt_perf_status & 0xff);
                seq_printf(m, "Render p-state limit: %d\n",
                           rp_state_limits & 0xff);
-               seq_printf(m, "CAGF: %dMHz\n", ((rpstat & GEN6_CAGF_MASK) >>
-                                               GEN6_CAGF_SHIFT) * GT_FREQUENCY_MULTIPLIER);
+               seq_printf(m, "CAGF: %dMHz\n", cagf);
                seq_printf(m, "RP CUR UP EI: %dus\n", rpupei &
                           GEN6_CURICONT_MASK);
                seq_printf(m, "RP CUR UP: %dus\n", rpcurup &
@@@ -1372,28 -1450,31 +1450,31 @@@ static int i915_gem_framebuffer_info(st
        ifbdev = dev_priv->fbdev;
        fb = to_intel_framebuffer(ifbdev->helper.fb);
  
-       seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, obj ",
+       seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, refcount %d, obj ",
                   fb->base.width,
                   fb->base.height,
                   fb->base.depth,
-                  fb->base.bits_per_pixel);
+                  fb->base.bits_per_pixel,
+                  atomic_read(&fb->base.refcount.refcount));
        describe_obj(m, fb->obj);
        seq_printf(m, "\n");
+       mutex_unlock(&dev->mode_config.mutex);
  
+       mutex_lock(&dev->mode_config.fb_lock);
        list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) {
                if (&fb->base == ifbdev->helper.fb)
                        continue;
  
-               seq_printf(m, "user size: %d x %d, depth %d, %d bpp, obj ",
+               seq_printf(m, "user size: %d x %d, depth %d, %d bpp, refcount %d, obj ",
                           fb->base.width,
                           fb->base.height,
                           fb->base.depth,
-                          fb->base.bits_per_pixel);
+                          fb->base.bits_per_pixel,
+                          atomic_read(&fb->base.refcount.refcount));
                describe_obj(m, fb->obj);
                seq_printf(m, "\n");
        }
-       mutex_unlock(&dev->mode_config.mutex);
+       mutex_unlock(&dev->mode_config.fb_lock);
  
        return 0;
  }
@@@ -1403,7 -1484,8 +1484,8 @@@ static int i915_context_status(struct s
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       int ret;
+       struct intel_ring_buffer *ring;
+       int ret, i;
  
        ret = mutex_lock_interruptible(&dev->mode_config.mutex);
        if (ret)
                seq_printf(m, "\n");
        }
  
+       for_each_ring(ring, dev_priv, i) {
+               if (ring->default_context) {
+                       seq_printf(m, "HW default context %s ring ", ring->name);
+                       describe_obj(m, ring->default_context->obj);
+                       seq_printf(m, "\n");
+               }
+       }
        mutex_unlock(&dev->mode_config.mutex);
  
        return 0;
@@@ -1460,7 -1550,7 +1550,7 @@@ static const char *swizzle_string(unsig
        case I915_BIT_6_SWIZZLE_9_10_17:
                return "bit9/bit10/bit17";
        case I915_BIT_6_SWIZZLE_UNKNOWN:
 -              return "unkown";
 +              return "unknown";
        }
  
        return "bug";
@@@ -1556,7 -1646,7 +1646,7 @@@ static int i915_dpio_info(struct seq_fi
                return 0;
        }
  
-       ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+       ret = mutex_lock_interruptible(&dev_priv->dpio_lock);
        if (ret)
                return ret;
  
        seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
                   intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
  
-       mutex_unlock(&dev->mode_config.mutex);
+       mutex_unlock(&dev_priv->dpio_lock);
  
        return 0;
  }
@@@ -1603,7 -1693,7 +1693,7 @@@ i915_wedged_read(struct file *filp
  
        len = snprintf(buf, sizeof(buf),
                       "wedged :  %d\n",
-                      atomic_read(&dev_priv->mm.wedged));
+                      atomic_read(&dev_priv->gpu_error.reset_counter));
  
        if (len > sizeof(buf))
                len = sizeof(buf);
@@@ -1658,7 -1748,7 +1748,7 @@@ i915_ring_stop_read(struct file *filp
        int len;
  
        len = snprintf(buf, sizeof(buf),
-                      "0x%08x\n", dev_priv->stop_rings);
+                      "0x%08x\n", dev_priv->gpu_error.stop_rings);
  
        if (len > sizeof(buf))
                len = sizeof(buf);
@@@ -1694,7 -1784,7 +1784,7 @@@ i915_ring_stop_write(struct file *filp
        if (ret)
                return ret;
  
-       dev_priv->stop_rings = val;
+       dev_priv->gpu_error.stop_rings = val;
        mutex_unlock(&dev->struct_mutex);
  
        return cnt;
@@@ -1708,6 -1798,102 +1798,102 @@@ static const struct file_operations i91
        .llseek = default_llseek,
  };
  
+ #define DROP_UNBOUND 0x1
+ #define DROP_BOUND 0x2
+ #define DROP_RETIRE 0x4
+ #define DROP_ACTIVE 0x8
+ #define DROP_ALL (DROP_UNBOUND | \
+                 DROP_BOUND | \
+                 DROP_RETIRE | \
+                 DROP_ACTIVE)
+ static ssize_t
+ i915_drop_caches_read(struct file *filp,
+                     char __user *ubuf,
+                     size_t max,
+                     loff_t *ppos)
+ {
+       char buf[20];
+       int len;
+       len = snprintf(buf, sizeof(buf), "0x%08x\n", DROP_ALL);
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+       return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+ }
+ static ssize_t
+ i915_drop_caches_write(struct file *filp,
+                      const char __user *ubuf,
+                      size_t cnt,
+                      loff_t *ppos)
+ {
+       struct drm_device *dev = filp->private_data;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_gem_object *obj, *next;
+       char buf[20];
+       int val = 0, ret;
+       if (cnt > 0) {
+               if (cnt > sizeof(buf) - 1)
+                       return -EINVAL;
+               if (copy_from_user(buf, ubuf, cnt))
+                       return -EFAULT;
+               buf[cnt] = 0;
+               val = simple_strtoul(buf, NULL, 0);
+       }
+       DRM_DEBUG_DRIVER("Dropping caches: 0x%08x\n", val);
+       /* No need to check and wait for gpu resets, only libdrm auto-restarts
+        * on ioctls on -EAGAIN. */
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+       if (val & DROP_ACTIVE) {
+               ret = i915_gpu_idle(dev);
+               if (ret)
+                       goto unlock;
+       }
+       if (val & (DROP_RETIRE | DROP_ACTIVE))
+               i915_gem_retire_requests(dev);
+       if (val & DROP_BOUND) {
+               list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list, mm_list)
+                       if (obj->pin_count == 0) {
+                               ret = i915_gem_object_unbind(obj);
+                               if (ret)
+                                       goto unlock;
+                       }
+       }
+       if (val & DROP_UNBOUND) {
+               list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list)
+                       if (obj->pages_pin_count == 0) {
+                               ret = i915_gem_object_put_pages(obj);
+                               if (ret)
+                                       goto unlock;
+                       }
+       }
+ unlock:
+       mutex_unlock(&dev->struct_mutex);
+       return ret ?: cnt;
+ }
+ static const struct file_operations i915_drop_caches_fops = {
+       .owner = THIS_MODULE,
+       .open = simple_open,
+       .read = i915_drop_caches_read,
+       .write = i915_drop_caches_write,
+       .llseek = default_llseek,
+ };
  static ssize_t
  i915_max_freq_read(struct file *filp,
                   char __user *ubuf,
@@@ -2104,12 -2290,24 +2290,24 @@@ int i915_debugfs_init(struct drm_minor 
        if (ret)
                return ret;
  
+       ret = i915_debugfs_create(minor->debugfs_root, minor,
+                                 "i915_gem_drop_caches",
+                                 &i915_drop_caches_fops);
+       if (ret)
+               return ret;
        ret = i915_debugfs_create(minor->debugfs_root, minor,
                                  "i915_error_state",
                                  &i915_error_state_fops);
        if (ret)
                return ret;
  
+       ret = i915_debugfs_create(minor->debugfs_root, minor,
+                                "i915_next_seqno",
+                                &i915_next_seqno_fops);
+       if (ret)
+               return ret;
        return drm_debugfs_create_files(i915_debugfs_list,
                                        I915_DEBUGFS_ENTRIES,
                                        minor->debugfs_root, minor);
@@@ -2129,10 -2327,14 +2327,14 @@@ void i915_debugfs_cleanup(struct drm_mi
                                 1, minor);
        drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops,
                                 1, minor);
+       drm_debugfs_remove_files((struct drm_info_list *) &i915_drop_caches_fops,
+                                1, minor);
        drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops,
                                 1, minor);
        drm_debugfs_remove_files((struct drm_info_list *) &i915_error_state_fops,
                                 1, minor);
+       drm_debugfs_remove_files((struct drm_info_list *) &i915_next_seqno_fops,
+                                1, minor);
  }
  
  #endif /* CONFIG_DEBUG_FS */
index 106bb19fdd9a65ee12b0c92241ea5045a4b692ac,6a902672f6f47e321f1a9c3b334f67b0e308a508..62e68baef087b17b48fefb0b0478716c75f28b09
@@@ -50,13 -50,10 +50,13 @@@ int  nouveau_object_fini(struct nouveau
  
  extern struct nouveau_ofuncs nouveau_object_ofuncs;
  
 +/* Don't allocate dynamically, because lockdep needs lock_class_keys to be in
 + * ".data". */
  struct nouveau_oclass {
        u32 handle;
 -      struct nouveau_ofuncs *ofuncs;
 -      struct nouveau_omthds *omthds;
 +      struct nouveau_ofuncs * const ofuncs;
 +      struct nouveau_omthds * const omthds;
 +      struct lock_class_key lock_class_key;
  };
  
  #define nv_oclass(o)    nv_object(o)->oclass
@@@ -136,7 -133,7 +136,7 @@@ static inline u
  nv_ro08(void *obj, u64 addr)
  {
        u8 data = nv_ofuncs(obj)->rd08(obj, addr);
-       nv_spam(obj, "nv_ro08 0x%08x 0x%02x\n", addr, data);
+       nv_spam(obj, "nv_ro08 0x%08llx 0x%02x\n", addr, data);
        return data;
  }
  
@@@ -144,7 -141,7 +144,7 @@@ static inline u1
  nv_ro16(void *obj, u64 addr)
  {
        u16 data = nv_ofuncs(obj)->rd16(obj, addr);
-       nv_spam(obj, "nv_ro16 0x%08x 0x%04x\n", addr, data);
+       nv_spam(obj, "nv_ro16 0x%08llx 0x%04x\n", addr, data);
        return data;
  }
  
@@@ -152,28 -149,28 +152,28 @@@ static inline u3
  nv_ro32(void *obj, u64 addr)
  {
        u32 data = nv_ofuncs(obj)->rd32(obj, addr);
-       nv_spam(obj, "nv_ro32 0x%08x 0x%08x\n", addr, data);
+       nv_spam(obj, "nv_ro32 0x%08llx 0x%08x\n", addr, data);
        return data;
  }
  
  static inline void
  nv_wo08(void *obj, u64 addr, u8 data)
  {
-       nv_spam(obj, "nv_wo08 0x%08x 0x%02x\n", addr, data);
+       nv_spam(obj, "nv_wo08 0x%08llx 0x%02x\n", addr, data);
        nv_ofuncs(obj)->wr08(obj, addr, data);
  }
  
  static inline void
  nv_wo16(void *obj, u64 addr, u16 data)
  {
-       nv_spam(obj, "nv_wo16 0x%08x 0x%04x\n", addr, data);
+       nv_spam(obj, "nv_wo16 0x%08llx 0x%04x\n", addr, data);
        nv_ofuncs(obj)->wr16(obj, addr, data);
  }
  
  static inline void
  nv_wo32(void *obj, u64 addr, u32 data)
  {
-       nv_spam(obj, "nv_wo32 0x%08x 0x%08x\n", addr, data);
+       nv_spam(obj, "nv_wo32 0x%08llx 0x%08x\n", addr, data);
        nv_ofuncs(obj)->wr32(obj, addr, data);
  }
  
index eac236ed19b251042ea3bfe1ef75d6da6856d188,a4338d92b02e45bd2d561c64c50821a3d88d9b7c..0772ec978165151070ee046553a8b5e754aef49d
   * Authors: Ben Skeggs
   */
  
- #include <core/object.h>
+ #include <core/client.h>
  #include <core/enum.h>
+ #include <core/engctx.h>
+ #include <core/object.h>
  
  #include <subdev/fb.h>
  #include <subdev/bios.h>
@@@ -99,7 -101,7 +101,7 @@@ nv50_fb_vram_init(struct nouveau_fb *pf
        struct nouveau_bios *bios = nouveau_bios(device);
        const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
        const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
 -      u32 size;
 +      u32 size, tags = 0;
        int ret;
  
        pfb->ram.size = nv_rd32(pfb, 0x10020c);
                        return ret;
  
                pfb->ram.ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1;
 +              tags = nv_rd32(pfb, 0x100320);
                break;
        }
  
 -      return nv_rd32(pfb, 0x100320);
 +      return tags;
  }
  
  static int
@@@ -303,17 -304,18 +305,18 @@@ static const struct nouveau_enum vm_cli
  };
  
  static const struct nouveau_enum vm_engine[] = {
-       { 0x00000000, "PGRAPH", NULL },
-       { 0x00000001, "PVP", NULL },
+       { 0x00000000, "PGRAPH", NULL, NVDEV_ENGINE_GR },
+       { 0x00000001, "PVP", NULL, NVDEV_ENGINE_VP },
        { 0x00000004, "PEEPHOLE", NULL },
-       { 0x00000005, "PFIFO", vm_pfifo_subclients },
+       { 0x00000005, "PFIFO", vm_pfifo_subclients, NVDEV_ENGINE_FIFO },
        { 0x00000006, "BAR", vm_bar_subclients },
-       { 0x00000008, "PPPP", NULL },
-       { 0x00000009, "PBSP", NULL },
-       { 0x0000000a, "PCRYPT", NULL },
+       { 0x00000008, "PPPP", NULL, NVDEV_ENGINE_PPP },
+       { 0x00000008, "PMPEG", NULL, NVDEV_ENGINE_MPEG },
+       { 0x00000009, "PBSP", NULL, NVDEV_ENGINE_BSP },
+       { 0x0000000a, "PCRYPT", NULL, NVDEV_ENGINE_CRYPT },
        { 0x0000000b, "PCOUNTER", NULL },
        { 0x0000000c, "SEMAPHORE_BG", NULL },
-       { 0x0000000d, "PCOPY", NULL },
+       { 0x0000000d, "PCOPY", NULL, NVDEV_ENGINE_COPY0 },
        { 0x0000000e, "PDAEMON", NULL },
        {}
  };
@@@ -335,8 -337,10 +338,10 @@@ static voi
  nv50_fb_intr(struct nouveau_subdev *subdev)
  {
        struct nouveau_device *device = nv_device(subdev);
+       struct nouveau_engine *engine;
        struct nv50_fb_priv *priv = (void *)subdev;
        const struct nouveau_enum *en, *cl;
+       struct nouveau_object *engctx = NULL;
        u32 trap[6], idx, chan;
        u8 st0, st1, st2, st3;
        int i;
        }
        chan = (trap[2] << 16) | trap[1];
  
-       nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x ",
+       en = nouveau_enum_find(vm_engine, st0);
+       if (en && en->data2) {
+               const struct nouveau_enum *orig_en = en;
+               while (en->name && en->value == st0 && en->data2) {
+                       engine = nouveau_engine(subdev, en->data2);
+                       if (engine) {
+                               engctx = nouveau_engctx_get(engine, chan);
+                               if (engctx)
+                                       break;
+                       }
+                       en++;
+               }
+               if (!engctx)
+                       en = orig_en;
+       }
+       nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x [%s] ",
                 (trap[5] & 0x00000100) ? "read" : "write",
-                trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan);
+                trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan,
+                nouveau_client_name(engctx));
+       nouveau_engctx_put(engctx);
  
-       en = nouveau_enum_find(vm_engine, st0);
        if (en)
-               printk("%s/", en->name);
+               pr_cont("%s/", en->name);
        else
-               printk("%02x/", st0);
+               pr_cont("%02x/", st0);
  
        cl = nouveau_enum_find(vm_client, st2);
        if (cl)
-               printk("%s/", cl->name);
+               pr_cont("%s/", cl->name);
        else
-               printk("%02x/", st2);
+               pr_cont("%02x/", st2);
  
        if      (cl && cl->data) cl = nouveau_enum_find(cl->data, st3);
        else if (en && en->data) cl = nouveau_enum_find(en->data, st3);
        else                     cl = NULL;
        if (cl)
-               printk("%s", cl->name);
+               pr_cont("%s", cl->name);
        else
-               printk("%02x", st3);
+               pr_cont("%02x", st3);
  
-       printk(" reason: ");
+       pr_cont(" reason: ");
        en = nouveau_enum_find(vm_fault, st1);
        if (en)
-               printk("%s\n", en->name);
+               pr_cont("%s\n", en->name);
        else
-               printk("0x%08x\n", st1);
+               pr_cont("0x%08x\n", st1);
  }
  
  static int
index 5e7aef23825a0d33f08addfdcb97cc8e663f62b8,8a03c58ae9882a0c435097d969e1d0678362c64d..d1099365bfc1f47d6aa1be0e640f66c3fb66fcf2
@@@ -34,6 -34,8 +34,8 @@@
  #include <subdev/device.h>
  #include <subdev/vm.h>
  
+ #include <engine/disp.h>
  #include "nouveau_drm.h"
  #include "nouveau_irq.h"
  #include "nouveau_dma.h"
@@@ -48,6 -50,7 +50,7 @@@
  #include "nouveau_abi16.h"
  #include "nouveau_fbcon.h"
  #include "nouveau_fence.h"
+ #include "nouveau_debugfs.h"
  
  MODULE_PARM_DESC(config, "option string to pass to driver core");
  static char *nouveau_config;
@@@ -68,6 -71,32 +71,32 @@@ module_param_named(modeset, nouveau_mod
  
  static struct drm_driver driver;
  
+ static int
+ nouveau_drm_vblank_enable(struct drm_device *dev, int head)
+ {
+       struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_disp *pdisp = nouveau_disp(drm->device);
+       nouveau_event_get(pdisp->vblank, head, &drm->vblank);
+       return 0;
+ }
+ static void
+ nouveau_drm_vblank_disable(struct drm_device *dev, int head)
+ {
+       struct nouveau_drm *drm = nouveau_drm(dev);
+       struct nouveau_disp *pdisp = nouveau_disp(drm->device);
+       nouveau_event_put(pdisp->vblank, head, &drm->vblank);
+ }
+ static int
+ nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
+ {
+       struct nouveau_drm *drm =
+               container_of(event, struct nouveau_drm, vblank);
+       drm_handle_vblank(drm->dev, head);
+       return NVKM_EVENT_KEEP;
+ }
  static u64
  nouveau_name(struct pci_dev *pdev)
  {
@@@ -132,7 -161,8 +161,8 @@@ nouveau_accel_init(struct nouveau_drm *
  
        /* initialise synchronisation routines */
        if      (device->card_type < NV_10) ret = nv04_fence_create(drm);
-       else if (device->card_type < NV_50) ret = nv10_fence_create(drm);
+       else if (device->chipset   <  0x17) ret = nv10_fence_create(drm);
+       else if (device->card_type < NV_50) ret = nv17_fence_create(drm);
        else if (device->chipset   <  0x84) ret = nv50_fence_create(drm);
        else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);
        else                                ret = nvc0_fence_create(drm);
@@@ -245,8 -275,6 +275,8 @@@ static int nouveau_drm_probe(struct pci
        return 0;
  }
  
 +static struct lock_class_key drm_client_lock_class_key;
 +
  static int
  nouveau_drm_load(struct drm_device *dev, unsigned long flags)
  {
        ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm);
        if (ret)
                return ret;
 +      lockdep_set_class(&drm->client.mutex, &drm_client_lock_class_key);
  
        dev->dev_private = drm;
        drm->dev = dev;
+       drm->vblank.func = nouveau_drm_vblank_handler;
  
        INIT_LIST_HEAD(&drm->clients);
        spin_lock_init(&drm->tile.lock);
@@@ -401,7 -429,7 +432,7 @@@ nouveau_drm_remove(struct pci_dev *pdev
        nouveau_object_debug();
  }
  
- int
static int
  nouveau_do_suspend(struct drm_device *dev)
  {
        struct nouveau_drm *drm = nouveau_drm(dev);
@@@ -472,7 -500,7 +503,7 @@@ int nouveau_pmops_suspend(struct devic
        return 0;
  }
  
- int
static int
  nouveau_do_resume(struct drm_device *dev)
  {
        struct nouveau_drm *drm = nouveau_drm(dev);
@@@ -546,10 -574,11 +577,11 @@@ nouveau_drm_open(struct drm_device *dev
        struct pci_dev *pdev = dev->pdev;
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_cli *cli;
-       char name[16];
+       char name[32], tmpname[TASK_COMM_LEN];
        int ret;
  
-       snprintf(name, sizeof(name), "%d", pid_nr(fpriv->pid));
+       get_task_comm(tmpname, current);
+       snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
  
        ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli);
        if (ret)
@@@ -639,22 -668,32 +671,32 @@@ driver = 
        .postclose = nouveau_drm_postclose,
        .lastclose = nouveau_vga_lastclose,
  
+ #if defined(CONFIG_DEBUG_FS)
+       .debugfs_init = nouveau_debugfs_init,
+       .debugfs_cleanup = nouveau_debugfs_takedown,
+ #endif
        .irq_preinstall = nouveau_irq_preinstall,
        .irq_postinstall = nouveau_irq_postinstall,
        .irq_uninstall = nouveau_irq_uninstall,
        .irq_handler = nouveau_irq_handler,
  
        .get_vblank_counter = drm_vblank_count,
-       .enable_vblank = nouveau_vblank_enable,
-       .disable_vblank = nouveau_vblank_disable,
+       .enable_vblank = nouveau_drm_vblank_enable,
+       .disable_vblank = nouveau_drm_vblank_disable,
  
        .ioctls = nouveau_ioctls,
        .fops = &nouveau_driver_fops,
  
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
-       .gem_prime_export = nouveau_gem_prime_export,
-       .gem_prime_import = nouveau_gem_prime_import,
+       .gem_prime_export = drm_gem_prime_export,
+       .gem_prime_import = drm_gem_prime_import,
+       .gem_prime_pin = nouveau_gem_prime_pin,
+       .gem_prime_get_sg_table = nouveau_gem_prime_get_sg_table,
+       .gem_prime_import_sg_table = nouveau_gem_prime_import_sg_table,
+       .gem_prime_vmap = nouveau_gem_prime_vmap,
+       .gem_prime_vunmap = nouveau_gem_prime_vunmap,
  
        .gem_init_object = nouveau_gem_object_new,
        .gem_free_object = nouveau_gem_object_del,
index 09f65dc3d2c85397e4147e51291c1b7510450d03,b724a41314359053d598176e7ac871ba3a63704e..09f65dc3d2c85397e4147e51291c1b7510450d03
@@@ -3,8 -3,8 +3,8 @@@ config DRM_OMA
        tristate "OMAP DRM"
        depends on DRM && !CONFIG_FB_OMAP2
        depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
 +      depends on OMAP2_DSS
        select DRM_KMS_HELPER
 -      select OMAP2_DSS
        select FB_SYS_FILLRECT
        select FB_SYS_COPYAREA
        select FB_SYS_IMAGEBLIT
index 8979c80adb5febac4e5a49c1ed3fd4480ea1930f,44284fd981fc0824b3bd5c6b6e0d583c03d5f72a..c451c41a7a7d2f5b2333dc2217a2adc2db061ecc
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * drivers/staging/omapdrm/omap_connector.c
+  * drivers/gpu/drm/omapdrm/omap_connector.c
   *
   * Copyright (C) 2011 Texas Instruments
   * Author: Rob Clark <rob@ti.com>
@@@ -261,8 -261,10 +261,8 @@@ struct drm_connector *omap_connector_in
        omap_dss_get_device(dssdev);
  
        omap_connector = kzalloc(sizeof(struct omap_connector), GFP_KERNEL);
 -      if (!omap_connector) {
 -              dev_err(dev->dev, "could not allocate connector\n");
 +      if (!omap_connector)
                goto fail;
 -      }
  
        omap_connector->dssdev = dssdev;
        omap_connector->encoder = encoder;
index 32109c09357c8c544abb6cb1ef991843d4b0d53d,ac2258f59805968e65cde237a3134de6b92bd89b..bec66a490b8f7ded93ff3f766c562a8a76967f2e
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * drivers/staging/omapdrm/omap_crtc.c
+  * drivers/gpu/drm/omapdrm/omap_crtc.c
   *
   * Copyright (C) 2011 Texas Instruments
   * Author: Rob Clark <rob@ti.com>
@@@ -274,17 -274,16 +274,16 @@@ static void page_flip_worker(struct wor
        struct omap_crtc *omap_crtc =
                        container_of(work, struct omap_crtc, page_flip_work);
        struct drm_crtc *crtc = &omap_crtc->base;
-       struct drm_device *dev = crtc->dev;
        struct drm_display_mode *mode = &crtc->mode;
        struct drm_gem_object *bo;
  
-       mutex_lock(&dev->mode_config.mutex);
+       mutex_lock(&crtc->mutex);
        omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        crtc->x << 16, crtc->y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16,
                        vblank_cb, crtc);
-       mutex_unlock(&dev->mode_config.mutex);
+       mutex_unlock(&crtc->mutex);
  
        bo = omap_framebuffer_bo(crtc->fb, 0);
        drm_gem_object_unreference_unlocked(bo);
@@@ -417,7 -416,7 +416,7 @@@ static void apply_worker(struct work_st
         * the callbacks and list modification all serialized
         * with respect to modesetting ioctls from userspace.
         */
-       mutex_lock(&dev->mode_config.mutex);
+       mutex_lock(&crtc->mutex);
        dispc_runtime_get();
  
        /*
  
  out:
        dispc_runtime_put();
-       mutex_unlock(&dev->mode_config.mutex);
+       mutex_unlock(&crtc->mutex);
  }
  
  int omap_crtc_apply(struct drm_crtc *crtc,
                struct omap_drm_apply *apply)
  {
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
  
-       WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+       WARN_ON(!mutex_is_locked(&crtc->mutex));
  
        /* no need to queue it again if it is already queued: */
        if (apply->queued)
@@@ -601,8 -599,11 +599,8 @@@ struct drm_crtc *omap_crtc_init(struct 
        DBG("%s", channel_names[channel]);
  
        omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
 -
 -      if (!omap_crtc) {
 -              dev_err(dev->dev, "could not allocate CRTC\n");
 +      if (!omap_crtc)
                goto fail;
 -      }
  
        crtc = &omap_crtc->base;
  
index 9b794c933c811dde3289f760be63bf1e026cd71c,3910215371053037aff61580939cd8596298e9eb..9b794c933c811dde3289f760be63bf1e026cd71c
@@@ -581,8 -581,10 +581,8 @@@ static int omap_dmm_probe(struct platfo
        struct resource *mem;
  
        omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
 -      if (!omap_dmm) {
 -              dev_err(&dev->dev, "failed to allocate driver data section\n");
 +      if (!omap_dmm)
                goto fail;
 -      }
  
        /* initialize lists */
        INIT_LIST_HEAD(&omap_dmm->alloc_head);
        }
  
        /* alloc engines */
 -      omap_dmm->engines = kzalloc(
 -                      omap_dmm->num_engines * sizeof(struct refill_engine),
 -                      GFP_KERNEL);
 +      omap_dmm->engines = kcalloc(omap_dmm->num_engines,
 +                                  sizeof(struct refill_engine), GFP_KERNEL);
        if (!omap_dmm->engines) {
 -              dev_err(&dev->dev, "could not allocate engines\n");
                ret = -ENOMEM;
                goto fail;
        }
                list_add(&omap_dmm->engines[i].idle_node, &omap_dmm->idle_head);
        }
  
 -      omap_dmm->tcm = kzalloc(omap_dmm->num_lut * sizeof(*omap_dmm->tcm),
 +      omap_dmm->tcm = kcalloc(omap_dmm->num_lut, sizeof(*omap_dmm->tcm),
                                GFP_KERNEL);
        if (!omap_dmm->tcm) {
 -              dev_err(&dev->dev, "failed to allocate lut ptrs\n");
                ret = -ENOMEM;
                goto fail;
        }
index 480dc343446cc59aca8d6101684ac574e69a5459,9083538bd16a8d0017fed2ad1fce4df5356acd62..079c54c6f94c974c966a32524cbd95210ed2572f
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * drivers/staging/omapdrm/omap_drv.c
+  * drivers/gpu/drm/omapdrm/omap_drv.c
   *
   * Copyright (C) 2011 Texas Instruments
   * Author: Rob Clark <rob@ti.com>
@@@ -335,8 -335,10 +335,8 @@@ static int dev_load(struct drm_device *
        DBG("load: dev=%p", dev);
  
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 -      if (!priv) {
 -              dev_err(dev->dev, "could not allocate priv\n");
 +      if (!priv)
                return -ENOMEM;
 -      }
  
        priv->omaprev = pdata->omaprev;
  
@@@ -452,9 -454,9 +452,9 @@@ static void dev_lastclose(struct drm_de
                }
        }
  
-       mutex_lock(&dev->mode_config.mutex);
+       drm_modeset_lock_all(dev);
        ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
-       mutex_unlock(&dev->mode_config.mutex);
+       drm_modeset_unlock_all(dev);
        if (ret)
                DBG("failed to restore crtc mode");
  }
index 25fc0c7b4f6dd314a1155e8394b888347555b0e0,7e1f2ab653729edc653438d43eca1619e8c49011..21d126d0317ebc31ad5b28938ac1ef0452e6bbe1
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * drivers/staging/omapdrm/omap_encoder.c
+  * drivers/gpu/drm/omapdrm/omap_encoder.c
   *
   * Copyright (C) 2011 Texas Instruments
   * Author: Rob Clark <rob@ti.com>
@@@ -147,8 -147,10 +147,8 @@@ struct drm_encoder *omap_encoder_init(s
        struct omap_encoder *omap_encoder;
  
        omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL);
 -      if (!omap_encoder) {
 -              dev_err(dev->dev, "could not allocate encoder\n");
 +      if (!omap_encoder)
                goto fail;
 -      }
  
        omap_encoder->dssdev = dssdev;
  
index bb4969942148e67d785b48126d515220c9689d81,9d5f6f696c7275457abf6a34ddc1ec12b76fe04e..8031402e79516ac984ae24c4ca6ec6e74e2dc663
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * drivers/staging/omapdrm/omap_fb.c
+  * drivers/gpu/drm/omapdrm/omap_fb.c
   *
   * Copyright (C) 2011 Texas Instruments
   * Author: Rob Clark <rob@ti.com>
@@@ -418,19 -418,12 +418,11 @@@ struct drm_framebuffer *omap_framebuffe
  
        omap_fb = kzalloc(sizeof(*omap_fb), GFP_KERNEL);
        if (!omap_fb) {
 -              dev_err(dev->dev, "could not allocate fb\n");
                ret = -ENOMEM;
                goto fail;
        }
  
        fb = &omap_fb->base;
-       ret = drm_framebuffer_init(dev, fb, &omap_framebuffer_funcs);
-       if (ret) {
-               dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
-               goto fail;
-       }
-       DBG("create: FB ID: %d (%p)", fb->base.id, fb);
        omap_fb->format = format;
  
        for (i = 0; i < n; i++) {
  
        drm_helper_mode_fill_fb_struct(fb, mode_cmd);
  
+       ret = drm_framebuffer_init(dev, fb, &omap_framebuffer_funcs);
+       if (ret) {
+               dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
+               goto fail;
+       }
+       DBG("create: FB ID: %d (%p)", fb->base.id, fb);
        return fb;
  
  fail:
index 70f2d6ed2ed37a9ec0060fbb8dd9370d50b71b9e,f0033bd3e4ae3b46249e9ee171326736481a24cf..b11ce609fcc218894471b9da564df2943b2cfa06
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * drivers/staging/omapdrm/omap_fbdev.c
+  * drivers/gpu/drm/omapdrm/omap_fbdev.c
   *
   * Copyright (C) 2011 Texas Instruments
   * Author: Rob Clark <rob@ti.com>
@@@ -131,9 -131,6 +131,6 @@@ static struct fb_ops omap_fb_ops = 
        .fb_pan_display = omap_fbdev_pan_display,
        .fb_blank = drm_fb_helper_blank,
        .fb_setcmap = drm_fb_helper_setcmap,
-       .fb_debug_enter = drm_fb_helper_debug_enter,
-       .fb_debug_leave = drm_fb_helper_debug_leave,
  };
  
  static int omap_fbdev_create(struct drm_fb_helper *helper,
@@@ -275,8 -272,10 +272,10 @@@ fail
        if (ret) {
                if (fbi)
                        framebuffer_release(fbi);
-               if (fb)
+               if (fb) {
+                       drm_framebuffer_unregister_private(fb);
                        drm_framebuffer_remove(fb);
+               }
        }
  
        return ret;
@@@ -294,25 -293,10 +293,10 @@@ static void omap_crtc_fb_gamma_get(stru
        DBG("fbdev: get gamma");
  }
  
- static int omap_fbdev_probe(struct drm_fb_helper *helper,
-               struct drm_fb_helper_surface_size *sizes)
- {
-       int new_fb = 0;
-       int ret;
-       if (!helper->fb) {
-               ret = omap_fbdev_create(helper, sizes);
-               if (ret)
-                       return ret;
-               new_fb = 1;
-       }
-       return new_fb;
- }
  static struct drm_fb_helper_funcs omap_fb_helper_funcs = {
        .gamma_set = omap_crtc_fb_gamma_set,
        .gamma_get = omap_crtc_fb_gamma_get,
-       .fb_probe = omap_fbdev_probe,
+       .fb_probe = omap_fbdev_create,
  };
  
  static struct drm_fb_helper *get_fb(struct fb_info *fbi)
@@@ -348,8 -332,10 +332,8 @@@ struct drm_fb_helper *omap_fbdev_init(s
        int ret = 0;
  
        fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
 -      if (!fbdev) {
 -              dev_err(dev->dev, "could not allocate fbdev\n");
 +      if (!fbdev)
                goto fail;
 -      }
  
        INIT_WORK(&fbdev->work, pan_worker);
  
        }
  
        drm_fb_helper_single_add_all_connectors(helper);
+       /* disable all the possible outputs/crtcs before entering KMS mode */
+       drm_helper_disable_unused_functions(dev);
        drm_fb_helper_initial_config(helper, 32);
  
        priv->fbdev = helper;
@@@ -398,8 -388,10 +386,10 @@@ void omap_fbdev_free(struct drm_device 
        fbdev = to_omap_fbdev(priv->fbdev);
  
        /* this will free the backing object */
-       if (fbdev->fb)
+       if (fbdev->fb) {
+               drm_framebuffer_unregister_private(fbdev->fb);
                drm_framebuffer_remove(fbdev->fb);
+       }
  
        kfree(fbdev);
  
index 518d03d4d4f3ea91aa985f990a0bfd52a2dcc109,e8302b02691d5d0a5c0fa345e49f4000aa293611..ebbdf4132e9cb2175fabd6422ac17365eaa10d4a
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * drivers/staging/omapdrm/omap_gem.c
+  * drivers/gpu/drm/omapdrm/omap_gem.c
   *
   * Copyright (C) 2011 Texas Instruments
   * Author: Rob Clark <rob.clark@linaro.org>
@@@ -1402,8 -1402,10 +1402,8 @@@ struct drm_gem_object *omap_gem_new(str
        }
  
        omap_obj = kzalloc(sizeof(*omap_obj), GFP_KERNEL);
 -      if (!omap_obj) {
 -              dev_err(dev->dev, "could not allocate GEM object\n");
 +      if (!omap_obj)
                goto fail;
 -      }
  
        list_add(&omap_obj->mm_list, &priv->obj_list);
  
@@@ -1459,9 -1461,11 +1459,9 @@@ void omap_gem_init(struct drm_device *d
                return;
        }
  
 -      usergart = kzalloc(3 * sizeof(*usergart), GFP_KERNEL);
 -      if (!usergart) {
 -              dev_warn(dev->dev, "could not allocate usergart\n");
 +      usergart = kcalloc(3, sizeof(*usergart), GFP_KERNEL);
 +      if (!usergart)
                return;
 -      }
  
        /* reserve 4k aligned/wide regions for userspace mappings: */
        for (i = 0; i < ARRAY_SIZE(fmts); i++) {
index c063476db3bb23397f686af3048ab2bf3cddc344,dd68d14ce61588c1c0ca3f4f4f227a7bf9a06ba4..2882cda6ea19de38039f498a9a7fa31e488d92c7
@@@ -1,5 -1,5 +1,5 @@@
  /*
-  * drivers/staging/omapdrm/omap_plane.c
+  * drivers/gpu/drm/omapdrm/omap_plane.c
   *
   * Copyright (C) 2011 Texas Instruments
   * Author: Rob Clark <rob.clark@linaro.org>
@@@ -390,8 -390,10 +390,8 @@@ struct drm_plane *omap_plane_init(struc
        DBG("%s: priv=%d", plane_names[id], private_plane);
  
        omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
 -      if (!omap_plane) {
 -              dev_err(dev->dev, "could not allocate plane\n");
 +      if (!omap_plane)
                goto fail;
 -      }
  
        ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL);
        if (ret) {
index ee4cff534f100dae84d64bff2122b9b2bc89a9aa,d8f5d5fcd303f68e1a71694dd067f26adb8caddb..99fb13286fd02d3393ff09e28b9c10e91cb9d9e7
@@@ -36,9 -36,6 +36,6 @@@
  
  int r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
                           struct radeon_cs_reloc **cs_reloc);
- static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
-                                         struct radeon_cs_reloc **cs_reloc);
  struct evergreen_cs_track {
        u32                     group_size;
        u32                     nbanks;
@@@ -1009,223 -1006,35 +1006,35 @@@ static int evergreen_cs_track_check(str
  }
  
  /**
-  * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet
-  * @parser:   parser structure holding parsing context.
-  * @pkt:      where to store packet informations
-  *
-  * Assume that chunk_ib_index is properly set. Will return -EINVAL
-  * if packet is bigger than remaining ib size. or if packets is unknown.
-  **/
- static int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
-                             struct radeon_cs_packet *pkt,
-                             unsigned idx)
- {
-       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
-       uint32_t header;
-       if (idx >= ib_chunk->length_dw) {
-               DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
-                         idx, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       header = radeon_get_ib_value(p, idx);
-       pkt->idx = idx;
-       pkt->type = CP_PACKET_GET_TYPE(header);
-       pkt->count = CP_PACKET_GET_COUNT(header);
-       pkt->one_reg_wr = 0;
-       switch (pkt->type) {
-       case PACKET_TYPE0:
-               pkt->reg = CP_PACKET0_GET_REG(header);
-               break;
-       case PACKET_TYPE3:
-               pkt->opcode = CP_PACKET3_GET_OPCODE(header);
-               break;
-       case PACKET_TYPE2:
-               pkt->count = -1;
-               break;
-       default:
-               DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
-               return -EINVAL;
-       }
-       if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
-               DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
-                         pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       return 0;
- }
- /**
-  * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3
+  * evergreen_cs_packet_parse_vline() - parse userspace VLINE packet
   * @parser:           parser structure holding parsing context.
-  * @data:             pointer to relocation data
-  * @offset_start:     starting offset
-  * @offset_mask:      offset mask (to align start offset on)
-  * @reloc:            reloc informations
   *
-  * Check next packet is relocation packet3, do bo validation and compute
-  * GPU offset using the provided start.
-  **/
- static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
-                                         struct radeon_cs_reloc **cs_reloc)
- {
-       struct radeon_cs_chunk *relocs_chunk;
-       struct radeon_cs_packet p3reloc;
-       unsigned idx;
-       int r;
-       if (p->chunk_relocs_idx == -1) {
-               DRM_ERROR("No relocation chunk !\n");
-               return -EINVAL;
-       }
-       *cs_reloc = NULL;
-       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
-       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return r;
-       }
-       p->idx += p3reloc.count + 2;
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
-                         p3reloc.idx);
-               return -EINVAL;
-       }
-       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
-       if (idx >= relocs_chunk->length_dw) {
-               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
-               return -EINVAL;
-       }
-       /* FIXME: we assume reloc size is 4 dwords */
-       *cs_reloc = p->relocs_ptr[(idx / 4)];
-       return 0;
- }
- /**
-  * evergreen_cs_packet_next_is_pkt3_nop() - test if the next packet is NOP
-  * @p:                structure holding the parser context.
-  *
-  * Check if the next packet is a relocation packet3.
-  **/
- static bool evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
- {
-       struct radeon_cs_packet p3reloc;
-       int r;
-       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return false;
-       }
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               return false;
-       }
-       return true;
- }
- /**
-  * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
-  * @parser:           parser structure holding parsing context.
-  *
-  * Userspace sends a special sequence for VLINE waits.
-  * PACKET0 - VLINE_START_END + value
-  * PACKET3 - WAIT_REG_MEM poll vline status reg
-  * RELOC (P3) - crtc_id in reloc.
-  *
-  * This function parses this and relocates the VLINE START END
-  * and WAIT_REG_MEM packets to the correct crtc.
-  * It also detects a switched off crtc and nulls out the
-  * wait in that case.
+  * This is an Evergreen(+)-specific function for parsing VLINE packets.
+  * Real work is done by r600_cs_common_vline_parse function.
+  * Here we just set up ASIC-specific register table and call
+  * the common implementation function.
   */
  static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
  {
-       struct drm_mode_object *obj;
-       struct drm_crtc *crtc;
-       struct radeon_crtc *radeon_crtc;
-       struct radeon_cs_packet p3reloc, wait_reg_mem;
-       int crtc_id;
-       int r;
-       uint32_t header, h_idx, reg, wait_reg_mem_info;
-       volatile uint32_t *ib;
-       ib = p->ib.ptr;
-       /* parse the WAIT_REG_MEM */
-       r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);
-       if (r)
-               return r;
-       /* check its a WAIT_REG_MEM */
-       if (wait_reg_mem.type != PACKET_TYPE3 ||
-           wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
-               DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
-               return -EINVAL;
-       }
-       wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
-       /* bit 4 is reg (0) or mem (1) */
-       if (wait_reg_mem_info & 0x10) {
-               DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
-               return -EINVAL;
-       }
-       /* waiting for value to be equal */
-       if ((wait_reg_mem_info & 0x7) != 0x3) {
-               DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
-               return -EINVAL;
-       }
-       if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
-               DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
-               return -EINVAL;
-       }
-       if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
-               DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
-               return -EINVAL;
-       }
-       /* jump over the NOP */
-       r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
-       if (r)
-               return r;
-       h_idx = p->idx - 2;
-       p->idx += wait_reg_mem.count + 2;
-       p->idx += p3reloc.count + 2;
  
-       header = radeon_get_ib_value(p, h_idx);
-       crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
-       reg = CP_PACKET0_GET_REG(header);
-       obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
-       if (!obj) {
-               DRM_ERROR("cannot find crtc %d\n", crtc_id);
-               return -EINVAL;
-       }
-       crtc = obj_to_crtc(obj);
-       radeon_crtc = to_radeon_crtc(crtc);
-       crtc_id = radeon_crtc->crtc_id;
-       if (!crtc->enabled) {
-               /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
-               ib[h_idx + 2] = PACKET2(0);
-               ib[h_idx + 3] = PACKET2(0);
-               ib[h_idx + 4] = PACKET2(0);
-               ib[h_idx + 5] = PACKET2(0);
-               ib[h_idx + 6] = PACKET2(0);
-               ib[h_idx + 7] = PACKET2(0);
-               ib[h_idx + 8] = PACKET2(0);
-       } else {
-               switch (reg) {
-               case EVERGREEN_VLINE_START_END:
-                       header &= ~R600_CP_PACKET0_REG_MASK;
-                       header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
-                       ib[h_idx] = header;
-                       ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
-                       break;
-               default:
-                       DRM_ERROR("unknown crtc reloc\n");
-                       return -EINVAL;
-               }
-       }
-       return 0;
+       static uint32_t vline_start_end[6] = {
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC0_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC1_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC2_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC3_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC4_REGISTER_OFFSET,
+               EVERGREEN_VLINE_START_END + EVERGREEN_CRTC5_REGISTER_OFFSET
+       };
+       static uint32_t vline_status[6] = {
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
+               EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET
+       };
+       return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
  }
  
  static int evergreen_packet0_check(struct radeon_cs_parser *p,
@@@ -1347,7 -1156,7 +1156,7 @@@ static int evergreen_cs_check_reg(struc
        case SQ_LSTMP_RING_BASE:
        case SQ_PSTMP_RING_BASE:
        case SQ_VSTMP_RING_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
        case DB_Z_INFO:
                track->db_z_info = radeon_get_ib_value(p, idx);
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                                "0x%04X\n", reg);
                track->db_dirty = true;
                break;
        case DB_Z_READ_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                track->db_dirty = true;
                break;
        case DB_Z_WRITE_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                track->db_dirty = true;
                break;
        case DB_STENCIL_READ_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                track->db_dirty = true;
                break;
        case DB_STENCIL_WRITE_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
        case VGT_STRMOUT_BUFFER_BASE_1:
        case VGT_STRMOUT_BUFFER_BASE_2:
        case VGT_STRMOUT_BUFFER_BASE_3:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                track->streamout_dirty = true;
                break;
        case CP_COHER_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
                                        "0x%04X\n", reg);
                tmp = (reg - CB_COLOR0_INFO) / 0x3c;
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                                "0x%04X\n", reg);
                tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                                "0x%04X\n", reg);
        case CB_COLOR5_ATTRIB:
        case CB_COLOR6_ATTRIB:
        case CB_COLOR7_ATTRIB:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
        case CB_COLOR9_ATTRIB:
        case CB_COLOR10_ATTRIB:
        case CB_COLOR11_ATTRIB:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
        case CB_COLOR6_FMASK:
        case CB_COLOR7_FMASK:
                tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                        return -EINVAL;
        case CB_COLOR6_CMASK:
        case CB_COLOR7_CMASK:
                tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                        return -EINVAL;
        case CB_COLOR5_BASE:
        case CB_COLOR6_BASE:
        case CB_COLOR7_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
        case CB_COLOR9_BASE:
        case CB_COLOR10_BASE:
        case CB_COLOR11_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                track->cb_dirty = true;
                break;
        case DB_HTILE_DATA_BASE:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
        case SQ_ALU_CONST_CACHE_LS_13:
        case SQ_ALU_CONST_CACHE_LS_14:
        case SQ_ALU_CONST_CACHE_LS_15:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                                 "0x%04X\n", reg);
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONFIG_REG "
                                        "0x%04X\n", reg);
                                 "0x%04X\n", reg);
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
@@@ -2018,7 -1827,7 +1827,7 @@@ static int evergreen_packet3_check(stru
                        return -EINVAL;
                }
  
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad SET PREDICATION\n");
                        return -EINVAL;
                        DRM_ERROR("bad INDEX_BASE\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad INDEX_BASE\n");
                        return -EINVAL;
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
                        DRM_ERROR("bad DRAW_INDEX_2\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad DRAW_INDEX_2\n");
                        return -EINVAL;
                        DRM_ERROR("bad DISPATCH_INDIRECT\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad DISPATCH_INDIRECT\n");
                        return -EINVAL;
                if (idx_value & 0x10) {
                        uint64_t offset;
  
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad WAIT_REG_MEM\n");
                                return -EINVAL;
  
                        ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc);
                        ib[idx+2] = upper_32_bits(offset) & 0xff;
+               } else if (idx_value & 0x100) {
+                       DRM_ERROR("cannot use PFP on REG wait\n");
+                       return -EINVAL;
                }
                break;
        case PACKET3_CP_DMA:
                        }
                        /* src address space is memory */
                        if (((info & 0x60000000) >> 29) == 0) {
-                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                if (r) {
                                        DRM_ERROR("bad CP DMA SRC\n");
                                        return -EINVAL;
                                return -EINVAL;
                        }
                        if (((info & 0x00300000) >> 20) == 0) {
-                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                if (r) {
                                        DRM_ERROR("bad CP DMA DST\n");
                                        return -EINVAL;
                /* 0xffffffff/0x0 is flush all cache flag */
                if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
                    radeon_get_ib_value(p, idx + 2) != 0) {
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad SURFACE_SYNC\n");
                                return -EINVAL;
                if (pkt->count) {
                        uint64_t offset;
  
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad EVENT_WRITE\n");
                                return -EINVAL;
                        DRM_ERROR("bad EVENT_WRITE_EOP\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad EVENT_WRITE_EOP\n");
                        return -EINVAL;
                        DRM_ERROR("bad EVENT_WRITE_EOS\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad EVENT_WRITE_EOS\n");
                        return -EINVAL;
                        switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
                        case SQ_TEX_VTX_VALID_TEXTURE:
                                /* tex base */
-                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE (tex)\n");
                                        return -EINVAL;
  
                                if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) &&
                                    !mip_address &&
-                                   !evergreen_cs_packet_next_is_pkt3_nop(p)) {
+                                   !radeon_cs_packet_next_is_pkt3_nop(p)) {
                                        /* MIP_ADDRESS should point to FMASK for an MSAA texture.
                                         * It should be 0 if FMASK is disabled. */
                                        moffset = 0;
                                        mipmap = NULL;
                                } else {
-                                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                        if (r) {
                                                DRM_ERROR("bad SET_RESOURCE (tex)\n");
                                                return -EINVAL;
                        {
                                uint64_t offset64;
                                /* vtx base */
-                               r = evergreen_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE (vtx)\n");
                                        return -EINVAL;
                /* Updating memory at DST_ADDRESS. */
                if (idx_value & 0x1) {
                        u64 offset;
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
                                return -EINVAL;
                /* Reading data from SRC_ADDRESS. */
                if (((idx_value >> 1) & 0x3) == 2) {
                        u64 offset;
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
                                return -EINVAL;
                        DRM_ERROR("bad MEM_WRITE (invalid count)\n");
                        return -EINVAL;
                }
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                if (r) {
                        DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
                        return -EINVAL;
                if (idx_value & 0x1) {
                        u64 offset;
                        /* SRC is memory. */
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing src reloc)\n");
                                return -EINVAL;
                if (idx_value & 0x2) {
                        u64 offset;
                        /* DST is memory. */
-                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
                                return -EINVAL;
@@@ -2819,7 -2631,7 +2631,7 @@@ int evergreen_cs_parse(struct radeon_cs
                p->track = track;
        }
        do {
-               r = evergreen_cs_packet_parse(p, &pkt, p->idx);
+               r = radeon_cs_packet_parse(p, &pkt, p->idx);
                if (r) {
                        kfree(p->track);
                        p->track = NULL;
                }
                p->idx += pkt.count + 2;
                switch (pkt.type) {
-               case PACKET_TYPE0:
+               case RADEON_PACKET_TYPE0:
                        r = evergreen_cs_parse_packet0(p, &pkt);
                        break;
-               case PACKET_TYPE2:
+               case RADEON_PACKET_TYPE2:
                        break;
-               case PACKET_TYPE3:
+               case RADEON_PACKET_TYPE3:
                        r = evergreen_packet3_check(p, &pkt);
                        break;
                default:
        return 0;
  }
  
- /*
-  *  DMA
-  */
- #define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
- #define GET_DMA_COUNT(h) ((h) & 0x000fffff)
- #define GET_DMA_T(h) (((h) & 0x00800000) >> 23)
- #define GET_DMA_NEW(h) (((h) & 0x04000000) >> 26)
- #define GET_DMA_MISC(h) (((h) & 0x0700000) >> 20)
  /**
   * evergreen_dma_cs_parse() - parse the DMA IB
   * @p:                parser structure holding parsing context.
@@@ -2881,9 -2683,9 +2683,9 @@@ int evergreen_dma_cs_parse(struct radeo
  {
        struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
        struct radeon_cs_reloc *src_reloc, *dst_reloc, *dst2_reloc;
-       u32 header, cmd, count, tiled, new_cmd, misc;
+       u32 header, cmd, count, sub_cmd;
        volatile u32 *ib = p->ib.ptr;
-       u32 idx, idx_value;
+       u32 idx;
        u64 src_offset, dst_offset, dst2_offset;
        int r;
  
                header = radeon_get_ib_value(p, idx);
                cmd = GET_DMA_CMD(header);
                count = GET_DMA_COUNT(header);
-               tiled = GET_DMA_T(header);
-               new_cmd = GET_DMA_NEW(header);
-               misc = GET_DMA_MISC(header);
+               sub_cmd = GET_DMA_SUB_CMD(header);
  
                switch (cmd) {
                case DMA_PACKET_WRITE:
                                DRM_ERROR("bad DMA_PACKET_WRITE\n");
                                return -EINVAL;
                        }
-                       if (tiled) {
+                       switch (sub_cmd) {
+                       /* tiled */
+                       case 8:
 -                              dst_offset = ib[idx+1];
 +                              dst_offset = radeon_get_ib_value(p, idx+1);
                                dst_offset <<= 8;
  
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                p->idx += count + 7;
-                       } else {
+                               break;
+                       /* linear */
+                       case 0:
 -                              dst_offset = ib[idx+1];
 -                              dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
 +                              dst_offset = radeon_get_ib_value(p, idx+1);
 +                              dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
  
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                p->idx += count + 3;
 -                              DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, ib[idx+0]);
+                               break;
+                       default:
++                              DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, header);
+                               return -EINVAL;
                        }
                        if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
                                dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n",
                                DRM_ERROR("bad DMA_PACKET_COPY\n");
                                return -EINVAL;
                        }
-                       if (tiled) {
-                               idx_value = radeon_get_ib_value(p, idx + 2);
-                               if (new_cmd) {
-                                       switch (misc) {
-                                       case 0:
-                                               /* L2T, frame to fields */
-                                               if (idx_value & (1 << 31)) {
-                                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
-                                               if (r) {
-                                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset <<= 8;
-                                               dst2_offset = radeon_get_ib_value(p, idx+2);
-                                               dst2_offset <<= 8;
-                                               src_offset = radeon_get_ib_value(p, idx+8);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n",
-                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
-                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
-                                                                dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 10;
-                                               break;
-                                       case 1:
-                                               /* L2T, T2L partial */
-                                               if (p->family < CHIP_CAYMAN) {
-                                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
-                                                       return -EINVAL;
-                                               }
-                                               /* detile bit */
-                                               if (idx_value & (1 << 31)) {
-                                                       /* tiled src, linear dst */
-                                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
-                                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               } else {
-                                                       /* linear src, tiled dst */
-                                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               }
-                                               p->idx += 12;
-                                               break;
-                                       case 3:
-                                               /* L2T, broadcast */
-                                               if (idx_value & (1 << 31)) {
-                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
-                                               if (r) {
-                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset <<= 8;
-                                               dst2_offset = radeon_get_ib_value(p, idx+2);
-                                               dst2_offset <<= 8;
-                                               src_offset = radeon_get_ib_value(p, idx+8);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
-                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
-                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
-                                                                dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 10;
-                                               break;
-                                       case 4:
-                                               /* L2T, T2L */
-                                               /* detile bit */
-                                               if (idx_value & (1 << 31)) {
-                                                       /* tiled src, linear dst */
-                                                       src_offset = radeon_get_ib_value(p, idx+1);
-                                                       src_offset <<= 8;
-                                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
-                                                       dst_offset = radeon_get_ib_value(p, idx+7);
-                                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
-                                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               } else {
-                                                       /* linear src, tiled dst */
-                                                       src_offset = radeon_get_ib_value(p, idx+7);
-                                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
-                                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                                       dst_offset = radeon_get_ib_value(p, idx+1);
-                                                       dst_offset <<= 8;
-                                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               }
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n",
-                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n",
-                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               p->idx += 9;
-                                               break;
-                                       case 5:
-                                               /* T2T partial */
-                                               if (p->family < CHIP_CAYMAN) {
-                                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               p->idx += 13;
-                                               break;
-                                       case 7:
-                                               /* L2T, broadcast */
-                                               if (idx_value & (1 << 31)) {
-                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
-                                               if (r) {
-                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset <<= 8;
-                                               dst2_offset = radeon_get_ib_value(p, idx+2);
-                                               dst2_offset <<= 8;
-                                               src_offset = radeon_get_ib_value(p, idx+8);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
-                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
-                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
-                                                                dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
-                                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 10;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
+                       switch (sub_cmd) {
+                       /* Copy L2L, DW aligned */
+                       case 0x00:
+                               /* L2L, dw */
 -                              src_offset = ib[idx+2];
 -                              src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
 -                              dst_offset = ib[idx+1];
 -                              dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
++                              src_offset = radeon_get_ib_value(p, idx+2);
++                              src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
++                              dst_offset = radeon_get_ib_value(p, idx+1);
++                              dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n",
+                                                       src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n",
+                                                       dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 5;
+                               break;
+                       /* Copy L2T/T2L */
+                       case 0x08:
+                               /* detile bit */
 -                              if (ib[idx + 2] & (1 << 31)) {
++                              if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
+                                       /* tiled src, linear dst */
 -                                      src_offset = ib[idx+1];
++                                      src_offset = radeon_get_ib_value(p, idx+1);
+                                       src_offset <<= 8;
+                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+                                       dst_offset = radeon_get_ib_value(p, idx + 7);
 -                                      dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
++                                      dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
+                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                } else {
-                                       switch (misc) {
-                                       case 0:
-                                               /* detile bit */
-                                               if (idx_value & (1 << 31)) {
-                                                       /* tiled src, linear dst */
-                                                       src_offset = radeon_get_ib_value(p, idx+1);
-                                                       src_offset <<= 8;
-                                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
-                                                       dst_offset = radeon_get_ib_value(p, idx+7);
-                                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
-                                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               } else {
-                                                       /* linear src, tiled dst */
-                                                       src_offset = radeon_get_ib_value(p, idx+7);
-                                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
-                                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                                       dst_offset = radeon_get_ib_value(p, idx+1);
-                                                       dst_offset <<= 8;
-                                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
-                                               }
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
-                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
-                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               p->idx += 9;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
+                                       /* linear src, tiled dst */
 -                                      src_offset = ib[idx+7];
 -                                      src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
++                                      src_offset = radeon_get_ib_value(p, idx+7);
++                                      src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
+                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
 -                                      dst_offset = ib[idx+1];
++                                      dst_offset = radeon_get_ib_value(p, idx+1);
+                                       dst_offset <<= 8;
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                }
-                       } else {
-                               if (new_cmd) {
-                                       switch (misc) {
-                                       case 0:
-                                               /* L2L, byte */
-                                               src_offset = radeon_get_ib_value(p, idx+2);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
-                                               if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n",
-                                                                src_offset + count, radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n",
-                                                                dst_offset + count, radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
-                                               ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
-                                               ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 5;
-                                               break;
-                                       case 1:
-                                               /* L2L, partial */
-                                               if (p->family < CHIP_CAYMAN) {
-                                                       DRM_ERROR("L2L Partial is cayman only !\n");
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
-                                               ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
-                                               ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 9;
-                                               break;
-                                       case 4:
-                                               /* L2L, dw, broadcast */
-                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
-                                               if (r) {
-                                                       DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
-                                                       return -EINVAL;
-                                               }
-                                               dst_offset = radeon_get_ib_value(p, idx+1);
-                                               dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
-                                               dst2_offset = radeon_get_ib_value(p, idx+2);
-                                               dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32;
-                                               src_offset = radeon_get_ib_value(p, idx+3);
-                                               src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
-                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n",
-                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n",
-                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
-                                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n",
-                                                                dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
-                                                       return -EINVAL;
-                                               }
-                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                               ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                               ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff;
-                                               ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                               p->idx += 7;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, src buffer too small (%llu %lu)\n",
+                                                       src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, dst buffer too small (%llu %lu)\n",
+                                                       dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               p->idx += 9;
+                               break;
+                       /* Copy L2L, byte aligned */
+                       case 0x40:
+                               /* L2L, byte */
 -                              src_offset = ib[idx+2];
 -                              src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
 -                              dst_offset = ib[idx+1];
 -                              dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
++                              src_offset = radeon_get_ib_value(p, idx+2);
++                              src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
++                              dst_offset = radeon_get_ib_value(p, idx+1);
++                              dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
+                               if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n",
+                                                       src_offset + count, radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n",
+                                                       dst_offset + count, radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
+                               ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
+                               ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 5;
+                               break;
+                       /* Copy L2L, partial */
+                       case 0x41:
+                               /* L2L, partial */
+                               if (p->family < CHIP_CAYMAN) {
+                                       DRM_ERROR("L2L Partial is cayman only !\n");
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
+                               ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
+                               ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 9;
+                               break;
+                       /* Copy L2L, DW aligned, broadcast */
+                       case 0x44:
+                               /* L2L, dw, broadcast */
+                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                               if (r) {
+                                       DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
 -                              dst_offset = ib[idx+1];
 -                              dst_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
 -                              dst2_offset = ib[idx+2];
 -                              dst2_offset |= ((u64)(ib[idx+5] & 0xff)) << 32;
 -                              src_offset = ib[idx+3];
 -                              src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
++                              dst_offset = radeon_get_ib_value(p, idx+1);
++                              dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
++                              dst2_offset = radeon_get_ib_value(p, idx+2);
++                              dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32;
++                              src_offset = radeon_get_ib_value(p, idx+3);
++                              src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n",
+                                                       src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n",
+                                                       dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n",
+                                                       dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 7;
+                               break;
+                       /* Copy L2T Frame to Field */
+                       case 0x48:
 -                              if (ib[idx + 2] & (1 << 31)) {
++                              if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
+                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                               if (r) {
+                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
 -                              dst_offset = ib[idx+1];
++                              dst_offset = radeon_get_ib_value(p, idx+1);
+                               dst_offset <<= 8;
 -                              dst2_offset = ib[idx+2];
++                              dst2_offset = radeon_get_ib_value(p, idx+2);
+                               dst2_offset <<= 8;
 -                              src_offset = ib[idx+8];
 -                              src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
++                              src_offset = radeon_get_ib_value(p, idx+8);
++                              src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n",
+                                                       src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
+                                                       dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
+                                                       dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 10;
+                               break;
+                       /* Copy L2T/T2L, partial */
+                       case 0x49:
+                               /* L2T, T2L partial */
+                               if (p->family < CHIP_CAYMAN) {
+                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
+                                       return -EINVAL;
+                               }
+                               /* detile bit */
 -                              if (ib[idx + 2 ] & (1 << 31)) {
++                              if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
+                                       /* tiled src, linear dst */
+                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               } else {
+                                       /* linear src, tiled dst */
+                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               }
+                               p->idx += 12;
+                               break;
+                       /* Copy L2T broadcast */
+                       case 0x4b:
+                               /* L2T, broadcast */
 -                              if (ib[idx + 2] & (1 << 31)) {
++                              if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
+                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                               if (r) {
+                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
 -                              dst_offset = ib[idx+1];
++                              dst_offset = radeon_get_ib_value(p, idx+1);
+                               dst_offset <<= 8;
 -                              dst2_offset = ib[idx+2];
++                              dst2_offset = radeon_get_ib_value(p, idx+2);
+                               dst2_offset <<= 8;
 -                              src_offset = ib[idx+8];
 -                              src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
++                              src_offset = radeon_get_ib_value(p, idx+8);
++                              src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
+                                                       src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
+                                                       dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
+                                                       dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 10;
+                               break;
+                       /* Copy L2T/T2L (tile units) */
+                       case 0x4c:
+                               /* L2T, T2L */
+                               /* detile bit */
 -                              if (ib[idx + 2] & (1 << 31)) {
++                              if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
+                                       /* tiled src, linear dst */
 -                                      src_offset = ib[idx+1];
++                                      src_offset = radeon_get_ib_value(p, idx+1);
+                                       src_offset <<= 8;
+                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
 -                                      dst_offset = ib[idx+7];
 -                                      dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
++                                      dst_offset = radeon_get_ib_value(p, idx+7);
++                                      dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
+                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                } else {
-                                       /* L2L, dw */
-                                       src_offset = radeon_get_ib_value(p, idx+2);
-                                       src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
+                                       /* linear src, tiled dst */
 -                                      src_offset = ib[idx+7];
 -                                      src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
++                                      src_offset = radeon_get_ib_value(p, idx+7);
++                                      src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32;
+                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
 -                                      dst_offset = ib[idx+1];
 +                                      dst_offset = radeon_get_ib_value(p, idx+1);
-                                       dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
-                                       if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
-                                               dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n",
-                                                        src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
-                                               return -EINVAL;
-                                       }
-                                       if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
-                                               dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n",
-                                                        dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
-                                               return -EINVAL;
-                                       }
-                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
-                                       ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
-                                       ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
-                                       ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
-                                       p->idx += 5;
+                                       dst_offset <<= 8;
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                }
 -                              if (ib[idx + 2] & (1 << 31)) {
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n",
+                                                       src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n",
+                                                       dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               p->idx += 9;
+                               break;
+                       /* Copy T2T, partial (tile units) */
+                       case 0x4d:
+                               /* T2T partial */
+                               if (p->family < CHIP_CAYMAN) {
+                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               p->idx += 13;
+                               break;
+                       /* Copy L2T broadcast (tile units) */
+                       case 0x4f:
+                               /* L2T, broadcast */
 -                              dst_offset = ib[idx+1];
++                              if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) {
+                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
+                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                               if (r) {
+                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                       return -EINVAL;
+                               }
 -                              dst2_offset = ib[idx+2];
++                              dst_offset = radeon_get_ib_value(p, idx+1);
+                               dst_offset <<= 8;
 -                              src_offset = ib[idx+8];
 -                              src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
++                              dst2_offset = radeon_get_ib_value(p, idx+2);
+                               dst2_offset <<= 8;
 -                              DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, ib[idx+0]);
++                              src_offset = radeon_get_ib_value(p, idx+8);
++                              src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32;
+                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
+                                                       src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
+                                                       dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
+                                                       dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                       return -EINVAL;
+                               }
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
+                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 10;
+                               break;
+                       default:
++                              DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, header);
+                               return -EINVAL;
                        }
                        break;
                case DMA_PACKET_CONSTANT_FILL:
                                DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n");
                                return -EINVAL;
                        }
 -                      dst_offset = ib[idx+1];
 -                      dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
 +                      dst_offset = radeon_get_ib_value(p, idx+1);
 +                      dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16;
                        if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
                                dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
                                         dst_offset, radeon_bo_size(dst_reloc->robj));
@@@ -3583,19 -3383,19 +3383,19 @@@ int evergreen_ib_parse(struct radeon_de
  
        do {
                pkt.idx = idx;
-               pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]);
-               pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]);
+               pkt.type = RADEON_CP_PACKET_GET_TYPE(ib->ptr[idx]);
+               pkt.count = RADEON_CP_PACKET_GET_COUNT(ib->ptr[idx]);
                pkt.one_reg_wr = 0;
                switch (pkt.type) {
-               case PACKET_TYPE0:
+               case RADEON_PACKET_TYPE0:
                        dev_err(rdev->dev, "Packet0 not allowed!\n");
                        ret = -EINVAL;
                        break;
-               case PACKET_TYPE2:
+               case RADEON_PACKET_TYPE2:
                        idx += 1;
                        break;
-               case PACKET_TYPE3:
-                       pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
+               case RADEON_PACKET_TYPE3:
+                       pkt.opcode = RADEON_CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
                        ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt);
                        idx += pkt.count + 2;
                        break;
  int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
  {
        u32 idx = 0;
-       u32 header, cmd, count, tiled, new_cmd, misc;
+       u32 header, cmd, count, sub_cmd;
  
        do {
                header = ib->ptr[idx];
                cmd = GET_DMA_CMD(header);
                count = GET_DMA_COUNT(header);
-               tiled = GET_DMA_T(header);
-               new_cmd = GET_DMA_NEW(header);
-               misc = GET_DMA_MISC(header);
+               sub_cmd = GET_DMA_SUB_CMD(header);
  
                switch (cmd) {
                case DMA_PACKET_WRITE:
-                       if (tiled)
+                       switch (sub_cmd) {
+                       /* tiled */
+                       case 8:
                                idx += count + 7;
-                       else
+                               break;
+                       /* linear */
+                       case 0:
                                idx += count + 3;
+                               break;
+                       default:
+                               DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, ib->ptr[idx]);
+                               return -EINVAL;
+                       }
                        break;
                case DMA_PACKET_COPY:
-                       if (tiled) {
-                               if (new_cmd) {
-                                       switch (misc) {
-                                       case 0:
-                                               /* L2T, frame to fields */
-                                               idx += 10;
-                                               break;
-                                       case 1:
-                                               /* L2T, T2L partial */
-                                               idx += 12;
-                                               break;
-                                       case 3:
-                                               /* L2T, broadcast */
-                                               idx += 10;
-                                               break;
-                                       case 4:
-                                               /* L2T, T2L */
-                                               idx += 9;
-                                               break;
-                                       case 5:
-                                               /* T2T partial */
-                                               idx += 13;
-                                               break;
-                                       case 7:
-                                               /* L2T, broadcast */
-                                               idx += 10;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
-                               } else {
-                                       switch (misc) {
-                                       case 0:
-                                               idx += 9;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
-                               }
-                       } else {
-                               if (new_cmd) {
-                                       switch (misc) {
-                                       case 0:
-                                               /* L2L, byte */
-                                               idx += 5;
-                                               break;
-                                       case 1:
-                                               /* L2L, partial */
-                                               idx += 9;
-                                               break;
-                                       case 4:
-                                               /* L2L, dw, broadcast */
-                                               idx += 7;
-                                               break;
-                                       default:
-                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
-                                               return -EINVAL;
-                                       }
-                               } else {
-                                       /* L2L, dw */
-                                       idx += 5;
-                               }
+                       switch (sub_cmd) {
+                       /* Copy L2L, DW aligned */
+                       case 0x00:
+                               idx += 5;
+                               break;
+                       /* Copy L2T/T2L */
+                       case 0x08:
+                               idx += 9;
+                               break;
+                       /* Copy L2L, byte aligned */
+                       case 0x40:
+                               idx += 5;
+                               break;
+                       /* Copy L2L, partial */
+                       case 0x41:
+                               idx += 9;
+                               break;
+                       /* Copy L2L, DW aligned, broadcast */
+                       case 0x44:
+                               idx += 7;
+                               break;
+                       /* Copy L2T Frame to Field */
+                       case 0x48:
+                               idx += 10;
+                               break;
+                       /* Copy L2T/T2L, partial */
+                       case 0x49:
+                               idx += 12;
+                               break;
+                       /* Copy L2T broadcast */
+                       case 0x4b:
+                               idx += 10;
+                               break;
+                       /* Copy L2T/T2L (tile units) */
+                       case 0x4c:
+                               idx += 9;
+                               break;
+                       /* Copy T2T, partial (tile units) */
+                       case 0x4d:
+                               idx += 13;
+                               break;
+                       /* Copy L2T broadcast (tile units) */
+                       case 0x4f:
+                               idx += 10;
+                               break;
+                       default:
+                               DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, ib->ptr[idx]);
+                               return -EINVAL;
                        }
                        break;
                case DMA_PACKET_CONSTANT_FILL:
index 9b2512bf1a46638f870b5967a45877455fc48c0f,931a70289033d3825079d31bac0850b154bac51e..01a3ec83f284de58b34bd56ff9ec85525efcc0fb
  #include "r600d.h"
  #include "r600_reg_safe.h"
  
- static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc);
- static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc);
- typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
- static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
+ static int r600_nomm;
  extern void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size);
  
  
@@@ -784,170 -779,29 +779,29 @@@ static int r600_cs_track_check(struct r
  }
  
  /**
-  * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
-  * @parser:   parser structure holding parsing context.
-  * @pkt:      where to store packet informations
-  *
-  * Assume that chunk_ib_index is properly set. Will return -EINVAL
-  * if packet is bigger than remaining ib size. or if packets is unknown.
-  **/
- static int r600_cs_packet_parse(struct radeon_cs_parser *p,
-                       struct radeon_cs_packet *pkt,
-                       unsigned idx)
- {
-       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
-       uint32_t header;
-       if (idx >= ib_chunk->length_dw) {
-               DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
-                         idx, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       header = radeon_get_ib_value(p, idx);
-       pkt->idx = idx;
-       pkt->type = CP_PACKET_GET_TYPE(header);
-       pkt->count = CP_PACKET_GET_COUNT(header);
-       pkt->one_reg_wr = 0;
-       switch (pkt->type) {
-       case PACKET_TYPE0:
-               pkt->reg = CP_PACKET0_GET_REG(header);
-               break;
-       case PACKET_TYPE3:
-               pkt->opcode = CP_PACKET3_GET_OPCODE(header);
-               break;
-       case PACKET_TYPE2:
-               pkt->count = -1;
-               break;
-       default:
-               DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
-               return -EINVAL;
-       }
-       if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
-               DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
-                         pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
-               return -EINVAL;
-       }
-       return 0;
- }
- /**
-  * r600_cs_packet_next_reloc_mm() - parse next packet which should be reloc packet3
-  * @parser:           parser structure holding parsing context.
-  * @data:             pointer to relocation data
-  * @offset_start:     starting offset
-  * @offset_mask:      offset mask (to align start offset on)
-  * @reloc:            reloc informations
-  *
-  * Check next packet is relocation packet3, do bo validation and compute
-  * GPU offset using the provided start.
-  **/
- static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc)
- {
-       struct radeon_cs_chunk *relocs_chunk;
-       struct radeon_cs_packet p3reloc;
-       unsigned idx;
-       int r;
-       if (p->chunk_relocs_idx == -1) {
-               DRM_ERROR("No relocation chunk !\n");
-               return -EINVAL;
-       }
-       *cs_reloc = NULL;
-       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
-       r = r600_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return r;
-       }
-       p->idx += p3reloc.count + 2;
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
-                         p3reloc.idx);
-               return -EINVAL;
-       }
-       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
-       if (idx >= relocs_chunk->length_dw) {
-               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
-               return -EINVAL;
-       }
-       /* FIXME: we assume reloc size is 4 dwords */
-       *cs_reloc = p->relocs_ptr[(idx / 4)];
-       return 0;
- }
- /**
-  * r600_cs_packet_next_reloc_nomm() - parse next packet which should be reloc packet3
-  * @parser:           parser structure holding parsing context.
-  * @data:             pointer to relocation data
-  * @offset_start:     starting offset
-  * @offset_mask:      offset mask (to align start offset on)
-  * @reloc:            reloc informations
-  *
-  * Check next packet is relocation packet3, do bo validation and compute
-  * GPU offset using the provided start.
-  **/
- static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
-                                       struct radeon_cs_reloc **cs_reloc)
- {
-       struct radeon_cs_chunk *relocs_chunk;
-       struct radeon_cs_packet p3reloc;
-       unsigned idx;
-       int r;
-       if (p->chunk_relocs_idx == -1) {
-               DRM_ERROR("No relocation chunk !\n");
-               return -EINVAL;
-       }
-       *cs_reloc = NULL;
-       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
-       r = r600_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return r;
-       }
-       p->idx += p3reloc.count + 2;
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               DRM_ERROR("No packet3 for relocation for packet at %d.\n",
-                         p3reloc.idx);
-               return -EINVAL;
-       }
-       idx = radeon_get_ib_value(p, p3reloc.idx + 1);
-       if (idx >= relocs_chunk->length_dw) {
-               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-                         idx, relocs_chunk->length_dw);
-               return -EINVAL;
-       }
-       *cs_reloc = p->relocs;
-       (*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32;
-       (*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0];
-       return 0;
- }
- /**
-  * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
+  * r600_cs_packet_parse_vline() - parse userspace VLINE packet
   * @parser:           parser structure holding parsing context.
   *
-  * Check next packet is relocation packet3, do bo validation and compute
-  * GPU offset using the provided start.
-  **/
- static int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+  * This is an R600-specific function for parsing VLINE packets.
+  * Real work is done by r600_cs_common_vline_parse function.
+  * Here we just set up ASIC-specific register table and call
+  * the common implementation function.
+  */
+ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
  {
-       struct radeon_cs_packet p3reloc;
-       int r;
+       static uint32_t vline_start_end[2] = {AVIVO_D1MODE_VLINE_START_END,
+                                             AVIVO_D2MODE_VLINE_START_END};
+       static uint32_t vline_status[2] = {AVIVO_D1MODE_VLINE_STATUS,
+                                          AVIVO_D2MODE_VLINE_STATUS};
  
-       r = r600_cs_packet_parse(p, &p3reloc, p->idx);
-       if (r) {
-               return 0;
-       }
-       if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
-               return 0;
-       }
-       return 1;
+       return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
  }
  
  /**
-  * r600_cs_packet_next_vline() - parse userspace VLINE packet
+  * r600_cs_common_vline_parse() - common vline parser
   * @parser:           parser structure holding parsing context.
+  * @vline_start_end:    table of vline_start_end registers
+  * @vline_status:       table of vline_status registers
   *
   * Userspace sends a special sequence for VLINE waits.
   * PACKET0 - VLINE_START_END + value
   * This function parses this and relocates the VLINE START END
   * and WAIT_REG_MEM packets to the correct crtc.
   * It also detects a switched off crtc and nulls out the
-  * wait in that case.
+  * wait in that case. This function is common for all ASICs that
+  * are R600 and newer. The parsing algorithm is the same, and only
+  * differs in which registers are used.
+  *
+  * Caller is the ASIC-specific function which passes the parser
+  * context and ASIC-specific register table
   */
- static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
+ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
+                              uint32_t *vline_start_end,
+                              uint32_t *vline_status)
  {
        struct drm_mode_object *obj;
        struct drm_crtc *crtc;
        ib = p->ib.ptr;
  
        /* parse the WAIT_REG_MEM */
-       r = r600_cs_packet_parse(p, &wait_reg_mem, p->idx);
+       r = radeon_cs_packet_parse(p, &wait_reg_mem, p->idx);
        if (r)
                return r;
  
        /* check its a WAIT_REG_MEM */
-       if (wait_reg_mem.type != PACKET_TYPE3 ||
+       if (wait_reg_mem.type != RADEON_PACKET_TYPE3 ||
            wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
                DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
                return -EINVAL;
        wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
        /* bit 4 is reg (0) or mem (1) */
        if (wait_reg_mem_info & 0x10) {
-               DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
+               DRM_ERROR("vline WAIT_REG_MEM waiting on MEM instead of REG\n");
+               return -EINVAL;
+       }
+       /* bit 8 is me (0) or pfp (1) */
+       if (wait_reg_mem_info & 0x100) {
+               DRM_ERROR("vline WAIT_REG_MEM waiting on PFP instead of ME\n");
                return -EINVAL;
        }
        /* waiting for value to be equal */
                DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
                return -EINVAL;
        }
-       if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) {
+       if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != vline_status[0]) {
                DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
                return -EINVAL;
        }
  
-       if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) {
+       if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != RADEON_VLINE_STAT) {
                DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
                return -EINVAL;
        }
  
        /* jump over the NOP */
-       r = r600_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
+       r = radeon_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
        if (r)
                return r;
  
  
        header = radeon_get_ib_value(p, h_idx);
        crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
-       reg = CP_PACKET0_GET_REG(header);
+       reg = R600_CP_PACKET0_GET_REG(header);
  
        obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
        if (!obj) {
        crtc_id = radeon_crtc->crtc_id;
  
        if (!crtc->enabled) {
-               /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
+               /* CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
                ib[h_idx + 2] = PACKET2(0);
                ib[h_idx + 3] = PACKET2(0);
                ib[h_idx + 4] = PACKET2(0);
                ib[h_idx + 6] = PACKET2(0);
                ib[h_idx + 7] = PACKET2(0);
                ib[h_idx + 8] = PACKET2(0);
-       } else if (crtc_id == 1) {
-               switch (reg) {
-               case AVIVO_D1MODE_VLINE_START_END:
-                       header &= ~R600_CP_PACKET0_REG_MASK;
-                       header |= AVIVO_D2MODE_VLINE_START_END >> 2;
-                       break;
-               default:
-                       DRM_ERROR("unknown crtc reloc\n");
-                       return -EINVAL;
-               }
+       } else if (reg == vline_start_end[0]) {
+               header &= ~R600_CP_PACKET0_REG_MASK;
+               header |= vline_start_end[crtc_id] >> 2;
                ib[h_idx] = header;
-               ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
+               ib[h_idx + 4] = vline_status[crtc_id] >> 2;
+       } else {
+               DRM_ERROR("unknown crtc reloc\n");
+               return -EINVAL;
        }
        return 0;
  }
  
@@@ -1155,8 -1016,8 +1016,8 @@@ static int r600_cs_check_reg(struct rad
                break;
        case R_028010_DB_DEPTH_INFO:
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
-                   r600_cs_packet_next_is_pkt3_nop(p)) {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                   radeon_cs_packet_next_is_pkt3_nop(p)) {
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                         "0x%04X\n", reg);
        case VGT_STRMOUT_BUFFER_BASE_1:
        case VGT_STRMOUT_BUFFER_BASE_2:
        case VGT_STRMOUT_BUFFER_BASE_3:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                track->streamout_dirty = true;
                break;
        case CP_COHER_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
                                        "0x%04X\n", reg);
        case R_0280B8_CB_COLOR6_INFO:
        case R_0280BC_CB_COLOR7_INFO:
                if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
-                    r600_cs_packet_next_is_pkt3_nop(p)) {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                    radeon_cs_packet_next_is_pkt3_nop(p)) {
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
        case R_0280F8_CB_COLOR6_FRAG:
        case R_0280FC_CB_COLOR7_FRAG:
                tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4;
-               if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+               if (!radeon_cs_packet_next_is_pkt3_nop(p)) {
                        if (!track->cb_color_base_last[tmp]) {
                                dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
                                return -EINVAL;
                        track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp];
                        ib[idx] = track->cb_color_base_last[tmp];
                } else {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
        case R_0280D8_CB_COLOR6_TILE:
        case R_0280DC_CB_COLOR7_TILE:
                tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4;
-               if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+               if (!radeon_cs_packet_next_is_pkt3_nop(p)) {
                        if (!track->cb_color_base_last[tmp]) {
                                dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
                                return -EINVAL;
                        track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp];
                        ib[idx] = track->cb_color_base_last[tmp];
                } else {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
        case CB_COLOR5_BASE:
        case CB_COLOR6_BASE:
        case CB_COLOR7_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                track->cb_dirty = true;
                break;
        case DB_DEPTH_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                track->db_dirty = true;
                break;
        case DB_HTILE_DATA_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
        case SQ_ALU_CONST_CACHE_VS_13:
        case SQ_ALU_CONST_CACHE_VS_14:
        case SQ_ALU_CONST_CACHE_VS_15:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONTEXT_REG "
                                        "0x%04X\n", reg);
                ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                break;
        case SX_MEMORY_EXPORT_BASE:
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        dev_warn(p->dev, "bad SET_CONFIG_REG "
                                        "0x%04X\n", reg);
@@@ -1788,7 -1649,7 +1649,7 @@@ static int r600_packet3_check(struct ra
                        return -EINVAL;
                }
  
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad SET PREDICATION\n");
                        return -EINVAL;
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
                }
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad DRAW_INDEX\n");
                        return -EINVAL;
                if (idx_value & 0x10) {
                        uint64_t offset;
  
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad WAIT_REG_MEM\n");
                                return -EINVAL;
  
                        ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffff0);
                        ib[idx+2] = upper_32_bits(offset) & 0xff;
+               } else if (idx_value & 0x100) {
+                       DRM_ERROR("cannot use PFP on REG wait\n");
+                       return -EINVAL;
                }
                break;
        case PACKET3_CP_DMA:
                                return -EINVAL;
                        }
                        /* src address space is memory */
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad CP DMA SRC\n");
                                return -EINVAL;
                                DRM_ERROR("CP DMA DAIC only supported for registers\n");
                                return -EINVAL;
                        }
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad CP DMA DST\n");
                                return -EINVAL;
                /* 0xffffffff/0x0 is flush all cache flag */
                if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
                    radeon_get_ib_value(p, idx + 2) != 0) {
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad SURFACE_SYNC\n");
                                return -EINVAL;
                if (pkt->count) {
                        uint64_t offset;
  
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad EVENT_WRITE\n");
                                return -EINVAL;
                        DRM_ERROR("bad EVENT_WRITE_EOP\n");
                        return -EINVAL;
                }
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad EVENT_WRITE\n");
                        return -EINVAL;
                        switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
                        case SQ_TEX_VTX_VALID_TEXTURE:
                                /* tex base */
-                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE\n");
                                        return -EINVAL;
                                }
                                texture = reloc->robj;
                                /* tex mip base */
-                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE\n");
                                        return -EINVAL;
                        {
                                uint64_t offset64;
                                /* vtx base */
-                               r = r600_cs_packet_next_reloc(p, &reloc);
+                               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                                if (r) {
                                        DRM_ERROR("bad SET_RESOURCE\n");
                                        return -EINVAL;
                {
                        u64 offset;
  
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BASE_UPDATE reloc\n");
                                return -EINVAL;
                /* Updating memory at DST_ADDRESS. */
                if (idx_value & 0x1) {
                        u64 offset;
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
                                return -EINVAL;
                /* Reading data from SRC_ADDRESS. */
                if (((idx_value >> 1) & 0x3) == 2) {
                        u64 offset;
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
                                return -EINVAL;
                        DRM_ERROR("bad MEM_WRITE (invalid count)\n");
                        return -EINVAL;
                }
-               r = r600_cs_packet_next_reloc(p, &reloc);
+               r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                if (r) {
                        DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
                        return -EINVAL;
                if (idx_value & 0x1) {
                        u64 offset;
                        /* SRC is memory. */
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing src reloc)\n");
                                return -EINVAL;
                if (idx_value & 0x2) {
                        u64 offset;
                        /* DST is memory. */
-                       r = r600_cs_packet_next_reloc(p, &reloc);
+                       r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
                        if (r) {
                                DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
                                return -EINVAL;
@@@ -2410,7 -2274,7 +2274,7 @@@ int r600_cs_parse(struct radeon_cs_pars
                p->track = track;
        }
        do {
-               r = r600_cs_packet_parse(p, &pkt, p->idx);
+               r = radeon_cs_packet_parse(p, &pkt, p->idx);
                if (r) {
                        kfree(p->track);
                        p->track = NULL;
                }
                p->idx += pkt.count + 2;
                switch (pkt.type) {
-               case PACKET_TYPE0:
+               case RADEON_PACKET_TYPE0:
                        r = r600_cs_parse_packet0(p, &pkt);
                        break;
-               case PACKET_TYPE2:
+               case RADEON_PACKET_TYPE2:
                        break;
-               case PACKET_TYPE3:
+               case RADEON_PACKET_TYPE3:
                        r = r600_packet3_check(p, &pkt);
                        break;
                default:
        return 0;
  }
  
- static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
- {
-       if (p->chunk_relocs_idx == -1) {
-               return 0;
-       }
-       p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL);
-       if (p->relocs == NULL) {
-               return -ENOMEM;
-       }
-       return 0;
- }
+ #ifdef CONFIG_DRM_RADEON_UMS
  
  /**
   * cs_parser_fini() - clean parser states
@@@ -2485,6 -2339,18 +2339,18 @@@ static void r600_cs_parser_fini(struct 
        kfree(parser->chunks_array);
  }
  
+ static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
+ {
+       if (p->chunk_relocs_idx == -1) {
+               return 0;
+       }
+       p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL);
+       if (p->relocs == NULL) {
+               return -ENOMEM;
+       }
+       return 0;
+ }
  int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
                        unsigned family, u32 *ib, int *l)
  {
  
  void r600_cs_legacy_init(void)
  {
-       r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm;
+       r600_nomm = 1;
  }
  
+ #endif
  /*
   *  DMA
   */
@@@ -2623,14 -2491,14 +2491,14 @@@ int r600_dma_cs_parse(struct radeon_cs_
                                return -EINVAL;
                        }
                        if (tiled) {
 -                              dst_offset = ib[idx+1];
 +                              dst_offset = radeon_get_ib_value(p, idx+1);
                                dst_offset <<= 8;
  
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                p->idx += count + 5;
                        } else {
 -                              dst_offset = ib[idx+1];
 -                              dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
 +                              dst_offset = radeon_get_ib_value(p, idx+1);
 +                              dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
  
                                ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                /* detile bit */
                                if (idx_value & (1 << 31)) {
                                        /* tiled src, linear dst */
 -                                      src_offset = ib[idx+1];
 +                                      src_offset = radeon_get_ib_value(p, idx+1);
                                        src_offset <<= 8;
                                        ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
  
 -                                      dst_offset = ib[idx+5];
 -                                      dst_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
 +                                      dst_offset = radeon_get_ib_value(p, idx+5);
 +                                      dst_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
                                        ib[idx+5] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+6] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
                                } else {
                                        /* linear src, tiled dst */
 -                                      src_offset = ib[idx+5];
 -                                      src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
 +                                      src_offset = radeon_get_ib_value(p, idx+5);
 +                                      src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
                                        ib[idx+5] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
  
 -                                      dst_offset = ib[idx+1];
 +                                      dst_offset = radeon_get_ib_value(p, idx+1);
                                        dst_offset <<= 8;
                                        ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
                                }
                                p->idx += 7;
                        } else {
                                if (p->family >= CHIP_RV770) {
 -                                      src_offset = ib[idx+2];
 -                                      src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
 -                                      dst_offset = ib[idx+1];
 -                                      dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
 +                                      src_offset = radeon_get_ib_value(p, idx+2);
 +                                      src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
 +                                      dst_offset = radeon_get_ib_value(p, idx+1);
 +                                      dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
  
                                        ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
                                        p->idx += 5;
                                } else {
 -                                      src_offset = ib[idx+2];
 -                                      src_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
 -                                      dst_offset = ib[idx+1];
 -                                      dst_offset |= ((u64)(ib[idx+3] & 0xff0000)) << 16;
 +                                      src_offset = radeon_get_ib_value(p, idx+2);
 +                                      src_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
 +                                      dst_offset = radeon_get_ib_value(p, idx+1);
 +                                      dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff0000)) << 16;
  
                                        ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
                                        ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
                                DRM_ERROR("bad DMA_PACKET_WRITE\n");
                                return -EINVAL;
                        }
 -                      dst_offset = ib[idx+1];
 -                      dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
 +                      dst_offset = radeon_get_ib_value(p, idx+1);
 +                      dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16;
                        if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
                                dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
                                         dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
index b6679b36700f98422965f17b7efcf7d6b6831f78,bf8095c55bd1320aa4c178935eb2ac716c0053fb..de94707b9dbed00bc84a564dda11970f5b2e0b12
  #include <linux/module.h>
  #include <linux/of.h>
  #include <linux/platform_device.h>
 -
 -#include <mach/clk.h>
 +#include <linux/clk/tegra.h>
  
  #include "drm.h"
  #include "dc.h"
  
- struct tegra_dc_window {
-       fixed20_12 x;
-       fixed20_12 y;
-       fixed20_12 w;
-       fixed20_12 h;
-       unsigned int outx;
-       unsigned int outy;
-       unsigned int outw;
-       unsigned int outh;
-       unsigned int stride;
-       unsigned int fmt;
+ struct tegra_plane {
+       struct drm_plane base;
+       unsigned int index;
  };
  
+ static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
+ {
+       return container_of(plane, struct tegra_plane, base);
+ }
+ static int tegra_plane_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)
+ {
+       struct tegra_plane *p = to_tegra_plane(plane);
+       struct tegra_dc *dc = to_tegra_dc(crtc);
+       struct tegra_dc_window window;
+       unsigned int i;
+       memset(&window, 0, sizeof(window));
+       window.src.x = src_x >> 16;
+       window.src.y = src_y >> 16;
+       window.src.w = src_w >> 16;
+       window.src.h = src_h >> 16;
+       window.dst.x = crtc_x;
+       window.dst.y = crtc_y;
+       window.dst.w = crtc_w;
+       window.dst.h = crtc_h;
+       window.format = tegra_dc_format(fb->pixel_format);
+       window.bits_per_pixel = fb->bits_per_pixel;
+       for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
+               struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
+               window.base[i] = gem->paddr + fb->offsets[i];
+               /*
+                * Tegra doesn't support different strides for U and V planes
+                * so we display a warning if the user tries to display a
+                * framebuffer with such a configuration.
+                */
+               if (i >= 2) {
+                       if (fb->pitches[i] != window.stride[1])
+                               DRM_ERROR("unsupported UV-plane configuration\n");
+               } else {
+                       window.stride[i] = fb->pitches[i];
+               }
+       }
+       return tegra_dc_setup_window(dc, p->index, &window);
+ }
+ static int tegra_plane_disable(struct drm_plane *plane)
+ {
+       struct tegra_dc *dc = to_tegra_dc(plane->crtc);
+       struct tegra_plane *p = to_tegra_plane(plane);
+       unsigned long value;
+       value = WINDOW_A_SELECT << p->index;
+       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
+       value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
+       value &= ~WIN_ENABLE;
+       tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
+       tegra_dc_writel(dc, WIN_A_UPDATE << p->index, DC_CMD_STATE_CONTROL);
+       tegra_dc_writel(dc, WIN_A_ACT_REQ << p->index, DC_CMD_STATE_CONTROL);
+       return 0;
+ }
+ static void tegra_plane_destroy(struct drm_plane *plane)
+ {
+       tegra_plane_disable(plane);
+       drm_plane_cleanup(plane);
+ }
+ static const struct drm_plane_funcs tegra_plane_funcs = {
+       .update_plane = tegra_plane_update,
+       .disable_plane = tegra_plane_disable,
+       .destroy = tegra_plane_destroy,
+ };
+ static const uint32_t plane_formats[] = {
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_UYVY,
+       DRM_FORMAT_YUV420,
+       DRM_FORMAT_YUV422,
+ };
+ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
+ {
+       unsigned int i;
+       int err = 0;
+       for (i = 0; i < 2; i++) {
+               struct tegra_plane *plane;
+               plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
+               if (!plane)
+                       return -ENOMEM;
+               plane->index = 1 + i;
+               err = drm_plane_init(drm, &plane->base, 1 << dc->pipe,
+                                    &tegra_plane_funcs, plane_formats,
+                                    ARRAY_SIZE(plane_formats), false);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+ }
+ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
+                            struct drm_framebuffer *fb)
+ {
+       struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, 0);
+       unsigned long value;
+       tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
+       value = fb->offsets[0] + y * fb->pitches[0] +
+               x * fb->bits_per_pixel / 8;
+       tegra_dc_writel(dc, gem->paddr + value, DC_WINBUF_START_ADDR);
+       tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
+       value = GENERAL_UPDATE | WIN_A_UPDATE;
+       tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
+       value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
+       tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
+       return 0;
+ }
+ void tegra_dc_enable_vblank(struct tegra_dc *dc)
+ {
+       unsigned long value, flags;
+       spin_lock_irqsave(&dc->lock, flags);
+       value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
+       value |= VBLANK_INT;
+       tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
+       spin_unlock_irqrestore(&dc->lock, flags);
+ }
+ void tegra_dc_disable_vblank(struct tegra_dc *dc)
+ {
+       unsigned long value, flags;
+       spin_lock_irqsave(&dc->lock, flags);
+       value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
+       value &= ~VBLANK_INT;
+       tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
+       spin_unlock_irqrestore(&dc->lock, flags);
+ }
+ static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
+ {
+       struct drm_device *drm = dc->base.dev;
+       struct drm_crtc *crtc = &dc->base;
+       struct drm_gem_cma_object *gem;
+       unsigned long flags, base;
+       if (!dc->event)
+               return;
+       gem = drm_fb_cma_get_gem_obj(crtc->fb, 0);
+       /* check if new start address has been latched */
+       tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
+       base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
+       tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
+       if (base == gem->paddr + crtc->fb->offsets[0]) {
+               spin_lock_irqsave(&drm->event_lock, flags);
+               drm_send_vblank_event(drm, dc->pipe, dc->event);
+               drm_vblank_put(drm, dc->pipe);
+               dc->event = NULL;
+               spin_unlock_irqrestore(&drm->event_lock, flags);
+       }
+ }
+ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
+ {
+       struct tegra_dc *dc = to_tegra_dc(crtc);
+       struct drm_device *drm = crtc->dev;
+       unsigned long flags;
+       spin_lock_irqsave(&drm->event_lock, flags);
+       if (dc->event && dc->event->base.file_priv == file) {
+               dc->event->base.destroy(&dc->event->base);
+               drm_vblank_put(drm, dc->pipe);
+               dc->event = NULL;
+       }
+       spin_unlock_irqrestore(&drm->event_lock, flags);
+ }
+ static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+                             struct drm_pending_vblank_event *event)
+ {
+       struct tegra_dc *dc = to_tegra_dc(crtc);
+       struct drm_device *drm = crtc->dev;
+       if (dc->event)
+               return -EBUSY;
+       if (event) {
+               event->pipe = dc->pipe;
+               dc->event = event;
+               drm_vblank_get(drm, dc->pipe);
+       }
+       tegra_dc_set_base(dc, 0, 0, fb);
+       crtc->fb = fb;
+       return 0;
+ }
  static const struct drm_crtc_funcs tegra_crtc_funcs = {
+       .page_flip = tegra_dc_page_flip,
        .set_config = drm_crtc_helper_set_config,
        .destroy = drm_crtc_cleanup,
  };
  
- static void tegra_crtc_dpms(struct drm_crtc *crtc, int mode)
+ static void tegra_crtc_disable(struct drm_crtc *crtc)
  {
+       struct drm_device *drm = crtc->dev;
+       struct drm_plane *plane;
+       list_for_each_entry(plane, &drm->mode_config.plane_list, head) {
+               if (plane->crtc == crtc) {
+                       tegra_plane_disable(plane);
+                       plane->crtc = NULL;
+                       if (plane->fb) {
+                               drm_framebuffer_unreference(plane->fb);
+                               plane->fb = NULL;
+                       }
+               }
+       }
  }
  
  static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
        return true;
  }
  
- static inline u32 compute_dda_inc(fixed20_12 inf, unsigned int out, bool v,
+ static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v,
                                  unsigned int bpp)
  {
        fixed20_12 outf = dfixed_init(out);
+       fixed20_12 inf = dfixed_init(in);
        u32 dda_inc;
        int max;
  
        return dda_inc;
  }
  
- static inline u32 compute_initial_dda(fixed20_12 in)
+ static inline u32 compute_initial_dda(unsigned int in)
  {
-       return dfixed_frac(in);
+       fixed20_12 inf = dfixed_init(in);
+       return dfixed_frac(inf);
  }
  
  static int tegra_dc_set_timings(struct tegra_dc *dc,
@@@ -152,18 -386,198 +385,198 @@@ static int tegra_crtc_setup_clk(struct 
        return 0;
  }
  
+ static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar)
+ {
+       switch (format) {
+       case WIN_COLOR_DEPTH_YCbCr422:
+       case WIN_COLOR_DEPTH_YUV422:
+               if (planar)
+                       *planar = false;
+               return true;
+       case WIN_COLOR_DEPTH_YCbCr420P:
+       case WIN_COLOR_DEPTH_YUV420P:
+       case WIN_COLOR_DEPTH_YCbCr422P:
+       case WIN_COLOR_DEPTH_YUV422P:
+       case WIN_COLOR_DEPTH_YCbCr422R:
+       case WIN_COLOR_DEPTH_YUV422R:
+       case WIN_COLOR_DEPTH_YCbCr422RA:
+       case WIN_COLOR_DEPTH_YUV422RA:
+               if (planar)
+                       *planar = true;
+               return true;
+       }
+       return false;
+ }
+ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
+                         const struct tegra_dc_window *window)
+ {
+       unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
+       unsigned long value;
+       bool yuv, planar;
+       /*
+        * For YUV planar modes, the number of bytes per pixel takes into
+        * account only the luma component and therefore is 1.
+        */
+       yuv = tegra_dc_format_is_yuv(window->format, &planar);
+       if (!yuv)
+               bpp = window->bits_per_pixel / 8;
+       else
+               bpp = planar ? 1 : 2;
+       value = WINDOW_A_SELECT << index;
+       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
+       tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
+       tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
+       value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
+       tegra_dc_writel(dc, value, DC_WIN_POSITION);
+       value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
+       tegra_dc_writel(dc, value, DC_WIN_SIZE);
+       h_offset = window->src.x * bpp;
+       v_offset = window->src.y;
+       h_size = window->src.w * bpp;
+       v_size = window->src.h;
+       value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
+       tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
+       /*
+        * For DDA computations the number of bytes per pixel for YUV planar
+        * modes needs to take into account all Y, U and V components.
+        */
+       if (yuv && planar)
+               bpp = 2;
+       h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
+       v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
+       value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
+       tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
+       h_dda = compute_initial_dda(window->src.x);
+       v_dda = compute_initial_dda(window->src.y);
+       tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
+       tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
+       tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
+       tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
+       tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR);
+       if (yuv && planar) {
+               tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U);
+               tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V);
+               value = window->stride[1] << 16 | window->stride[0];
+               tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE);
+       } else {
+               tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE);
+       }
+       tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
+       tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
+       value = WIN_ENABLE;
+       if (yuv) {
+               /* setup default colorspace conversion coefficients */
+               tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
+               tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
+               tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
+               tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
+               tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
+               tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
+               tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
+               tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
+               value |= CSC_ENABLE;
+       } else if (window->bits_per_pixel < 24) {
+               value |= COLOR_EXPAND;
+       }
+       tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
+       /*
+        * Disable blending and assume Window A is the bottom-most window,
+        * Window C is the top-most window and Window B is in the middle.
+        */
+       tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY);
+       tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
+       switch (index) {
+       case 0:
+               tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X);
+               tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
+               tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
+               break;
+       case 1:
+               tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
+               tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y);
+               tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY);
+               break;
+       case 2:
+               tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X);
+               tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y);
+               tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY);
+               break;
+       }
+       tegra_dc_writel(dc, WIN_A_UPDATE << index, DC_CMD_STATE_CONTROL);
+       tegra_dc_writel(dc, WIN_A_ACT_REQ << index, DC_CMD_STATE_CONTROL);
+       return 0;
+ }
+ unsigned int tegra_dc_format(uint32_t format)
+ {
+       switch (format) {
+       case DRM_FORMAT_XRGB8888:
+               return WIN_COLOR_DEPTH_B8G8R8A8;
+       case DRM_FORMAT_RGB565:
+               return WIN_COLOR_DEPTH_B5G6R5;
+       case DRM_FORMAT_UYVY:
+               return WIN_COLOR_DEPTH_YCbCr422;
+       case DRM_FORMAT_YUV420:
+               return WIN_COLOR_DEPTH_YCbCr420P;
+       case DRM_FORMAT_YUV422:
+               return WIN_COLOR_DEPTH_YCbCr422P;
+       default:
+               break;
+       }
+       WARN(1, "unsupported pixel format %u, using default\n", format);
+       return WIN_COLOR_DEPTH_B8G8R8A8;
+ }
  static int tegra_crtc_mode_set(struct drm_crtc *crtc,
                               struct drm_display_mode *mode,
                               struct drm_display_mode *adjusted,
                               int x, int y, struct drm_framebuffer *old_fb)
  {
-       struct tegra_framebuffer *fb = to_tegra_fb(crtc->fb);
+       struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(crtc->fb, 0);
        struct tegra_dc *dc = to_tegra_dc(crtc);
-       unsigned int h_dda, v_dda, bpp;
-       struct tegra_dc_window win;
+       struct tegra_dc_window window;
        unsigned long div, value;
        int err;
  
+       drm_vblank_pre_modeset(crtc->dev, dc->pipe);
        err = tegra_crtc_setup_clk(crtc, mode, &div);
        if (err) {
                dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
        tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
  
        /* setup window parameters */
-       memset(&win, 0, sizeof(win));
-       win.x.full = dfixed_const(0);
-       win.y.full = dfixed_const(0);
-       win.w.full = dfixed_const(mode->hdisplay);
-       win.h.full = dfixed_const(mode->vdisplay);
-       win.outx = 0;
-       win.outy = 0;
-       win.outw = mode->hdisplay;
-       win.outh = mode->vdisplay;
-       switch (crtc->fb->pixel_format) {
-       case DRM_FORMAT_XRGB8888:
-               win.fmt = WIN_COLOR_DEPTH_B8G8R8A8;
-               break;
-       case DRM_FORMAT_RGB565:
-               win.fmt = WIN_COLOR_DEPTH_B5G6R5;
-               break;
-       default:
-               win.fmt = WIN_COLOR_DEPTH_B8G8R8A8;
-               WARN_ON(1);
-               break;
-       }
-       bpp = crtc->fb->bits_per_pixel / 8;
-       win.stride = crtc->fb->pitches[0];
-       /* program window registers */
-       value = WINDOW_A_SELECT;
-       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
-       tegra_dc_writel(dc, win.fmt, DC_WIN_COLOR_DEPTH);
-       tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
-       value = V_POSITION(win.outy) | H_POSITION(win.outx);
-       tegra_dc_writel(dc, value, DC_WIN_POSITION);
-       value = V_SIZE(win.outh) | H_SIZE(win.outw);
-       tegra_dc_writel(dc, value, DC_WIN_SIZE);
-       value = V_PRESCALED_SIZE(dfixed_trunc(win.h)) |
-               H_PRESCALED_SIZE(dfixed_trunc(win.w) * bpp);
-       tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE);
-       h_dda = compute_dda_inc(win.w, win.outw, false, bpp);
-       v_dda = compute_dda_inc(win.h, win.outh, true, bpp);
-       value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda);
-       tegra_dc_writel(dc, value, DC_WIN_DDA_INC);
-       h_dda = compute_initial_dda(win.x);
-       v_dda = compute_initial_dda(win.y);
-       tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
-       tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
-       tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
-       tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
-       tegra_dc_writel(dc, fb->obj->paddr, DC_WINBUF_START_ADDR);
-       tegra_dc_writel(dc, win.stride, DC_WIN_LINE_STRIDE);
-       tegra_dc_writel(dc, dfixed_trunc(win.x) * bpp,
-                       DC_WINBUF_ADDR_H_OFFSET);
-       tegra_dc_writel(dc, dfixed_trunc(win.y), DC_WINBUF_ADDR_V_OFFSET);
-       value = WIN_ENABLE;
-       if (bpp < 24)
-               value |= COLOR_EXPAND;
+       memset(&window, 0, sizeof(window));
+       window.src.x = 0;
+       window.src.y = 0;
+       window.src.w = mode->hdisplay;
+       window.src.h = mode->vdisplay;
+       window.dst.x = 0;
+       window.dst.y = 0;
+       window.dst.w = mode->hdisplay;
+       window.dst.h = mode->vdisplay;
+       window.format = tegra_dc_format(crtc->fb->pixel_format);
+       window.bits_per_pixel = crtc->fb->bits_per_pixel;
+       window.stride[0] = crtc->fb->pitches[0];
+       window.base[0] = gem->paddr;
+       err = tegra_dc_setup_window(dc, 0, &window);
+       if (err < 0)
+               dev_err(dc->dev, "failed to enable root plane\n");
  
-       tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS);
+       return 0;
+ }
  
-       tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_NOKEY);
-       tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_1WIN);
+ static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+                                   struct drm_framebuffer *old_fb)
+ {
+       struct tegra_dc *dc = to_tegra_dc(crtc);
  
-       return 0;
+       return tegra_dc_set_base(dc, x, y, crtc->fb);
  }
  
  static void tegra_crtc_prepare(struct drm_crtc *crtc)
                WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
        tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
  
-       value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
-       tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
        value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
        tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
+       value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
+       tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
  }
  
  static void tegra_crtc_commit(struct drm_crtc *crtc)
  {
        struct tegra_dc *dc = to_tegra_dc(crtc);
-       unsigned long update_mask;
        unsigned long value;
  
-       update_mask = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
-       tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL);
+       value = GENERAL_UPDATE | WIN_A_UPDATE;
+       tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
  
-       value = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
-       value |= FRAME_END_INT;
-       tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
-       value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
-       value |= FRAME_END_INT;
-       tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
+       value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
+       tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
  
-       tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
+       drm_vblank_post_modeset(crtc->dev, dc->pipe);
  }
  
  static void tegra_crtc_load_lut(struct drm_crtc *crtc)
  }
  
  static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
-       .dpms = tegra_crtc_dpms,
+       .disable = tegra_crtc_disable,
        .mode_fixup = tegra_crtc_mode_fixup,
        .mode_set = tegra_crtc_mode_set,
+       .mode_set_base = tegra_crtc_mode_set_base,
        .prepare = tegra_crtc_prepare,
        .commit = tegra_crtc_commit,
        .load_lut = tegra_crtc_load_lut,
  };
  
- static irqreturn_t tegra_drm_irq(int irq, void *data)
+ static irqreturn_t tegra_dc_irq(int irq, void *data)
  {
        struct tegra_dc *dc = data;
        unsigned long status;
                dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
                */
                drm_handle_vblank(dc->base.dev, dc->pipe);
+               tegra_dc_finish_page_flip(dc);
        }
  
        if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
@@@ -587,7 -946,7 +945,7 @@@ static int tegra_dc_show_regs(struct se
        DUMP_REG(DC_WIN_BLEND_1WIN);
        DUMP_REG(DC_WIN_BLEND_2WIN_X);
        DUMP_REG(DC_WIN_BLEND_2WIN_Y);
-       DUMP_REG(DC_WIN_BLEND32WIN_XY);
+       DUMP_REG(DC_WIN_BLEND_3WIN_XY);
        DUMP_REG(DC_WIN_HP_FETCH_CONTROL);
        DUMP_REG(DC_WINBUF_START_ADDR);
        DUMP_REG(DC_WINBUF_START_ADDR_NS);
@@@ -689,13 -1048,17 +1047,17 @@@ static int tegra_dc_drm_init(struct hos
                return err;
        }
  
+       err = tegra_dc_add_planes(drm, dc);
+       if (err < 0)
+               return err;
        if (IS_ENABLED(CONFIG_DEBUG_FS)) {
                err = tegra_dc_debugfs_init(dc, drm->primary);
                if (err < 0)
                        dev_err(dc->dev, "debugfs setup failed: %d\n", err);
        }
  
-       err = devm_request_irq(dc->dev, dc->irq, tegra_drm_irq, 0,
+       err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
                               dev_name(dc->dev), dc);
        if (err < 0) {
                dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
@@@ -744,6 -1107,7 +1106,7 @@@ static int tegra_dc_probe(struct platfo
        if (!dc)
                return -ENOMEM;
  
+       spin_lock_init(&dc->lock);
        INIT_LIST_HEAD(&dc->list);
        dc->dev = &pdev->dev;
  
                return -ENXIO;
        }
  
 -      dc->regs = devm_request_and_ioremap(&pdev->dev, regs);
 -      if (!dc->regs) {
 -              dev_err(&pdev->dev, "failed to remap registers\n");
 -              return -ENXIO;
 -      }
 +      dc->regs = devm_ioremap_resource(&pdev->dev, regs);
 +      if (IS_ERR(dc->regs))
 +              return PTR_ERR(dc->regs);
  
        dc->irq = platform_get_irq(pdev, 0);
        if (dc->irq < 0) {
index d980dc75788c1515258698c5457a02be7e4cf794,181a370c56c11dd059655ec374fa13ddd1c9deb4..9d452df5bcade8cd34cda8d71582fe9679a1eba0
@@@ -11,6 -11,7 +11,6 @@@
  #include <linux/of_address.h>
  #include <linux/of_platform.h>
  
 -#include <mach/clk.h>
  #include <linux/dma-mapping.h>
  #include <asm/dma-iommu.h>
  
@@@ -39,6 -40,10 +39,10 @@@ static int tegra_drm_load(struct drm_de
        if (err < 0)
                return err;
  
+       err = drm_vblank_init(drm, drm->mode_config.num_crtc);
+       if (err < 0)
+               return err;
        err = tegra_drm_fb_init(drm);
        if (err < 0)
                return err;
@@@ -88,13 -93,112 +92,112 @@@ static const struct file_operations teg
        .llseek = noop_llseek,
  };
  
+ static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe)
+ {
+       struct drm_crtc *crtc;
+       list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) {
+               struct tegra_dc *dc = to_tegra_dc(crtc);
+               if (dc->pipe == pipe)
+                       return crtc;
+       }
+       return NULL;
+ }
+ static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc)
+ {
+       /* TODO: implement real hardware counter using syncpoints */
+       return drm_vblank_count(dev, crtc);
+ }
+ static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
+ {
+       struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
+       struct tegra_dc *dc = to_tegra_dc(crtc);
+       if (!crtc)
+               return -ENODEV;
+       tegra_dc_enable_vblank(dc);
+       return 0;
+ }
+ static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe)
+ {
+       struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
+       struct tegra_dc *dc = to_tegra_dc(crtc);
+       if (crtc)
+               tegra_dc_disable_vblank(dc);
+ }
+ static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
+ {
+       struct drm_crtc *crtc;
+       list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
+               tegra_dc_cancel_page_flip(crtc, file);
+ }
+ #ifdef CONFIG_DEBUG_FS
+ static int tegra_debugfs_framebuffers(struct seq_file *s, void *data)
+ {
+       struct drm_info_node *node = (struct drm_info_node *)s->private;
+       struct drm_device *drm = node->minor->dev;
+       struct drm_framebuffer *fb;
+       mutex_lock(&drm->mode_config.fb_lock);
+       list_for_each_entry(fb, &drm->mode_config.fb_list, head) {
+               seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n",
+                          fb->base.id, fb->width, fb->height, fb->depth,
+                          fb->bits_per_pixel,
+                          atomic_read(&fb->refcount.refcount));
+       }
+       mutex_unlock(&drm->mode_config.fb_lock);
+       return 0;
+ }
+ static struct drm_info_list tegra_debugfs_list[] = {
+       { "framebuffers", tegra_debugfs_framebuffers, 0 },
+ };
+ static int tegra_debugfs_init(struct drm_minor *minor)
+ {
+       return drm_debugfs_create_files(tegra_debugfs_list,
+                                       ARRAY_SIZE(tegra_debugfs_list),
+                                       minor->debugfs_root, minor);
+ }
+ static void tegra_debugfs_cleanup(struct drm_minor *minor)
+ {
+       drm_debugfs_remove_files(tegra_debugfs_list,
+                                ARRAY_SIZE(tegra_debugfs_list), minor);
+ }
+ #endif
  struct drm_driver tegra_drm_driver = {
        .driver_features = DRIVER_BUS_PLATFORM | DRIVER_MODESET | DRIVER_GEM,
        .load = tegra_drm_load,
        .unload = tegra_drm_unload,
        .open = tegra_drm_open,
+       .preclose = tegra_drm_preclose,
        .lastclose = tegra_drm_lastclose,
  
+       .get_vblank_counter = tegra_drm_get_vblank_counter,
+       .enable_vblank = tegra_drm_enable_vblank,
+       .disable_vblank = tegra_drm_disable_vblank,
+ #if defined(CONFIG_DEBUG_FS)
+       .debugfs_init = tegra_debugfs_init,
+       .debugfs_cleanup = tegra_debugfs_cleanup,
+ #endif
        .gem_free_object = drm_gem_cma_free_object,
        .gem_vm_ops = &drm_gem_cma_vm_ops,
        .dumb_create = drm_gem_cma_dumb_create,
index d4f3fb9f0c298a9e925109db333cf79f70b68af2,0daee8e2578b4d46fe47444cfc9db45d114034b0..bb747f6cd1a44a30e49d0bdac9f607d0841a3f45
  #include <linux/clk.h>
  #include <linux/debugfs.h>
  #include <linux/gpio.h>
+ #include <linux/hdmi.h>
  #include <linux/module.h>
  #include <linux/of.h>
  #include <linux/platform_device.h>
  #include <linux/regulator/consumer.h>
 -
 -#include <mach/clk.h>
 +#include <linux/clk/tegra.h>
  
+ #include <drm/drm_edid.h>
  #include "hdmi.h"
  #include "drm.h"
  #include "dc.h"
@@@ -400,54 -404,65 +403,65 @@@ static int tegra_hdmi_setup_audio(struc
        return 0;
  }
  
- static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi,
-                                     unsigned int offset, u8 type,
-                                     u8 version, void *data, size_t size)
+ static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size)
  {
-       unsigned long value;
-       u8 *ptr = data;
-       u32 subpack[2];
+       unsigned long value = 0;
        size_t i;
-       u8 csum;
  
-       /* first byte of data is the checksum */
-       csum = type + version + size - 1;
+       for (i = size; i > 0; i--)
+               value = (value << 8) | ptr[i - 1];
  
-       for (i = 1; i < size; i++)
-               csum += ptr[i];
+       return value;
+ }
  
-       ptr[0] = 0x100 - csum;
+ static void tegra_hdmi_write_infopack(struct tegra_hdmi *hdmi, const void *data,
+                                     size_t size)
+ {
+       const u8 *ptr = data;
+       unsigned long offset;
+       unsigned long value;
+       size_t i, j;
  
-       value = INFOFRAME_HEADER_TYPE(type) |
-               INFOFRAME_HEADER_VERSION(version) |
-               INFOFRAME_HEADER_LEN(size - 1);
-       tegra_hdmi_writel(hdmi, value, offset);
+       switch (ptr[0]) {
+       case HDMI_INFOFRAME_TYPE_AVI:
+               offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER;
+               break;
  
-       /* The audio inforame only has one set of subpack registers.  The hdmi
-        * block pads the rest of the data as per the spec so we have to fixup
-        * the length before filling in the subpacks.
-        */
-       if (offset == HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER)
-               size = 6;
+       case HDMI_INFOFRAME_TYPE_AUDIO:
+               offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER;
+               break;
  
-       /* each subpack 7 bytes devided into:
-        *   subpack_low - bytes 0 - 3
-        *   subpack_high - bytes 4 - 6 (with byte 7 padded to 0x00)
-        */
-       for (i = 0; i < size; i++) {
-               size_t index = i % 7;
+       case HDMI_INFOFRAME_TYPE_VENDOR:
+               offset = HDMI_NV_PDISP_HDMI_GENERIC_HEADER;
+               break;
+       default:
+               dev_err(hdmi->dev, "unsupported infoframe type: %02x\n",
+                       ptr[0]);
+               return;
+       }
  
-               if (index == 0)
-                       memset(subpack, 0x0, sizeof(subpack));
+       value = INFOFRAME_HEADER_TYPE(ptr[0]) |
+               INFOFRAME_HEADER_VERSION(ptr[1]) |
+               INFOFRAME_HEADER_LEN(ptr[2]);
+       tegra_hdmi_writel(hdmi, value, offset);
+       offset++;
  
-               ((u8 *)subpack)[index] = ptr[i];
+       /*
+        * Each subpack contains 7 bytes, divided into:
+        * - subpack_low: bytes 0 - 3
+        * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
+        */
+       for (i = 3, j = 0; i < size; i += 7, j += 8) {
+               size_t rem = size - i, num = min_t(size_t, rem, 4);
  
-               if (index == 6 || (i + 1 == size)) {
-                       unsigned int reg = offset + 1 + (i / 7) * 2;
+               value = tegra_hdmi_subpack(&ptr[i], num);
+               tegra_hdmi_writel(hdmi, value, offset++);
  
-                       tegra_hdmi_writel(hdmi, subpack[0], reg);
-                       tegra_hdmi_writel(hdmi, subpack[1], reg + 1);
-               }
+               num = min_t(size_t, rem - num, 3);
+               value = tegra_hdmi_subpack(&ptr[i + 4], num);
+               tegra_hdmi_writel(hdmi, value, offset++);
        }
  }
  
@@@ -455,9 -470,8 +469,8 @@@ static void tegra_hdmi_setup_avi_infofr
                                           struct drm_display_mode *mode)
  {
        struct hdmi_avi_infoframe frame;
-       unsigned int h_front_porch;
-       unsigned int hsize = 16;
-       unsigned int vsize = 9;
+       u8 buffer[17];
+       ssize_t err;
  
        if (hdmi->dvi) {
                tegra_hdmi_writel(hdmi, 0,
                return;
        }
  
-       h_front_porch = mode->hsync_start - mode->hdisplay;
-       memset(&frame, 0, sizeof(frame));
-       frame.r = HDMI_AVI_R_SAME;
-       switch (mode->vdisplay) {
-       case 480:
-               if (mode->hdisplay == 640) {
-                       frame.m = HDMI_AVI_M_4_3;
-                       frame.vic = 1;
-               } else {
-                       frame.m = HDMI_AVI_M_16_9;
-                       frame.vic = 3;
-               }
-               break;
-       case 576:
-               if (((hsize * 10) / vsize) > 14) {
-                       frame.m = HDMI_AVI_M_16_9;
-                       frame.vic = 18;
-               } else {
-                       frame.m = HDMI_AVI_M_4_3;
-                       frame.vic = 17;
-               }
-               break;
-       case 720:
-       case 1470: /* stereo mode */
-               frame.m = HDMI_AVI_M_16_9;
-               if (h_front_porch == 110)
-                       frame.vic = 4;
-               else
-                       frame.vic = 19;
-               break;
-       case 1080:
-       case 2205: /* stereo mode */
-               frame.m = HDMI_AVI_M_16_9;
-               switch (h_front_porch) {
-               case 88:
-                       frame.vic = 16;
-                       break;
-               case 528:
-                       frame.vic = 31;
-                       break;
-               default:
-                       frame.vic = 32;
-                       break;
-               }
-               break;
+       err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+       if (err < 0) {
+               dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
+               return;
+       }
  
-       default:
-               frame.m = HDMI_AVI_M_16_9;
-               frame.vic = 0;
-               break;
+       err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
+       if (err < 0) {
+               dev_err(hdmi->dev, "failed to pack AVI infoframe: %zd\n", err);
+               return;
        }
  
-       tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER,
-                                 HDMI_INFOFRAME_TYPE_AVI, HDMI_AVI_VERSION,
-                                 &frame, sizeof(frame));
+       tegra_hdmi_write_infopack(hdmi, buffer, err);
  
        tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
                          HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
  static void tegra_hdmi_setup_audio_infoframe(struct tegra_hdmi *hdmi)
  {
        struct hdmi_audio_infoframe frame;
+       u8 buffer[14];
+       ssize_t err;
  
        if (hdmi->dvi) {
                tegra_hdmi_writel(hdmi, 0,
                return;
        }
  
-       memset(&frame, 0, sizeof(frame));
-       frame.cc = HDMI_AUDIO_CC_2;
+       err = hdmi_audio_infoframe_init(&frame);
+       if (err < 0) {
+               dev_err(hdmi->dev, "failed to initialize audio infoframe: %d\n",
+                       err);
+               return;
+       }
+       frame.channels = 2;
+       err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
+       if (err < 0) {
+               dev_err(hdmi->dev, "failed to pack audio infoframe: %zd\n",
+                       err);
+               return;
+       }
  
-       tegra_hdmi_write_infopack(hdmi,
-                                 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER,
-                                 HDMI_INFOFRAME_TYPE_AUDIO,
-                                 HDMI_AUDIO_VERSION,
-                                 &frame, sizeof(frame));
+       /*
+        * The audio infoframe has only one set of subpack registers, so the
+        * infoframe needs to be truncated. One set of subpack registers can
+        * contain 7 bytes. Including the 3 byte header only the first 10
+        * bytes can be programmed.
+        */
+       tegra_hdmi_write_infopack(hdmi, buffer, min(10, err));
  
        tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
                          HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
  
  static void tegra_hdmi_setup_stereo_infoframe(struct tegra_hdmi *hdmi)
  {
-       struct hdmi_stereo_infoframe frame;
+       struct hdmi_vendor_infoframe frame;
        unsigned long value;
+       u8 buffer[10];
+       ssize_t err;
  
        if (!hdmi->stereo) {
                value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
        }
  
        memset(&frame, 0, sizeof(frame));
-       frame.regid0 = 0x03;
-       frame.regid1 = 0x0c;
-       frame.regid2 = 0x00;
-       frame.hdmi_video_format = 2;
+       frame.type = HDMI_INFOFRAME_TYPE_VENDOR;
+       frame.version = 0x01;
+       frame.length = 6;
+       frame.data[0] = 0x03; /* regid0 */
+       frame.data[1] = 0x0c; /* regid1 */
+       frame.data[2] = 0x00; /* regid2 */
+       frame.data[3] = 0x02 << 5; /* video format */
  
        /* TODO: 74 MHz limit? */
        if (1) {
-               frame._3d_structure = 0;
+               frame.data[4] = 0x00 << 4; /* 3D structure */
        } else {
-               frame._3d_structure = 8;
-               frame._3d_ext_data = 0;
+               frame.data[4] = 0x08 << 4; /* 3D structure */
+               frame.data[5] = 0x00 << 4; /* 3D ext. data */
+       }
+       err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
+       if (err < 0) {
+               dev_err(hdmi->dev, "failed to pack vendor infoframe: %zd\n",
+                       err);
+               return;
        }
  
-       tegra_hdmi_write_infopack(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_HEADER,
-                                 HDMI_INFOFRAME_TYPE_VENDOR,
-                                 HDMI_VENDOR_VERSION, &frame, 6);
+       tegra_hdmi_write_infopack(hdmi, buffer, err);
  
        value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
        value |= GENERIC_CTRL_ENABLE;
@@@ -1258,9 -1251,9 +1250,9 @@@ static int tegra_hdmi_probe(struct plat
        if (!regs)
                return -ENXIO;
  
 -      hdmi->regs = devm_request_and_ioremap(&pdev->dev, regs);
 -      if (!hdmi->regs)
 -              return -EADDRNOTAVAIL;
 +      hdmi->regs = devm_ioremap_resource(&pdev->dev, regs);
 +      if (IS_ERR(hdmi->regs))
 +              return PTR_ERR(hdmi->regs);
  
        err = platform_get_irq(pdev, 0);
        if (err < 0)
index 43d5c8b8e7ad05681e758d23727fa680595c62f3,f1e7b86a7c3764569bda7e88996ce4d89cda0e8f..0099667a397efb3d11edfd582eb4aa4fa3c78009
@@@ -46,8 -46,6 +46,8 @@@
  #include <asm/cacheflush.h>
  #include <asm/iommu.h>
  
 +#include "irq_remapping.h"
 +
  #define ROOT_SIZE             VTD_PAGE_SIZE
  #define CONTEXT_SIZE          VTD_PAGE_SIZE
  
@@@ -4255,13 -4253,19 +4255,19 @@@ static void quirk_iommu_rwbf(struct pci
  {
        /*
         * Mobile 4 Series Chipset neglects to set RWBF capability,
-        * but needs it:
+        * but needs it. Same seems to hold for the desktop versions.
         */
        printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
        rwbf_quirk = 1;
  }
  
  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
  
  #define GGC 0x52
  #define GGC_MEMORY_SIZE_MASK  (0xf << 8)
diff --combined drivers/staging/Kconfig
index 3a7965d6ac28a69ff43d0747f191477ae419e75e,eca907bf8b6d4d4878b0ee3890c5fd4987bb7a3c..093f10c88ccef5cefb5905a4a7aa4a8aa1acde40
@@@ -74,6 -74,8 +74,6 @@@ source "drivers/staging/iio/Kconfig
  
  source "drivers/staging/zram/Kconfig"
  
 -source "drivers/staging/zcache/Kconfig"
 -
  source "drivers/staging/zsmalloc/Kconfig"
  
  source "drivers/staging/wlags49_h2/Kconfig"
@@@ -112,8 -114,6 +112,6 @@@ source "drivers/staging/media/Kconfig
  
  source "drivers/staging/net/Kconfig"
  
- source "drivers/staging/omapdrm/Kconfig"
  source "drivers/staging/android/Kconfig"
  
  source "drivers/staging/ozwpan/Kconfig"
@@@ -126,6 -126,8 +124,6 @@@ source "drivers/staging/csr/Kconfig
  
  source "drivers/staging/omap-thermal/Kconfig"
  
 -source "drivers/staging/ramster/Kconfig"
 -
  source "drivers/staging/silicom/Kconfig"
  
  source "drivers/staging/ced1401/Kconfig"
@@@ -138,8 -140,4 +136,8 @@@ source "drivers/staging/sb105x/Kconfig
  
  source "drivers/staging/fwserial/Kconfig"
  
 +source "drivers/staging/zcache/Kconfig"
 +
 +source "drivers/staging/goldfish/Kconfig"
 +
  endif # STAGING
diff --combined drivers/staging/Makefile
index 5971865d0c61017ff5bcfa12dc1f9efdb79874d7,d810ed729add5efc30f2045f8b619f5155735329..fa41b04cf4cb7e49a38af98dfa9fd0c519c5d940
@@@ -31,6 -31,7 +31,6 @@@ obj-$(CONFIG_VME_BUS)         += vme
  obj-$(CONFIG_DX_SEP)            += sep/
  obj-$(CONFIG_IIO)             += iio/
  obj-$(CONFIG_ZRAM)            += zram/
 -obj-$(CONFIG_ZCACHE)          += zcache/
  obj-$(CONFIG_ZSMALLOC)                += zsmalloc/
  obj-$(CONFIG_WLAGS49_H2)      += wlags49_h2/
  obj-$(CONFIG_WLAGS49_H25)     += wlags49_h25/
@@@ -48,18 -49,16 +48,17 @@@ obj-$(CONFIG_SPEAKUP)              += speakup
  obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217)     += cptm1217/
  obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)  += ste_rmi4/
  obj-$(CONFIG_MFD_NVEC)                += nvec/
- obj-$(CONFIG_DRM_OMAP)                += omapdrm/
  obj-$(CONFIG_ANDROID)         += android/
  obj-$(CONFIG_USB_WPAN_HCD)    += ozwpan/
  obj-$(CONFIG_USB_G_CCG)               += ccg/
  obj-$(CONFIG_WIMAX_GDM72XX)   += gdm72xx/
  obj-$(CONFIG_CSR_WIFI)                += csr/
  obj-$(CONFIG_OMAP_BANDGAP)    += omap-thermal/
 -obj-$(CONFIG_ZCACHE2)         += ramster/
  obj-$(CONFIG_NET_VENDOR_SILICOM)      += silicom/
  obj-$(CONFIG_CED1401)         += ced1401/
  obj-$(CONFIG_DRM_IMX)         += imx-drm/
  obj-$(CONFIG_DGRP)            += dgrp/
  obj-$(CONFIG_SB105X)          += sb105x/
  obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
 +obj-$(CONFIG_ZCACHE)          += zcache/
 +obj-$(CONFIG_GOLDFISH)                += goldfish/
diff --combined drivers/tty/vt/vt.c
index 6c4abeaf690fcba236bbd43cc8e7d1f28138f505,ed43a7f88b4f3aefd882e7001c0e65768c44c73d..fbd447b390f775fa8182a290266d3d4f41f46e2c
@@@ -539,7 -539,7 +539,7 @@@ static void insert_char(struct vc_data 
  {
        unsigned short *p = (unsigned short *) vc->vc_pos;
  
 -      scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x) * 2);
 +      scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2);
        scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
        vc->vc_need_wrap = 0;
        if (DO_UPDATE(vc))
@@@ -638,7 -638,7 +638,7 @@@ static inline void save_screen(struct v
   *    Redrawing of screen
   */
  
static void clear_buffer_attributes(struct vc_data *vc)
+ void clear_buffer_attributes(struct vc_data *vc)
  {
        unsigned short *p = (unsigned short *)vc->vc_origin;
        int count = vc->vc_screenbuf_size / 2;
@@@ -1333,13 -1333,13 +1333,13 @@@ static void csi_m(struct vc_data *vc
        update_attr(vc);
  }
  
 -static void respond_string(const char *p, struct tty_struct *tty)
 +static void respond_string(const char *p, struct tty_port *port)
  {
        while (*p) {
 -              tty_insert_flip_char(tty, *p, 0);
 +              tty_insert_flip_char(port, *p, 0);
                p++;
        }
 -      tty_schedule_flip(tty);
 +      tty_schedule_flip(port);
  }
  
  static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
        char buf[40];
  
        sprintf(buf, "\033[%d;%dR", vc->vc_y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->vc_x + 1);
 -      respond_string(buf, tty);
 +      respond_string(buf, tty->port);
  }
  
  static inline void status_report(struct tty_struct *tty)
  {
 -      respond_string("\033[0n", tty); /* Terminal ok */
 +      respond_string("\033[0n", tty->port);   /* Terminal ok */
  }
  
 -static inline void respond_ID(struct tty_struct * tty)
 +static inline void respond_ID(struct tty_struct *tty)
  {
 -      respond_string(VT102ID, tty);
 +      respond_string(VT102ID, tty->port);
  }
  
  void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry)
  
        sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
                (char)('!' + mry));
 -      respond_string(buf, tty);
 +      respond_string(buf, tty->port);
  }
  
  /* invoked via ioctl(TIOCLINUX) and through set_selection */
@@@ -2987,7 -2987,7 +2987,7 @@@ int __init vty_init(const struct file_o
  
  static struct class *vtconsole_class;
  
- static int bind_con_driver(const struct consw *csw, int first, int last,
+ static int do_bind_con_driver(const struct consw *csw, int first, int last,
                           int deflt)
  {
        struct module *owner = csw->owner;
        if (!try_module_get(owner))
                return -ENODEV;
  
-       console_lock();
+       WARN_CONSOLE_UNLOCKED();
  
        /* check if driver is registered */
        for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
  
        retval = 0;
  err:
-       console_unlock();
        module_put(owner);
        return retval;
  };
  
+ static int bind_con_driver(const struct consw *csw, int first, int last,
+                          int deflt)
+ {
+       int ret;
+       console_lock();
+       ret = do_bind_con_driver(csw, first, last, deflt);
+       console_unlock();
+       return ret;
+ }
  #ifdef CONFIG_VT_HW_CONSOLE_BINDING
  static int con_is_graphics(const struct consw *csw, int first, int last)
  {
   * or 0 on success.
   */
  int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
+ {
+       int retval;
+       console_lock();
+       retval = do_unbind_con_driver(csw, first, last, deflt);
+       console_unlock();
+       return retval;
+ }
+ EXPORT_SYMBOL(unbind_con_driver);
+ /* unlocked version of unbind_con_driver() */
+ int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
  {
        struct module *owner = csw->owner;
        const struct consw *defcsw = NULL;
        if (!try_module_get(owner))
                return -ENODEV;
  
-       console_lock();
+       WARN_CONSOLE_UNLOCKED();
  
        /* check if driver is registered and if it is unbindable */
        for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
                }
        }
  
-       if (retval) {
-               console_unlock();
+       if (retval)
                goto err;
-       }
  
        retval = -ENODEV;
  
                }
        }
  
-       if (retval) {
-               console_unlock();
+       if (retval)
                goto err;
-       }
  
-       if (!con_is_bound(csw)) {
-               console_unlock();
+       if (!con_is_bound(csw))
                goto err;
-       }
  
        first = max(first, con_driver->first);
        last = min(last, con_driver->last);
        if (!con_is_bound(csw))
                con_driver->flag &= ~CON_DRIVER_FLAG_INIT;
  
-       console_unlock();
        /* ignore return value, binding should not fail */
-       bind_con_driver(defcsw, first, last, deflt);
+       do_bind_con_driver(defcsw, first, last, deflt);
  err:
        module_put(owner);
        return retval;
  
  }
- EXPORT_SYMBOL(unbind_con_driver);
+ EXPORT_SYMBOL_GPL(do_unbind_con_driver);
  
  static int vt_bind(struct con_driver *con)
  {
@@@ -3492,28 -3508,18 +3508,18 @@@ int con_debug_leave(void
  }
  EXPORT_SYMBOL_GPL(con_debug_leave);
  
- /**
-  * register_con_driver - register console driver to console layer
-  * @csw: console driver
-  * @first: the first console to take over, minimum value is 0
-  * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
-  *
-  * DESCRIPTION: This function registers a console driver which can later
-  * bind to a range of consoles specified by @first and @last. It will
-  * also initialize the console driver by calling con_startup().
-  */
- int register_con_driver(const struct consw *csw, int first, int last)
+ static int do_register_con_driver(const struct consw *csw, int first, int last)
  {
        struct module *owner = csw->owner;
        struct con_driver *con_driver;
        const char *desc;
        int i, retval = 0;
  
+       WARN_CONSOLE_UNLOCKED();
        if (!try_module_get(owner))
                return -ENODEV;
  
-       console_lock();
        for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
                con_driver = &registered_con_driver[i];
  
        }
  
  err:
-       console_unlock();
        module_put(owner);
        return retval;
  }
+ /**
+  * register_con_driver - register console driver to console layer
+  * @csw: console driver
+  * @first: the first console to take over, minimum value is 0
+  * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
+  *
+  * DESCRIPTION: This function registers a console driver which can later
+  * bind to a range of consoles specified by @first and @last. It will
+  * also initialize the console driver by calling con_startup().
+  */
+ int register_con_driver(const struct consw *csw, int first, int last)
+ {
+       int retval;
+       console_lock();
+       retval = do_register_con_driver(csw, first, last);
+       console_unlock();
+       return retval;
+ }
  EXPORT_SYMBOL(register_con_driver);
  
  /**
   */
  int unregister_con_driver(const struct consw *csw)
  {
-       int i, retval = -ENODEV;
+       int retval;
  
        console_lock();
+       retval = do_unregister_con_driver(csw);
+       console_unlock();
+       return retval;
+ }
+ EXPORT_SYMBOL(unregister_con_driver);
+ int do_unregister_con_driver(const struct consw *csw)
+ {
+       int i, retval = -ENODEV;
  
        /* cannot unregister a bound driver */
        if (con_is_bound(csw))
                }
        }
  err:
-       console_unlock();
        return retval;
  }
- EXPORT_SYMBOL(unregister_con_driver);
+ EXPORT_SYMBOL_GPL(do_unregister_con_driver);
  
  /*
   *    If we support more console drivers, this function is used
   *    when a driver wants to take over some existing consoles
   *    and become default driver for newly opened ones.
   *
-  *      take_over_console is basically a register followed by unbind
+  *    take_over_console is basically a register followed by unbind
+  */
+ int do_take_over_console(const struct consw *csw, int first, int last, int deflt)
+ {
+       int err;
+       err = do_register_con_driver(csw, first, last);
+       /*
+        * If we get an busy error we still want to bind the console driver
+        * and return success, as we may have unbound the console driver
+        * but not unregistered it.
+        */
+       if (err == -EBUSY)
+               err = 0;
+       if (!err)
+               do_bind_con_driver(csw, first, last, deflt);
+       return err;
+ }
+ EXPORT_SYMBOL_GPL(do_take_over_console);
+ /*
+  *    If we support more console drivers, this function is used
+  *    when a driver wants to take over some existing consoles
+  *    and become default driver for newly opened ones.
+  *
+  *    take_over_console is basically a register followed by unbind
   */
  int take_over_console(const struct consw *csw, int first, int last, int deflt)
  {
        int err;
  
        err = register_con_driver(csw, first, last);
-       /* if we get an busy error we still want to bind the console driver
+       /*
+        * If we get an busy error we still want to bind the console driver
         * and return success, as we may have unbound the console driver
-       Â * but not unregistered it.
-       */
+        * but not unregistered it.
+        */
        if (err == -EBUSY)
                err = 0;
        if (!err)
diff --combined drivers/video/Kconfig
index 80cbd21b483f939912e58143d888d5ef426d0b83,b11eeab941510fe56a076668bb6a6f9ee87db693..4c1546f71d56a2be51785f3bf02ab50437ac94d6
@@@ -21,8 -21,6 +21,6 @@@ source "drivers/gpu/vga/Kconfig
  
  source "drivers/gpu/drm/Kconfig"
  
- source "drivers/gpu/stub/Kconfig"
  config VGASTATE
         tristate
         default n
@@@ -33,6 -31,30 +31,30 @@@ config VIDEO_OUTPUT_CONTRO
          This framework adds support for low-level control of the video 
          output switch.
  
+ config DISPLAY_TIMING
+        bool
+ config VIDEOMODE
+        bool
+ config OF_DISPLAY_TIMING
+       bool "Enable device tree display timing support"
+       depends on OF
+       select DISPLAY_TIMING
+       help
+         helper to parse display timings from the devicetree
+ config OF_VIDEOMODE
+       bool "Enable device tree videomode support"
+       depends on OF
+       select VIDEOMODE
+       select OF_DISPLAY_TIMING
+       help
+         helper to get videomodes from the devicetree
+ config HDMI
+       bool
  menuconfig FB
        tristate "Support for frame buffer devices"
        ---help---
@@@ -364,7 -386,7 +386,7 @@@ config FB_SA110
          Y here.
  
  config FB_IMX
 -      tristate "Freescale i.MX LCD support"
 +      tristate "Freescale i.MX1/21/25/27 LCD support"
        depends on FB && IMX_HAVE_PLATFORM_IMX_FB
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@@ -1112,8 -1134,8 +1134,8 @@@ config FB_RIVA_BACKLIGH
          Say Y here if you want to control the backlight of your display.
  
  config FB_I740
 -      tristate "Intel740 support (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL && FB && PCI
 +      tristate "Intel740 support"
 +      depends on FB && PCI
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
          This driver supports graphics cards based on Intel740 chip.
  
  config FB_I810
 -      tristate "Intel 810/815 support (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
 +      tristate "Intel 810/815 support"
 +      depends on FB && PCI && X86_32 && AGP_INTEL
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@@ -1187,8 -1209,8 +1209,8 @@@ config FB_CARILLO_RANC
          This driver supports the LE80578 (Carillo Ranch) board
  
  config FB_INTEL
 -      tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL && EXPERT
 +      tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support"
 +      depends on FB && PCI && X86 && AGP_INTEL && EXPERT
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@@ -1432,7 -1454,7 +1454,7 @@@ config FB_ATY_C
          is at <http://support.ati.com/products/pc/mach64/mach64.html>.
  
  config FB_ATY_GENERIC_LCD
 -      bool "Mach64 generic LCD support (EXPERIMENTAL)"
 +      bool "Mach64 generic LCD support"
        depends on FB_ATY_CT
        help
          Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
@@@ -1479,7 -1501,7 +1501,7 @@@ config FB_S3_DD
  
  config FB_SAVAGE
        tristate "S3 Savage support"
 -      depends on FB && PCI && EXPERIMENTAL
 +      depends on FB && PCI
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@@ -1633,15 -1655,15 +1655,15 @@@ config FB_3DF
          module will be called tdfxfb.
  
  config FB_3DFX_ACCEL
 -      bool "3Dfx Acceleration functions (EXPERIMENTAL)"
 -      depends on FB_3DFX && EXPERIMENTAL
 +      bool "3Dfx Acceleration functions"
 +      depends on FB_3DFX
        ---help---
        This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
        device driver with acceleration functions.
  
  config FB_3DFX_I2C
        bool "Enable DDC/I2C support"
 -      depends on FB_3DFX && EXPERIMENTAL
 +      depends on FB_3DFX
        select FB_DDC
        default y
        help
@@@ -1714,8 -1736,8 +1736,8 @@@ config FB_AR
          and ICS 5342 RAMDAC.
  
  config FB_PM3
 -      tristate "Permedia3 support (EXPERIMENTAL)"
 -      depends on FB && PCI && EXPERIMENTAL
 +      tristate "Permedia3 support"
 +      depends on FB && PCI
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
@@@ -2025,8 -2047,7 +2047,8 @@@ config FB_TMIO_ACCEL
  
  config FB_S3C
        tristate "Samsung S3C framebuffer support"
 -      depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0)
 +      depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || ARCH_S5P64X0 || \
 +              ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
@@@ -2184,15 -2205,6 +2206,15 @@@ config FB_XILIN
          framebuffer. ML300 carries a 640*480 LCD display on the board,
          ML403 uses a standard DB15 VGA connector.
  
 +config FB_GOLDFISH
 +      tristate "Goldfish Framebuffer"
 +      depends on FB
 +      select FB_CFB_FILLRECT
 +      select FB_CFB_COPYAREA
 +      select FB_CFB_IMAGEBLIT
 +      ---help---
 +        Framebuffer driver for Goldfish Virtual Platform
 +
  config FB_COBALT
        tristate "Cobalt server LCD frame buffer support"
        depends on FB && (MIPS_COBALT || MIPS_SEAD3)
@@@ -2432,7 -2444,6 +2454,7 @@@ config FB_PUV3_UNIGF
  source "drivers/video/omap/Kconfig"
  source "drivers/video/omap2/Kconfig"
  source "drivers/video/exynos/Kconfig"
 +source "drivers/video/mmp/Kconfig"
  source "drivers/video/backlight/Kconfig"
  
  if VT
diff --combined drivers/video/Makefile
index 0577f834fdcdfd55283adef6a80e0f709082f903,0b50082635e32ea6f80505e95c3c1224b9d034a5..9df387334cb7f8ed341b8728267fae3a5afd4dcc
@@@ -5,6 -5,7 +5,7 @@@
  # Each configuration option enables a list of files.
  
  obj-$(CONFIG_VGASTATE)            += vgastate.o
+ obj-$(CONFIG_HDMI)                += hdmi.o
  obj-y                             += fb_notify.o
  obj-$(CONFIG_FB)                  += fb.o
  fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
@@@ -98,7 -99,6 +99,7 @@@ obj-$(CONFIG_FB_ATMEL)                  += atmel_lcdf
  obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
  obj-$(CONFIG_FB_VOODOO1)          += sstfb.o
  obj-$(CONFIG_FB_ARMCLCD)        += amba-clcd.o
 +obj-$(CONFIG_FB_GOLDFISH)         += goldfishfb.o
  obj-$(CONFIG_FB_68328)            += 68328fb.o
  obj-$(CONFIG_FB_GBE)              += gbefb.o
  obj-$(CONFIG_FB_CIRRUS)                 += cirrusfb.o
@@@ -106,7 -106,6 +107,7 @@@ obj-$(CONFIG_FB_ASILIANT)    += asiliant
  obj-$(CONFIG_FB_PXA)            += pxafb.o
  obj-$(CONFIG_FB_PXA168)                 += pxa168fb.o
  obj-$(CONFIG_PXA3XX_GCU)        += pxa3xx-gcu.o
 +obj-$(CONFIG_MMP_DISP)           += mmp/
  obj-$(CONFIG_FB_W100)           += w100fb.o
  obj-$(CONFIG_FB_TMIO)           += tmiofb.o
  obj-$(CONFIG_FB_AU1100)                 += au1100fb.o
@@@ -170,3 -169,7 +171,7 @@@ obj-$(CONFIG_FB_VIRTUAL)          += vf
  
  #video output switch sysfs driver
  obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+ obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
+ obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o
+ obj-$(CONFIG_VIDEOMODE) += videomode.o
+ obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
index f8a61e210d2e63469d3196a97aee5cb704e9f940,501c599e75493b2424877617dc09a8c9fbaa7b12..3cd6759278269d837b444749192fb841521cfcbd
@@@ -529,6 -529,33 +529,33 @@@ static int search_for_mapped_con(void
        return retval;
  }
  
+ static int do_fbcon_takeover(int show_logo)
+ {
+       int err, i;
+       if (!num_registered_fb)
+               return -ENODEV;
+       if (!show_logo)
+               logo_shown = FBCON_LOGO_DONTSHOW;
+       for (i = first_fb_vc; i <= last_fb_vc; i++)
+               con2fb_map[i] = info_idx;
+       err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
+                               fbcon_is_default);
+       if (err) {
+               for (i = first_fb_vc; i <= last_fb_vc; i++)
+                       con2fb_map[i] = -1;
+               info_idx = -1;
+       } else {
+               fbcon_has_console_bind = 1;
+       }
+       return err;
+ }
  static int fbcon_takeover(int show_logo)
  {
        int err, i;
@@@ -815,6 -842,8 +842,8 @@@ static void con2fb_init_display(struct 
   *
   *    Maps a virtual console @unit to a frame buffer device
   *    @newidx.
+  *
+  *    This should be called with the console lock held.
   */
  static int set_con2fb_map(int unit, int newidx, int user)
  {
  
        if (!search_for_mapped_con() || !con_is_bound(&fb_con)) {
                info_idx = newidx;
-               return fbcon_takeover(0);
+               return do_fbcon_takeover(0);
        }
  
        if (oldidx != -1)
  
        found = search_fb_in_map(newidx);
  
-       console_lock();
        con2fb_map[unit] = newidx;
        if (!err && !found)
                err = con2fb_acquire_newinfo(vc, info, unit, oldidx);
        if (!search_fb_in_map(info_idx))
                info_idx = newidx;
  
-       console_unlock();
        return err;
  }
  
@@@ -990,7 -1017,7 +1017,7 @@@ static const char *fbcon_startup(void
        }
  
        /* Setup default font */
-       if (!p->fontdata) {
+       if (!p->fontdata && !vc->vc_font.data) {
                if (!fontname[0] || !(font = find_font(fontname)))
                        font = get_default_font(info->var.xres,
                                                info->var.yres,
                vc->vc_font.height = font->height;
                vc->vc_font.data = (void *)(p->fontdata = font->data);
                vc->vc_font.charcount = 256; /* FIXME  Need to support more fonts */
+       } else {
+               p->fontdata = vc->vc_font.data;
        }
  
        cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
@@@ -1159,9 -1188,9 +1188,9 @@@ static void fbcon_init(struct vc_data *
        ops->p = &fb_display[fg_console];
  }
  
- static void fbcon_free_font(struct display *p)
+ static void fbcon_free_font(struct display *p, bool freefont)
  {
-       if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
+       if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
                kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
        p->fontdata = NULL;
        p->userfont = 0;
@@@ -1173,8 -1202,8 +1202,8 @@@ static void fbcon_deinit(struct vc_dat
        struct fb_info *info;
        struct fbcon_ops *ops;
        int idx;
+       bool free_font = true;
  
-       fbcon_free_font(p);
        idx = con2fb_map[vc->vc_num];
  
        if (idx == -1)
        if (!info)
                goto finished;
  
+       if (info->flags & FBINFO_MISC_FIRMWARE)
+               free_font = false;
        ops = info->fbcon_par;
  
        if (!ops)
        ops->flags &= ~FBCON_FLAGS_INIT;
  finished:
  
+       fbcon_free_font(p, free_font);
        if (!con_is_bound(&fb_con))
                fbcon_exit();
  
@@@ -1242,16 -1275,8 +1275,16 @@@ static void fbcon_clear(struct vc_data 
        if (!height || !width)
                return;
  
 -      if (sy < vc->vc_top && vc->vc_top == logo_lines)
 +      if (sy < vc->vc_top && vc->vc_top == logo_lines) {
                vc->vc_top = 0;
 +              /*
 +               * If the font dimensions are not an integral of the display
 +               * dimensions then the ops->clear below won't end up clearing
 +               * the margins.  Call clear_margins here in case the logo
 +               * bitmap stretched into the margin area.
 +               */
 +              fbcon_clear_margins(vc, 0);
 +      }
  
        /* Split blits that cross physical y_wrap boundary */
  
@@@ -2985,7 -3010,7 +3018,7 @@@ static int fbcon_unbind(void
  {
        int ret;
  
-       ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
+       ret = do_unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
                                fbcon_is_default);
  
        if (!ret)
@@@ -3000,6 -3025,7 +3033,7 @@@ static inline int fbcon_unbind(void
  }
  #endif /* CONFIG_VT_HW_CONSOLE_BINDING */
  
+ /* called with console_lock held */
  static int fbcon_fb_unbind(int idx)
  {
        int i, new_idx = -1, ret = 0;
        return ret;
  }
  
+ /* called with console_lock held */
  static int fbcon_fb_unregistered(struct fb_info *info)
  {
        int i, idx;
                primary_device = -1;
  
        if (!num_registered_fb)
-               unregister_con_driver(&fb_con);
+               do_unregister_con_driver(&fb_con);
  
        return 0;
  }
  
+ /* called with console_lock held */
  static void fbcon_remap_all(int idx)
  {
        int i;
@@@ -3107,6 -3135,7 +3143,7 @@@ static inline void fbcon_select_primary
  }
  #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */
  
+ /* called with console_lock held */
  static int fbcon_fb_registered(struct fb_info *info)
  {
        int ret = 0, i, idx;
                }
  
                if (info_idx != -1)
-                       ret = fbcon_takeover(1);
+                       ret = do_fbcon_takeover(1);
        } else {
                for (i = first_fb_vc; i <= last_fb_vc; i++) {
                        if (con2fb_map_boot[i] == idx)
@@@ -3259,6 -3288,7 +3296,7 @@@ static int fbcon_event_notify(struct no
                ret = fbcon_fb_unregistered(info);
                break;
        case FB_EVENT_SET_CONSOLE_MAP:
+               /* called with console lock held */
                con2fb = event->data;
                ret = set_con2fb_map(con2fb->console - 1,
                                     con2fb->framebuffer, 1);
diff --combined include/linux/console.h
index 3b709da1786e314bd665da41ae9324567b38313e,47b858cffc478ce21bd4fc89bd0ac740dfa5cb50..29680a8cda9979a1a717d46afb909b900f5e7ab2
@@@ -77,7 -77,9 +77,9 @@@ extern const struct consw prom_con;   /* 
  int con_is_bound(const struct consw *csw);
  int register_con_driver(const struct consw *csw, int first, int last);
  int unregister_con_driver(const struct consw *csw);
+ int do_unregister_con_driver(const struct consw *csw);
  int take_over_console(const struct consw *sw, int first, int last, int deflt);
+ int do_take_over_console(const struct consw *sw, int first, int last, int deflt);
  void give_up_console(const struct consw *sw);
  #ifdef CONFIG_HW_CONSOLE
  int con_debug_enter(struct vc_data *vc);
@@@ -157,12 -159,7 +159,12 @@@ extern int is_console_locked(void)
  extern int braille_register_console(struct console *, int index,
                char *console_options, char *braille_options);
  extern int braille_unregister_console(struct console *);
 +#ifdef CONFIG_TTY
  extern void console_sysfs_notify(void);
 +#else
 +static inline void console_sysfs_notify(void)
 +{ }
 +#endif
  extern bool console_suspend_enabled;
  
  /* Suspend and resume console messages over PM events */
diff --combined kernel/printk.c
index f24633afa46a5e7c8c3ae9010548fc95c122d825,357f714ddd4983e75e3816577b237d8c8d38bd3f..0b31715f335a7a8ba1a846fe3b93fe71d97cd8d7
@@@ -42,7 -42,6 +42,7 @@@
  #include <linux/notifier.h>
  #include <linux/rculist.h>
  #include <linux/poll.h>
 +#include <linux/irq_work.h>
  
  #include <asm/uaccess.h>
  
@@@ -88,6 -87,12 +88,12 @@@ static DEFINE_SEMAPHORE(console_sem)
  struct console *console_drivers;
  EXPORT_SYMBOL_GPL(console_drivers);
  
+ #ifdef CONFIG_LOCKDEP
+ static struct lockdep_map console_lock_dep_map = {
+       .name = "console_lock"
+ };
+ #endif
  /*
   * This is used for debugging the mess that is the VT code by
   * keeping track if we have the console semaphore held. It's
@@@ -1919,6 -1924,7 +1925,7 @@@ void console_lock(void
                return;
        console_locked = 1;
        console_may_schedule = 1;
+       mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);
  }
  EXPORT_SYMBOL(console_lock);
  
@@@ -1940,6 -1946,7 +1947,7 @@@ int console_trylock(void
        }
        console_locked = 1;
        console_may_schedule = 0;
+       mutex_acquire(&console_lock_dep_map, 0, 1, _RET_IP_);
        return 1;
  }
  EXPORT_SYMBOL(console_trylock);
@@@ -1960,32 -1967,30 +1968,32 @@@ int is_console_locked(void
  static DEFINE_PER_CPU(int, printk_pending);
  static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
  
 -void printk_tick(void)
 +static void wake_up_klogd_work_func(struct irq_work *irq_work)
  {
 -      if (__this_cpu_read(printk_pending)) {
 -              int pending = __this_cpu_xchg(printk_pending, 0);
 -              if (pending & PRINTK_PENDING_SCHED) {
 -                      char *buf = __get_cpu_var(printk_sched_buf);
 -                      printk(KERN_WARNING "[sched_delayed] %s", buf);
 -              }
 -              if (pending & PRINTK_PENDING_WAKEUP)
 -                      wake_up_interruptible(&log_wait);
 +      int pending = __this_cpu_xchg(printk_pending, 0);
 +
 +      if (pending & PRINTK_PENDING_SCHED) {
 +              char *buf = __get_cpu_var(printk_sched_buf);
 +              printk(KERN_WARNING "[sched_delayed] %s", buf);
        }
 -}
  
 -int printk_needs_cpu(int cpu)
 -{
 -      if (cpu_is_offline(cpu))
 -              printk_tick();
 -      return __this_cpu_read(printk_pending);
 +      if (pending & PRINTK_PENDING_WAKEUP)
 +              wake_up_interruptible(&log_wait);
  }
  
 +static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
 +      .func = wake_up_klogd_work_func,
 +      .flags = IRQ_WORK_LAZY,
 +};
 +
  void wake_up_klogd(void)
  {
 -      if (waitqueue_active(&log_wait))
 +      preempt_disable();
 +      if (waitqueue_active(&log_wait)) {
                this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
 +              irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
 +      }
 +      preempt_enable();
  }
  
  static void console_cont_flush(char *text, size_t size)
@@@ -2102,6 -2107,7 +2110,7 @@@ skip
                local_irq_restore(flags);
        }
        console_locked = 0;
+       mutex_release(&console_lock_dep_map, 1, _RET_IP_);
  
        /* Release the exclusive_console once it is used */
        if (unlikely(exclusive_console))
@@@ -2465,7 -2471,6 +2474,7 @@@ int printk_sched(const char *fmt, ...
        va_end(args);
  
        __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED);
 +      irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
        local_irq_restore(flags);
  
        return r;