]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
drm/tegra: Move driver to DRM tree
authorThierry Reding <treding@nvidia.com>
Wed, 9 Oct 2013 08:32:49 +0000 (10:32 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 31 Oct 2013 08:55:40 +0000 (09:55 +0100)
In order to make subsystem-wide changes easier, move the Tegra DRM
driver back into the DRM tree.

Signed-off-by: Thierry Reding <treding@nvidia.com>
35 files changed:
MAINTAINERS
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/tegra/Kconfig [new file with mode: 0644]
drivers/gpu/drm/tegra/Makefile [new file with mode: 0644]
drivers/gpu/drm/tegra/bus.c [new file with mode: 0644]
drivers/gpu/drm/tegra/dc.c [new file with mode: 0644]
drivers/gpu/drm/tegra/dc.h [new file with mode: 0644]
drivers/gpu/drm/tegra/drm.c [new file with mode: 0644]
drivers/gpu/drm/tegra/drm.h [new file with mode: 0644]
drivers/gpu/drm/tegra/fb.c [new file with mode: 0644]
drivers/gpu/drm/tegra/gem.c [new file with mode: 0644]
drivers/gpu/drm/tegra/gem.h [new file with mode: 0644]
drivers/gpu/drm/tegra/gr2d.c [new file with mode: 0644]
drivers/gpu/drm/tegra/hdmi.c [new file with mode: 0644]
drivers/gpu/drm/tegra/hdmi.h [new file with mode: 0644]
drivers/gpu/drm/tegra/output.c [new file with mode: 0644]
drivers/gpu/drm/tegra/rgb.c [new file with mode: 0644]
drivers/gpu/host1x/Kconfig
drivers/gpu/host1x/Makefile
drivers/gpu/host1x/drm/Kconfig [deleted file]
drivers/gpu/host1x/drm/bus.c [deleted file]
drivers/gpu/host1x/drm/dc.c [deleted file]
drivers/gpu/host1x/drm/dc.h [deleted file]
drivers/gpu/host1x/drm/drm.c [deleted file]
drivers/gpu/host1x/drm/drm.h [deleted file]
drivers/gpu/host1x/drm/fb.c [deleted file]
drivers/gpu/host1x/drm/gem.c [deleted file]
drivers/gpu/host1x/drm/gem.h [deleted file]
drivers/gpu/host1x/drm/gr2d.c [deleted file]
drivers/gpu/host1x/drm/hdmi.c [deleted file]
drivers/gpu/host1x/drm/hdmi.h [deleted file]
drivers/gpu/host1x/drm/output.c [deleted file]
drivers/gpu/host1x/drm/rgb.c [deleted file]
drivers/video/Kconfig

index 89f347ae077f233b14b7c672f12dce3843200473..4907a747f3e02fed8cd6ded387cf430adcba0c7e 100644 (file)
@@ -2816,6 +2816,7 @@ L:        dri-devel@lists.freedesktop.org
 L:     linux-tegra@vger.kernel.org
 T:     git git://anongit.freedesktop.org/tegra/linux.git
 S:     Maintained
+F:     drivers/gpu/drm/tegra/
 F:     drivers/gpu/host1x/
 F:     include/linux/host1x.h
 F:     include/uapi/drm/tegra_drm.h
index 955555d6ec881faa6e821903b91f5d8c6b8c150a..290e2ac799f9583184a1bfa22b9f96d77c61ffb3 100644 (file)
@@ -236,3 +236,5 @@ source "drivers/gpu/drm/tilcdc/Kconfig"
 source "drivers/gpu/drm/qxl/Kconfig"
 
 source "drivers/gpu/drm/msm/Kconfig"
+
+source "drivers/gpu/drm/tegra/Kconfig"
index f089adfe70eed3daa21f08b81fcb6d9911ea45c6..e39cd031df762e69b09e612334eded1246ff108a 100644 (file)
@@ -55,4 +55,5 @@ obj-$(CONFIG_DRM_OMAP)        += omapdrm/
 obj-$(CONFIG_DRM_TILCDC)       += tilcdc/
 obj-$(CONFIG_DRM_QXL) += qxl/
 obj-$(CONFIG_DRM_MSM) += msm/
+obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-y                  += i2c/
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
new file mode 100644 (file)
index 0000000..7a092ea
--- /dev/null
@@ -0,0 +1,31 @@
+config DRM_TEGRA
+       bool "NVIDIA Tegra DRM"
+       depends on ARCH_TEGRA || ARCH_MULTIPLATFORM
+       depends on DRM
+       select TEGRA_HOST1X
+       select DRM_KMS_HELPER
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       help
+         Choose this option if you have an NVIDIA Tegra SoC.
+
+         To compile this driver as a module, choose M here: the module
+         will be called tegra-drm.
+
+if DRM_TEGRA
+
+config DRM_TEGRA_DEBUG
+       bool "NVIDIA Tegra DRM debug support"
+       help
+         Say yes here to enable debugging support.
+
+config DRM_TEGRA_STAGING
+       bool "Enable HOST1X interface"
+       depends on STAGING
+       help
+         Say yes if HOST1X should be available for userspace DRM users.
+
+         If unsure, choose N.
+
+endif
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
new file mode 100644 (file)
index 0000000..e1cdf1d
--- /dev/null
@@ -0,0 +1,14 @@
+ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
+
+tegra-drm-y := \
+       bus.o \
+       drm.o \
+       gem.o \
+       fb.o \
+       dc.o \
+       output.o \
+       rgb.o \
+       hdmi.o \
+       gr2d.o
+
+obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
diff --git a/drivers/gpu/drm/tegra/bus.c b/drivers/gpu/drm/tegra/bus.c
new file mode 100644 (file)
index 0000000..565f8f7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "drm.h"
+
+static int drm_host1x_set_busid(struct drm_device *dev,
+                               struct drm_master *master)
+{
+       const char *device = dev_name(dev->dev);
+       const char *driver = dev->driver->name;
+       const char *bus = dev->dev->bus->name;
+       int length;
+
+       master->unique_len = strlen(bus) + 1 + strlen(device);
+       master->unique_size = master->unique_len;
+
+       master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
+       if (!master->unique)
+               return -ENOMEM;
+
+       snprintf(master->unique, master->unique_len + 1, "%s:%s", bus, device);
+
+       length = strlen(driver) + 1 + master->unique_len;
+
+       dev->devname = kmalloc(length + 1, GFP_KERNEL);
+       if (!dev->devname)
+               return -ENOMEM;
+
+       snprintf(dev->devname, length + 1, "%s@%s", driver, master->unique);
+
+       return 0;
+}
+
+static struct drm_bus drm_host1x_bus = {
+       .bus_type = DRIVER_BUS_HOST1X,
+       .set_busid = drm_host1x_set_busid,
+};
+
+int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
+{
+       struct drm_device *drm;
+       int ret;
+
+       INIT_LIST_HEAD(&driver->device_list);
+       driver->bus = &drm_host1x_bus;
+
+       drm = drm_dev_alloc(driver, &device->dev);
+       if (!drm)
+               return -ENOMEM;
+
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               goto err_free;
+
+       DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name,
+                driver->major, driver->minor, driver->patchlevel,
+                driver->date, drm->primary->index);
+
+       return 0;
+
+err_free:
+       drm_dev_free(drm);
+       return ret;
+}
+
+void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device)
+{
+       struct tegra_drm *tegra = dev_get_drvdata(&device->dev);
+
+       drm_put_dev(tegra->drm);
+}
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
new file mode 100644 (file)
index 0000000..588d4ba
--- /dev/null
@@ -0,0 +1,1194 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk/tegra.h>
+#include <linux/debugfs.h>
+
+#include "dc.h"
+#include "drm.h"
+#include "gem.h"
+
+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 tegra_bo *bo = tegra_fb_get_plane(fb, i);
+
+               window.base[i] = bo->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;
+
+       if (!plane->crtc)
+               return 0;
+
+       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_XBGR8888,
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_RGB565,
+       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)
+{
+       unsigned int format = tegra_dc_format(fb->pixel_format);
+       struct tegra_bo *bo = tegra_fb_get_plane(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, bo->paddr + value, DC_WINBUF_START_ADDR);
+       tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
+       tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
+
+       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;
+       unsigned long flags, base;
+       struct tegra_bo *bo;
+
+       if (!dc->event)
+               return;
+
+       bo = tegra_fb_get_plane(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 == bo->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, uint32_t page_flip_flags)
+{
+       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_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,
+                                 const struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted)
+{
+       return true;
+}
+
+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;
+
+       if (v)
+               max = 15;
+       else {
+               switch (bpp) {
+               case 2:
+                       max = 8;
+                       break;
+
+               default:
+                       WARN_ON_ONCE(1);
+                       /* fallthrough */
+               case 4:
+                       max = 4;
+                       break;
+               }
+       }
+
+       outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
+       inf.full -= dfixed_const(1);
+
+       dda_inc = dfixed_div(inf, outf);
+       dda_inc = min_t(u32, dda_inc, dfixed_const(max));
+
+       return dda_inc;
+}
+
+static inline u32 compute_initial_dda(unsigned int in)
+{
+       fixed20_12 inf = dfixed_init(in);
+       return dfixed_frac(inf);
+}
+
+static int tegra_dc_set_timings(struct tegra_dc *dc,
+                               struct drm_display_mode *mode)
+{
+       /* TODO: For HDMI compliance, h & v ref_to_sync should be set to 1 */
+       unsigned int h_ref_to_sync = 0;
+       unsigned int v_ref_to_sync = 0;
+       unsigned long value;
+
+       tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
+
+       value = (v_ref_to_sync << 16) | h_ref_to_sync;
+       tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
+
+       value = ((mode->vsync_end - mode->vsync_start) << 16) |
+               ((mode->hsync_end - mode->hsync_start) <<  0);
+       tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
+
+       value = ((mode->vtotal - mode->vsync_end) << 16) |
+               ((mode->htotal - mode->hsync_end) <<  0);
+       tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
+
+       value = ((mode->vsync_start - mode->vdisplay) << 16) |
+               ((mode->hsync_start - mode->hdisplay) <<  0);
+       tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
+
+       value = (mode->vdisplay << 16) | mode->hdisplay;
+       tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
+
+       return 0;
+}
+
+static int tegra_crtc_setup_clk(struct drm_crtc *crtc,
+                               struct drm_display_mode *mode,
+                               unsigned long *div)
+{
+       unsigned long pclk = mode->clock * 1000, rate;
+       struct tegra_dc *dc = to_tegra_dc(crtc);
+       struct tegra_output *output = NULL;
+       struct drm_encoder *encoder;
+       long err;
+
+       list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head)
+               if (encoder->crtc == crtc) {
+                       output = encoder_to_output(encoder);
+                       break;
+               }
+
+       if (!output)
+               return -ENODEV;
+
+       /*
+        * This assumes that the display controller will divide its parent
+        * clock by 2 to generate the pixel clock.
+        */
+       err = tegra_output_setup_clock(output, dc->clk, pclk * 2);
+       if (err < 0) {
+               dev_err(dc->dev, "failed to setup clock: %ld\n", err);
+               return err;
+       }
+
+       rate = clk_get_rate(dc->clk);
+       *div = (rate * 2 / pclk) - 2;
+
+       DRM_DEBUG_KMS("rate: %lu, div: %lu\n", rate, *div);
+
+       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_XBGR8888:
+               return WIN_COLOR_DEPTH_R8G8B8A8;
+
+       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_bo *bo = tegra_fb_get_plane(crtc->fb, 0);
+       struct tegra_dc *dc = to_tegra_dc(crtc);
+       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);
+               return err;
+       }
+
+       /* program display mode */
+       tegra_dc_set_timings(dc, mode);
+
+       value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
+       tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
+
+       value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1));
+       value &= ~LVS_OUTPUT_POLARITY_LOW;
+       value &= ~LHS_OUTPUT_POLARITY_LOW;
+       tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
+
+       value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
+               DISP_ORDER_RED_BLUE;
+       tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
+
+       tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS);
+
+       value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
+       tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
+
+       /* setup window parameters */
+       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] = bo->paddr;
+
+       err = tegra_dc_setup_window(dc, 0, &window);
+       if (err < 0)
+               dev_err(dc->dev, "failed to enable root plane\n");
+
+       return 0;
+}
+
+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 tegra_dc_set_base(dc, x, y, crtc->fb);
+}
+
+static void tegra_crtc_prepare(struct drm_crtc *crtc)
+{
+       struct tegra_dc *dc = to_tegra_dc(crtc);
+       unsigned int syncpt;
+       unsigned long value;
+
+       /* hardware initialization */
+       tegra_periph_reset_deassert(dc->clk);
+       usleep_range(10000, 20000);
+
+       if (dc->pipe)
+               syncpt = SYNCPT_VBLANK1;
+       else
+               syncpt = SYNCPT_VBLANK0;
+
+       /* initialize display controller */
+       tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
+       tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
+
+       value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
+       tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
+
+       value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
+               WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
+       tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
+
+       value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+               PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
+       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+       value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+       value |= DISP_CTRL_MODE_C_DISPLAY;
+       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+       /* initialize timer */
+       value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
+               WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
+       tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
+
+       value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
+               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_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 value;
+
+       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);
+
+       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 = {
+       .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_dc_irq(int irq, void *data)
+{
+       struct tegra_dc *dc = data;
+       unsigned long status;
+
+       status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
+       tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
+
+       if (status & FRAME_END_INT) {
+               /*
+               dev_dbg(dc->dev, "%s(): frame end\n", __func__);
+               */
+       }
+
+       if (status & VBLANK_INT) {
+               /*
+               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)) {
+               /*
+               dev_dbg(dc->dev, "%s(): underflow\n", __func__);
+               */
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int tegra_dc_show_regs(struct seq_file *s, void *data)
+{
+       struct drm_info_node *node = s->private;
+       struct tegra_dc *dc = node->info_ent->data;
+
+#define DUMP_REG(name)                                         \
+       seq_printf(s, "%-40s %#05x %08lx\n", #name, name,       \
+                  tegra_dc_readl(dc, name))
+
+       DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT);
+       DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
+       DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_ERROR);
+       DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT);
+       DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL);
+       DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_ERROR);
+       DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT);
+       DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL);
+       DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_ERROR);
+       DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT);
+       DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL);
+       DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_ERROR);
+       DUMP_REG(DC_CMD_CONT_SYNCPT_VSYNC);
+       DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
+       DUMP_REG(DC_CMD_DISPLAY_COMMAND);
+       DUMP_REG(DC_CMD_SIGNAL_RAISE);
+       DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL);
+       DUMP_REG(DC_CMD_INT_STATUS);
+       DUMP_REG(DC_CMD_INT_MASK);
+       DUMP_REG(DC_CMD_INT_ENABLE);
+       DUMP_REG(DC_CMD_INT_TYPE);
+       DUMP_REG(DC_CMD_INT_POLARITY);
+       DUMP_REG(DC_CMD_SIGNAL_RAISE1);
+       DUMP_REG(DC_CMD_SIGNAL_RAISE2);
+       DUMP_REG(DC_CMD_SIGNAL_RAISE3);
+       DUMP_REG(DC_CMD_STATE_ACCESS);
+       DUMP_REG(DC_CMD_STATE_CONTROL);
+       DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
+       DUMP_REG(DC_CMD_REG_ACT_CONTROL);
+       DUMP_REG(DC_COM_CRC_CONTROL);
+       DUMP_REG(DC_COM_CRC_CHECKSUM);
+       DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(0));
+       DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(1));
+       DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(2));
+       DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(3));
+       DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(0));
+       DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(1));
+       DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(2));
+       DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(3));
+       DUMP_REG(DC_COM_PIN_OUTPUT_DATA(0));
+       DUMP_REG(DC_COM_PIN_OUTPUT_DATA(1));
+       DUMP_REG(DC_COM_PIN_OUTPUT_DATA(2));
+       DUMP_REG(DC_COM_PIN_OUTPUT_DATA(3));
+       DUMP_REG(DC_COM_PIN_INPUT_ENABLE(0));
+       DUMP_REG(DC_COM_PIN_INPUT_ENABLE(1));
+       DUMP_REG(DC_COM_PIN_INPUT_ENABLE(2));
+       DUMP_REG(DC_COM_PIN_INPUT_ENABLE(3));
+       DUMP_REG(DC_COM_PIN_INPUT_DATA(0));
+       DUMP_REG(DC_COM_PIN_INPUT_DATA(1));
+       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(0));
+       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(1));
+       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(2));
+       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(3));
+       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(4));
+       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(5));
+       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(6));
+       DUMP_REG(DC_COM_PIN_MISC_CONTROL);
+       DUMP_REG(DC_COM_PIN_PM0_CONTROL);
+       DUMP_REG(DC_COM_PIN_PM0_DUTY_CYCLE);
+       DUMP_REG(DC_COM_PIN_PM1_CONTROL);
+       DUMP_REG(DC_COM_PIN_PM1_DUTY_CYCLE);
+       DUMP_REG(DC_COM_SPI_CONTROL);
+       DUMP_REG(DC_COM_SPI_START_BYTE);
+       DUMP_REG(DC_COM_HSPI_WRITE_DATA_AB);
+       DUMP_REG(DC_COM_HSPI_WRITE_DATA_CD);
+       DUMP_REG(DC_COM_HSPI_CS_DC);
+       DUMP_REG(DC_COM_SCRATCH_REGISTER_A);
+       DUMP_REG(DC_COM_SCRATCH_REGISTER_B);
+       DUMP_REG(DC_COM_GPIO_CTRL);
+       DUMP_REG(DC_COM_GPIO_DEBOUNCE_COUNTER);
+       DUMP_REG(DC_COM_CRC_CHECKSUM_LATCHED);
+       DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
+       DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
+       DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
+       DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY);
+       DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
+       DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
+       DUMP_REG(DC_DISP_REF_TO_SYNC);
+       DUMP_REG(DC_DISP_SYNC_WIDTH);
+       DUMP_REG(DC_DISP_BACK_PORCH);
+       DUMP_REG(DC_DISP_ACTIVE);
+       DUMP_REG(DC_DISP_FRONT_PORCH);
+       DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
+       DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
+       DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
+       DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
+       DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
+       DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
+       DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
+       DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
+       DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
+       DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
+       DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
+       DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
+       DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
+       DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
+       DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
+       DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
+       DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
+       DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
+       DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
+       DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
+       DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
+       DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
+       DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
+       DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
+       DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
+       DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
+       DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
+       DUMP_REG(DC_DISP_M0_CONTROL);
+       DUMP_REG(DC_DISP_M1_CONTROL);
+       DUMP_REG(DC_DISP_DI_CONTROL);
+       DUMP_REG(DC_DISP_PP_CONTROL);
+       DUMP_REG(DC_DISP_PP_SELECT_A);
+       DUMP_REG(DC_DISP_PP_SELECT_B);
+       DUMP_REG(DC_DISP_PP_SELECT_C);
+       DUMP_REG(DC_DISP_PP_SELECT_D);
+       DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
+       DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
+       DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
+       DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
+       DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
+       DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
+       DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
+       DUMP_REG(DC_DISP_BORDER_COLOR);
+       DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
+       DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
+       DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
+       DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
+       DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
+       DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
+       DUMP_REG(DC_DISP_CURSOR_START_ADDR);
+       DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
+       DUMP_REG(DC_DISP_CURSOR_POSITION);
+       DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
+       DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
+       DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
+       DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
+       DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
+       DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
+       DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
+       DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
+       DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
+       DUMP_REG(DC_DISP_MCCIF_DISPLAY1A_HYST);
+       DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
+       DUMP_REG(DC_DISP_DAC_CRT_CTRL);
+       DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
+       DUMP_REG(DC_DISP_SD_CONTROL);
+       DUMP_REG(DC_DISP_SD_CSC_COEFF);
+       DUMP_REG(DC_DISP_SD_LUT(0));
+       DUMP_REG(DC_DISP_SD_LUT(1));
+       DUMP_REG(DC_DISP_SD_LUT(2));
+       DUMP_REG(DC_DISP_SD_LUT(3));
+       DUMP_REG(DC_DISP_SD_LUT(4));
+       DUMP_REG(DC_DISP_SD_LUT(5));
+       DUMP_REG(DC_DISP_SD_LUT(6));
+       DUMP_REG(DC_DISP_SD_LUT(7));
+       DUMP_REG(DC_DISP_SD_LUT(8));
+       DUMP_REG(DC_DISP_SD_FLICKER_CONTROL);
+       DUMP_REG(DC_DISP_DC_PIXEL_COUNT);
+       DUMP_REG(DC_DISP_SD_HISTOGRAM(0));
+       DUMP_REG(DC_DISP_SD_HISTOGRAM(1));
+       DUMP_REG(DC_DISP_SD_HISTOGRAM(2));
+       DUMP_REG(DC_DISP_SD_HISTOGRAM(3));
+       DUMP_REG(DC_DISP_SD_HISTOGRAM(4));
+       DUMP_REG(DC_DISP_SD_HISTOGRAM(5));
+       DUMP_REG(DC_DISP_SD_HISTOGRAM(6));
+       DUMP_REG(DC_DISP_SD_HISTOGRAM(7));
+       DUMP_REG(DC_DISP_SD_BL_TF(0));
+       DUMP_REG(DC_DISP_SD_BL_TF(1));
+       DUMP_REG(DC_DISP_SD_BL_TF(2));
+       DUMP_REG(DC_DISP_SD_BL_TF(3));
+       DUMP_REG(DC_DISP_SD_BL_CONTROL);
+       DUMP_REG(DC_DISP_SD_HW_K_VALUES);
+       DUMP_REG(DC_DISP_SD_MAN_K_VALUES);
+       DUMP_REG(DC_WIN_WIN_OPTIONS);
+       DUMP_REG(DC_WIN_BYTE_SWAP);
+       DUMP_REG(DC_WIN_BUFFER_CONTROL);
+       DUMP_REG(DC_WIN_COLOR_DEPTH);
+       DUMP_REG(DC_WIN_POSITION);
+       DUMP_REG(DC_WIN_SIZE);
+       DUMP_REG(DC_WIN_PRESCALED_SIZE);
+       DUMP_REG(DC_WIN_H_INITIAL_DDA);
+       DUMP_REG(DC_WIN_V_INITIAL_DDA);
+       DUMP_REG(DC_WIN_DDA_INC);
+       DUMP_REG(DC_WIN_LINE_STRIDE);
+       DUMP_REG(DC_WIN_BUF_STRIDE);
+       DUMP_REG(DC_WIN_UV_BUF_STRIDE);
+       DUMP_REG(DC_WIN_BUFFER_ADDR_MODE);
+       DUMP_REG(DC_WIN_DV_CONTROL);
+       DUMP_REG(DC_WIN_BLEND_NOKEY);
+       DUMP_REG(DC_WIN_BLEND_1WIN);
+       DUMP_REG(DC_WIN_BLEND_2WIN_X);
+       DUMP_REG(DC_WIN_BLEND_2WIN_Y);
+       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);
+       DUMP_REG(DC_WINBUF_START_ADDR_U);
+       DUMP_REG(DC_WINBUF_START_ADDR_U_NS);
+       DUMP_REG(DC_WINBUF_START_ADDR_V);
+       DUMP_REG(DC_WINBUF_START_ADDR_V_NS);
+       DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
+       DUMP_REG(DC_WINBUF_ADDR_H_OFFSET_NS);
+       DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
+       DUMP_REG(DC_WINBUF_ADDR_V_OFFSET_NS);
+       DUMP_REG(DC_WINBUF_UFLOW_STATUS);
+       DUMP_REG(DC_WINBUF_AD_UFLOW_STATUS);
+       DUMP_REG(DC_WINBUF_BD_UFLOW_STATUS);
+       DUMP_REG(DC_WINBUF_CD_UFLOW_STATUS);
+
+#undef DUMP_REG
+
+       return 0;
+}
+
+static struct drm_info_list debugfs_files[] = {
+       { "regs", tegra_dc_show_regs, 0, NULL },
+};
+
+static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
+{
+       unsigned int i;
+       char *name;
+       int err;
+
+       name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe);
+       dc->debugfs = debugfs_create_dir(name, minor->debugfs_root);
+       kfree(name);
+
+       if (!dc->debugfs)
+               return -ENOMEM;
+
+       dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
+                                   GFP_KERNEL);
+       if (!dc->debugfs_files) {
+               err = -ENOMEM;
+               goto remove;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
+               dc->debugfs_files[i].data = dc;
+
+       err = drm_debugfs_create_files(dc->debugfs_files,
+                                      ARRAY_SIZE(debugfs_files),
+                                      dc->debugfs, minor);
+       if (err < 0)
+               goto free;
+
+       dc->minor = minor;
+
+       return 0;
+
+free:
+       kfree(dc->debugfs_files);
+       dc->debugfs_files = NULL;
+remove:
+       debugfs_remove(dc->debugfs);
+       dc->debugfs = NULL;
+
+       return err;
+}
+
+static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
+{
+       drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files),
+                                dc->minor);
+       dc->minor = NULL;
+
+       kfree(dc->debugfs_files);
+       dc->debugfs_files = NULL;
+
+       debugfs_remove(dc->debugfs);
+       dc->debugfs = NULL;
+
+       return 0;
+}
+
+static int tegra_dc_init(struct host1x_client *client)
+{
+       struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+       struct tegra_dc *dc = host1x_client_to_dc(client);
+       int err;
+
+       dc->pipe = tegra->drm->mode_config.num_crtc;
+
+       drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
+       drm_mode_crtc_set_gamma_size(&dc->base, 256);
+       drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
+
+       err = tegra_dc_rgb_init(tegra->drm, dc);
+       if (err < 0 && err != -ENODEV) {
+               dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
+               return err;
+       }
+
+       err = tegra_dc_add_planes(tegra->drm, dc);
+       if (err < 0)
+               return err;
+
+       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+               err = tegra_dc_debugfs_init(dc, tegra->drm->primary);
+               if (err < 0)
+                       dev_err(dc->dev, "debugfs setup failed: %d\n", err);
+       }
+
+       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,
+                       err);
+               return err;
+       }
+
+       return 0;
+}
+
+static int tegra_dc_exit(struct host1x_client *client)
+{
+       struct tegra_dc *dc = host1x_client_to_dc(client);
+       int err;
+
+       devm_free_irq(dc->dev, dc->irq, dc);
+
+       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+               err = tegra_dc_debugfs_exit(dc);
+               if (err < 0)
+                       dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
+       }
+
+       err = tegra_dc_rgb_exit(dc);
+       if (err) {
+               dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static const struct host1x_client_ops dc_client_ops = {
+       .init = tegra_dc_init,
+       .exit = tegra_dc_exit,
+};
+
+static int tegra_dc_probe(struct platform_device *pdev)
+{
+       struct resource *regs;
+       struct tegra_dc *dc;
+       int err;
+
+       dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
+       if (!dc)
+               return -ENOMEM;
+
+       spin_lock_init(&dc->lock);
+       INIT_LIST_HEAD(&dc->list);
+       dc->dev = &pdev->dev;
+
+       dc->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dc->clk)) {
+               dev_err(&pdev->dev, "failed to get clock\n");
+               return PTR_ERR(dc->clk);
+       }
+
+       err = clk_prepare_enable(dc->clk);
+       if (err < 0)
+               return err;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       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) {
+               dev_err(&pdev->dev, "failed to get IRQ\n");
+               return -ENXIO;
+       }
+
+       INIT_LIST_HEAD(&dc->client.list);
+       dc->client.ops = &dc_client_ops;
+       dc->client.dev = &pdev->dev;
+
+       err = tegra_dc_rgb_probe(dc);
+       if (err < 0 && err != -ENODEV) {
+               dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
+               return err;
+       }
+
+       err = host1x_client_register(&dc->client);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to register host1x client: %d\n",
+                       err);
+               return err;
+       }
+
+       platform_set_drvdata(pdev, dc);
+
+       return 0;
+}
+
+static int tegra_dc_remove(struct platform_device *pdev)
+{
+       struct tegra_dc *dc = platform_get_drvdata(pdev);
+       int err;
+
+       err = host1x_client_unregister(&dc->client);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
+                       err);
+               return err;
+       }
+
+       clk_disable_unprepare(dc->clk);
+
+       return 0;
+}
+
+static struct of_device_id tegra_dc_of_match[] = {
+       { .compatible = "nvidia,tegra30-dc", },
+       { .compatible = "nvidia,tegra20-dc", },
+       { },
+};
+
+struct platform_driver tegra_dc_driver = {
+       .driver = {
+               .name = "tegra-dc",
+               .owner = THIS_MODULE,
+               .of_match_table = tegra_dc_of_match,
+       },
+       .probe = tegra_dc_probe,
+       .remove = tegra_dc_remove,
+};
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
new file mode 100644 (file)
index 0000000..79eaec9
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef TEGRA_DC_H
+#define TEGRA_DC_H 1
+
+#define DC_CMD_GENERAL_INCR_SYNCPT             0x000
+#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL       0x001
+#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR       0x002
+#define DC_CMD_WIN_A_INCR_SYNCPT               0x008
+#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL         0x009
+#define DC_CMD_WIN_A_INCR_SYNCPT_ERROR         0x00a
+#define DC_CMD_WIN_B_INCR_SYNCPT               0x010
+#define DC_CMD_WIN_B_INCR_SYNCPT_CNTRL         0x011
+#define DC_CMD_WIN_B_INCR_SYNCPT_ERROR         0x012
+#define DC_CMD_WIN_C_INCR_SYNCPT               0x018
+#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL         0x019
+#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR         0x01a
+#define DC_CMD_CONT_SYNCPT_VSYNC               0x028
+#define DC_CMD_DISPLAY_COMMAND_OPTION0         0x031
+#define DC_CMD_DISPLAY_COMMAND                 0x032
+#define DISP_CTRL_MODE_STOP (0 << 5)
+#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
+#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
+#define DC_CMD_SIGNAL_RAISE                    0x033
+#define DC_CMD_DISPLAY_POWER_CONTROL           0x036
+#define PW0_ENABLE (1 <<  0)
+#define PW1_ENABLE (1 <<  2)
+#define PW2_ENABLE (1 <<  4)
+#define PW3_ENABLE (1 <<  6)
+#define PW4_ENABLE (1 <<  8)
+#define PM0_ENABLE (1 << 16)
+#define PM1_ENABLE (1 << 18)
+
+#define DC_CMD_INT_STATUS                      0x037
+#define DC_CMD_INT_MASK                                0x038
+#define DC_CMD_INT_ENABLE                      0x039
+#define DC_CMD_INT_TYPE                                0x03a
+#define DC_CMD_INT_POLARITY                    0x03b
+#define CTXSW_INT     (1 << 0)
+#define FRAME_END_INT (1 << 1)
+#define VBLANK_INT    (1 << 2)
+#define WIN_A_UF_INT  (1 << 8)
+#define WIN_B_UF_INT  (1 << 9)
+#define WIN_C_UF_INT  (1 << 10)
+#define WIN_A_OF_INT  (1 << 14)
+#define WIN_B_OF_INT  (1 << 15)
+#define WIN_C_OF_INT  (1 << 16)
+
+#define DC_CMD_SIGNAL_RAISE1                   0x03c
+#define DC_CMD_SIGNAL_RAISE2                   0x03d
+#define DC_CMD_SIGNAL_RAISE3                   0x03e
+
+#define DC_CMD_STATE_ACCESS                    0x040
+#define READ_MUX  (1 << 0)
+#define WRITE_MUX (1 << 2)
+
+#define DC_CMD_STATE_CONTROL                   0x041
+#define GENERAL_ACT_REQ (1 <<  0)
+#define WIN_A_ACT_REQ   (1 <<  1)
+#define WIN_B_ACT_REQ   (1 <<  2)
+#define WIN_C_ACT_REQ   (1 <<  3)
+#define GENERAL_UPDATE  (1 <<  8)
+#define WIN_A_UPDATE    (1 <<  9)
+#define WIN_B_UPDATE    (1 << 10)
+#define WIN_C_UPDATE    (1 << 11)
+#define NC_HOST_TRIG    (1 << 24)
+
+#define DC_CMD_DISPLAY_WINDOW_HEADER           0x042
+#define WINDOW_A_SELECT (1 << 4)
+#define WINDOW_B_SELECT (1 << 5)
+#define WINDOW_C_SELECT (1 << 6)
+
+#define DC_CMD_REG_ACT_CONTROL                 0x043
+
+#define DC_COM_CRC_CONTROL                     0x300
+#define DC_COM_CRC_CHECKSUM                    0x301
+#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
+#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
+#define LVS_OUTPUT_POLARITY_LOW (1 << 28)
+#define LHS_OUTPUT_POLARITY_LOW (1 << 30)
+#define DC_COM_PIN_OUTPUT_DATA(x) (0x30a + (x))
+#define DC_COM_PIN_INPUT_ENABLE(x) (0x30e + (x))
+#define DC_COM_PIN_INPUT_DATA(x) (0x312 + (x))
+#define DC_COM_PIN_OUTPUT_SELECT(x) (0x314 + (x))
+
+#define DC_COM_PIN_MISC_CONTROL                        0x31b
+#define DC_COM_PIN_PM0_CONTROL                 0x31c
+#define DC_COM_PIN_PM0_DUTY_CYCLE              0x31d
+#define DC_COM_PIN_PM1_CONTROL                 0x31e
+#define DC_COM_PIN_PM1_DUTY_CYCLE              0x31f
+
+#define DC_COM_SPI_CONTROL                     0x320
+#define DC_COM_SPI_START_BYTE                  0x321
+#define DC_COM_HSPI_WRITE_DATA_AB              0x322
+#define DC_COM_HSPI_WRITE_DATA_CD              0x323
+#define DC_COM_HSPI_CS_DC                      0x324
+#define DC_COM_SCRATCH_REGISTER_A              0x325
+#define DC_COM_SCRATCH_REGISTER_B              0x326
+#define DC_COM_GPIO_CTRL                       0x327
+#define DC_COM_GPIO_DEBOUNCE_COUNTER           0x328
+#define DC_COM_CRC_CHECKSUM_LATCHED            0x329
+
+#define DC_DISP_DISP_SIGNAL_OPTIONS0           0x400
+#define H_PULSE_0_ENABLE (1 <<  8)
+#define H_PULSE_1_ENABLE (1 << 10)
+#define H_PULSE_2_ENABLE (1 << 12)
+
+#define DC_DISP_DISP_SIGNAL_OPTIONS1           0x401
+
+#define DC_DISP_DISP_WIN_OPTIONS               0x402
+#define HDMI_ENABLE (1 << 30)
+
+#define DC_DISP_DISP_MEM_HIGH_PRIORITY         0x403
+#define CURSOR_THRESHOLD(x)   (((x) & 0x03) << 24)
+#define WINDOW_A_THRESHOLD(x) (((x) & 0x7f) << 16)
+#define WINDOW_B_THRESHOLD(x) (((x) & 0x7f) <<  8)
+#define WINDOW_C_THRESHOLD(x) (((x) & 0xff) <<  0)
+
+#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER   0x404
+#define CURSOR_DELAY(x)   (((x) & 0x3f) << 24)
+#define WINDOW_A_DELAY(x) (((x) & 0x3f) << 16)
+#define WINDOW_B_DELAY(x) (((x) & 0x3f) <<  8)
+#define WINDOW_C_DELAY(x) (((x) & 0x3f) <<  0)
+
+#define DC_DISP_DISP_TIMING_OPTIONS            0x405
+#define VSYNC_H_POSITION(x) ((x) & 0xfff)
+
+#define DC_DISP_REF_TO_SYNC                    0x406
+#define DC_DISP_SYNC_WIDTH                     0x407
+#define DC_DISP_BACK_PORCH                     0x408
+#define DC_DISP_ACTIVE                         0x409
+#define DC_DISP_FRONT_PORCH                    0x40a
+#define DC_DISP_H_PULSE0_CONTROL               0x40b
+#define DC_DISP_H_PULSE0_POSITION_A            0x40c
+#define DC_DISP_H_PULSE0_POSITION_B            0x40d
+#define DC_DISP_H_PULSE0_POSITION_C            0x40e
+#define DC_DISP_H_PULSE0_POSITION_D            0x40f
+#define DC_DISP_H_PULSE1_CONTROL               0x410
+#define DC_DISP_H_PULSE1_POSITION_A            0x411
+#define DC_DISP_H_PULSE1_POSITION_B            0x412
+#define DC_DISP_H_PULSE1_POSITION_C            0x413
+#define DC_DISP_H_PULSE1_POSITION_D            0x414
+#define DC_DISP_H_PULSE2_CONTROL               0x415
+#define DC_DISP_H_PULSE2_POSITION_A            0x416
+#define DC_DISP_H_PULSE2_POSITION_B            0x417
+#define DC_DISP_H_PULSE2_POSITION_C            0x418
+#define DC_DISP_H_PULSE2_POSITION_D            0x419
+#define DC_DISP_V_PULSE0_CONTROL               0x41a
+#define DC_DISP_V_PULSE0_POSITION_A            0x41b
+#define DC_DISP_V_PULSE0_POSITION_B            0x41c
+#define DC_DISP_V_PULSE0_POSITION_C            0x41d
+#define DC_DISP_V_PULSE1_CONTROL               0x41e
+#define DC_DISP_V_PULSE1_POSITION_A            0x41f
+#define DC_DISP_V_PULSE1_POSITION_B            0x420
+#define DC_DISP_V_PULSE1_POSITION_C            0x421
+#define DC_DISP_V_PULSE2_CONTROL               0x422
+#define DC_DISP_V_PULSE2_POSITION_A            0x423
+#define DC_DISP_V_PULSE3_CONTROL               0x424
+#define DC_DISP_V_PULSE3_POSITION_A            0x425
+#define DC_DISP_M0_CONTROL                     0x426
+#define DC_DISP_M1_CONTROL                     0x427
+#define DC_DISP_DI_CONTROL                     0x428
+#define DC_DISP_PP_CONTROL                     0x429
+#define DC_DISP_PP_SELECT_A                    0x42a
+#define DC_DISP_PP_SELECT_B                    0x42b
+#define DC_DISP_PP_SELECT_C                    0x42c
+#define DC_DISP_PP_SELECT_D                    0x42d
+
+#define PULSE_MODE_NORMAL    (0 << 3)
+#define PULSE_MODE_ONE_CLOCK (1 << 3)
+#define PULSE_POLARITY_HIGH  (0 << 4)
+#define PULSE_POLARITY_LOW   (1 << 4)
+#define PULSE_QUAL_ALWAYS    (0 << 6)
+#define PULSE_QUAL_VACTIVE   (2 << 6)
+#define PULSE_QUAL_VACTIVE1  (3 << 6)
+#define PULSE_LAST_START_A   (0 << 8)
+#define PULSE_LAST_END_A     (1 << 8)
+#define PULSE_LAST_START_B   (2 << 8)
+#define PULSE_LAST_END_B     (3 << 8)
+#define PULSE_LAST_START_C   (4 << 8)
+#define PULSE_LAST_END_C     (5 << 8)
+#define PULSE_LAST_START_D   (6 << 8)
+#define PULSE_LAST_END_D     (7 << 8)
+
+#define PULSE_START(x) (((x) & 0xfff) <<  0)
+#define PULSE_END(x)   (((x) & 0xfff) << 16)
+
+#define DC_DISP_DISP_CLOCK_CONTROL             0x42e
+#define PIXEL_CLK_DIVIDER_PCD1  (0 << 8)
+#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
+#define PIXEL_CLK_DIVIDER_PCD2  (2 << 8)
+#define PIXEL_CLK_DIVIDER_PCD3  (3 << 8)
+#define PIXEL_CLK_DIVIDER_PCD4  (4 << 8)
+#define PIXEL_CLK_DIVIDER_PCD6  (5 << 8)
+#define PIXEL_CLK_DIVIDER_PCD8  (6 << 8)
+#define PIXEL_CLK_DIVIDER_PCD9  (7 << 8)
+#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
+#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
+#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
+#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
+#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
+#define SHIFT_CLK_DIVIDER(x)    ((x) & 0xff)
+
+#define DC_DISP_DISP_INTERFACE_CONTROL         0x42f
+#define DISP_DATA_FORMAT_DF1P1C    (0 << 0)
+#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
+#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
+#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
+#define DISP_DATA_FORMAT_DF2S      (4 << 0)
+#define DISP_DATA_FORMAT_DF3S      (5 << 0)
+#define DISP_DATA_FORMAT_DFSPI     (6 << 0)
+#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
+#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
+#define DISP_ALIGNMENT_MSB         (0 << 8)
+#define DISP_ALIGNMENT_LSB         (1 << 8)
+#define DISP_ORDER_RED_BLUE        (0 << 9)
+#define DISP_ORDER_BLUE_RED        (1 << 9)
+
+#define DC_DISP_DISP_COLOR_CONTROL             0x430
+#define BASE_COLOR_SIZE666     (0 << 0)
+#define BASE_COLOR_SIZE111     (1 << 0)
+#define BASE_COLOR_SIZE222     (2 << 0)
+#define BASE_COLOR_SIZE333     (3 << 0)
+#define BASE_COLOR_SIZE444     (4 << 0)
+#define BASE_COLOR_SIZE555     (5 << 0)
+#define BASE_COLOR_SIZE565     (6 << 0)
+#define BASE_COLOR_SIZE332     (7 << 0)
+#define BASE_COLOR_SIZE888     (8 << 0)
+#define DITHER_CONTROL_DISABLE (0 << 8)
+#define DITHER_CONTROL_ORDERED (2 << 8)
+#define DITHER_CONTROL_ERRDIFF (3 << 8)
+
+#define DC_DISP_SHIFT_CLOCK_OPTIONS            0x431
+
+#define DC_DISP_DATA_ENABLE_OPTIONS            0x432
+#define DE_SELECT_ACTIVE_BLANK  (0 << 0)
+#define DE_SELECT_ACTIVE        (1 << 0)
+#define DE_SELECT_ACTIVE_IS     (2 << 0)
+#define DE_CONTROL_ONECLK       (0 << 2)
+#define DE_CONTROL_NORMAL       (1 << 2)
+#define DE_CONTROL_EARLY_EXT    (2 << 2)
+#define DE_CONTROL_EARLY        (3 << 2)
+#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
+
+#define DC_DISP_SERIAL_INTERFACE_OPTIONS       0x433
+#define DC_DISP_LCD_SPI_OPTIONS                        0x434
+#define DC_DISP_BORDER_COLOR                   0x435
+#define DC_DISP_COLOR_KEY0_LOWER               0x436
+#define DC_DISP_COLOR_KEY0_UPPER               0x437
+#define DC_DISP_COLOR_KEY1_LOWER               0x438
+#define DC_DISP_COLOR_KEY1_UPPER               0x439
+
+#define DC_DISP_CURSOR_FOREGROUND              0x43c
+#define DC_DISP_CURSOR_BACKGROUND              0x43d
+
+#define DC_DISP_CURSOR_START_ADDR              0x43e
+#define DC_DISP_CURSOR_START_ADDR_NS           0x43f
+
+#define DC_DISP_CURSOR_POSITION                        0x440
+#define DC_DISP_CURSOR_POSITION_NS             0x441
+
+#define DC_DISP_INIT_SEQ_CONTROL               0x442
+#define DC_DISP_SPI_INIT_SEQ_DATA_A            0x443
+#define DC_DISP_SPI_INIT_SEQ_DATA_B            0x444
+#define DC_DISP_SPI_INIT_SEQ_DATA_C            0x445
+#define DC_DISP_SPI_INIT_SEQ_DATA_D            0x446
+
+#define DC_DISP_DC_MCCIF_FIFOCTRL              0x480
+#define DC_DISP_MCCIF_DISPLAY0A_HYST           0x481
+#define DC_DISP_MCCIF_DISPLAY0B_HYST           0x482
+#define DC_DISP_MCCIF_DISPLAY1A_HYST           0x483
+#define DC_DISP_MCCIF_DISPLAY1B_HYST           0x484
+
+#define DC_DISP_DAC_CRT_CTRL                   0x4c0
+#define DC_DISP_DISP_MISC_CONTROL              0x4c1
+#define DC_DISP_SD_CONTROL                     0x4c2
+#define DC_DISP_SD_CSC_COEFF                   0x4c3
+#define DC_DISP_SD_LUT(x)                      (0x4c4 + (x))
+#define DC_DISP_SD_FLICKER_CONTROL             0x4cd
+#define DC_DISP_DC_PIXEL_COUNT                 0x4ce
+#define DC_DISP_SD_HISTOGRAM(x)                        (0x4cf + (x))
+#define DC_DISP_SD_BL_PARAMETERS               0x4d7
+#define DC_DISP_SD_BL_TF(x)                    (0x4d8 + (x))
+#define DC_DISP_SD_BL_CONTROL                  0x4dc
+#define DC_DISP_SD_HW_K_VALUES                 0x4dd
+#define DC_DISP_SD_MAN_K_VALUES                        0x4de
+
+#define DC_WIN_CSC_YOF                         0x611
+#define DC_WIN_CSC_KYRGB                       0x612
+#define DC_WIN_CSC_KUR                         0x613
+#define DC_WIN_CSC_KVR                         0x614
+#define DC_WIN_CSC_KUG                         0x615
+#define DC_WIN_CSC_KVG                         0x616
+#define DC_WIN_CSC_KUB                         0x617
+#define DC_WIN_CSC_KVB                         0x618
+
+#define DC_WIN_WIN_OPTIONS                     0x700
+#define COLOR_EXPAND (1 <<  6)
+#define CSC_ENABLE   (1 << 18)
+#define WIN_ENABLE   (1 << 30)
+
+#define DC_WIN_BYTE_SWAP                       0x701
+#define BYTE_SWAP_NOSWAP  (0 << 0)
+#define BYTE_SWAP_SWAP2   (1 << 0)
+#define BYTE_SWAP_SWAP4   (2 << 0)
+#define BYTE_SWAP_SWAP4HW (3 << 0)
+
+#define DC_WIN_BUFFER_CONTROL                  0x702
+#define BUFFER_CONTROL_HOST  (0 << 0)
+#define BUFFER_CONTROL_VI    (1 << 0)
+#define BUFFER_CONTROL_EPP   (2 << 0)
+#define BUFFER_CONTROL_MPEGE (3 << 0)
+#define BUFFER_CONTROL_SB2D  (4 << 0)
+
+#define DC_WIN_COLOR_DEPTH                     0x703
+#define WIN_COLOR_DEPTH_P1              0
+#define WIN_COLOR_DEPTH_P2              1
+#define WIN_COLOR_DEPTH_P4              2
+#define WIN_COLOR_DEPTH_P8              3
+#define WIN_COLOR_DEPTH_B4G4R4A4        4
+#define WIN_COLOR_DEPTH_B5G5R5A         5
+#define WIN_COLOR_DEPTH_B5G6R5          6
+#define WIN_COLOR_DEPTH_AB5G5R5         7
+#define WIN_COLOR_DEPTH_B8G8R8A8       12
+#define WIN_COLOR_DEPTH_R8G8B8A8       13
+#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 14
+#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 15
+#define WIN_COLOR_DEPTH_YCbCr422       16
+#define WIN_COLOR_DEPTH_YUV422         17
+#define WIN_COLOR_DEPTH_YCbCr420P      18
+#define WIN_COLOR_DEPTH_YUV420P        19
+#define WIN_COLOR_DEPTH_YCbCr422P      20
+#define WIN_COLOR_DEPTH_YUV422P        21
+#define WIN_COLOR_DEPTH_YCbCr422R      22
+#define WIN_COLOR_DEPTH_YUV422R        23
+#define WIN_COLOR_DEPTH_YCbCr422RA     24
+#define WIN_COLOR_DEPTH_YUV422RA       25
+
+#define DC_WIN_POSITION                                0x704
+#define H_POSITION(x) (((x) & 0x1fff) <<  0)
+#define V_POSITION(x) (((x) & 0x1fff) << 16)
+
+#define DC_WIN_SIZE                            0x705
+#define H_SIZE(x) (((x) & 0x1fff) <<  0)
+#define V_SIZE(x) (((x) & 0x1fff) << 16)
+
+#define DC_WIN_PRESCALED_SIZE                  0x706
+#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) <<  0)
+#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
+
+#define DC_WIN_H_INITIAL_DDA                   0x707
+#define DC_WIN_V_INITIAL_DDA                   0x708
+#define DC_WIN_DDA_INC                         0x709
+#define H_DDA_INC(x) (((x) & 0xffff) <<  0)
+#define V_DDA_INC(x) (((x) & 0xffff) << 16)
+
+#define DC_WIN_LINE_STRIDE                     0x70a
+#define DC_WIN_BUF_STRIDE                      0x70b
+#define DC_WIN_UV_BUF_STRIDE                   0x70c
+#define DC_WIN_BUFFER_ADDR_MODE                        0x70d
+#define DC_WIN_DV_CONTROL                      0x70e
+
+#define DC_WIN_BLEND_NOKEY                     0x70f
+#define DC_WIN_BLEND_1WIN                      0x710
+#define DC_WIN_BLEND_2WIN_X                    0x711
+#define DC_WIN_BLEND_2WIN_Y                    0x712
+#define DC_WIN_BLEND_3WIN_XY                   0x713
+
+#define DC_WIN_HP_FETCH_CONTROL                        0x714
+
+#define DC_WINBUF_START_ADDR                   0x800
+#define DC_WINBUF_START_ADDR_NS                        0x801
+#define DC_WINBUF_START_ADDR_U                 0x802
+#define DC_WINBUF_START_ADDR_U_NS              0x803
+#define DC_WINBUF_START_ADDR_V                 0x804
+#define DC_WINBUF_START_ADDR_V_NS              0x805
+
+#define DC_WINBUF_ADDR_H_OFFSET                        0x806
+#define DC_WINBUF_ADDR_H_OFFSET_NS             0x807
+#define DC_WINBUF_ADDR_V_OFFSET                        0x808
+#define DC_WINBUF_ADDR_V_OFFSET_NS             0x809
+
+#define DC_WINBUF_UFLOW_STATUS                 0x80a
+
+#define DC_WINBUF_AD_UFLOW_STATUS              0xbca
+#define DC_WINBUF_BD_UFLOW_STATUS              0xdca
+#define DC_WINBUF_CD_UFLOW_STATUS              0xfca
+
+/* synchronization points */
+#define SYNCPT_VBLANK0 26
+#define SYNCPT_VBLANK1 27
+
+#endif /* TEGRA_DC_H */
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
new file mode 100644 (file)
index 0000000..c2db409
--- /dev/null
@@ -0,0 +1,545 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/host1x.h>
+
+#include "drm.h"
+#include "gem.h"
+
+#define DRIVER_NAME "tegra"
+#define DRIVER_DESC "NVIDIA Tegra graphics"
+#define DRIVER_DATE "20120330"
+#define DRIVER_MAJOR 0
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
+
+struct tegra_drm_file {
+       struct list_head contexts;
+};
+
+static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
+{
+       struct host1x_device *device = to_host1x_device(drm->dev);
+       struct tegra_drm *tegra;
+       int err;
+
+       tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
+       if (!tegra)
+               return -ENOMEM;
+
+       dev_set_drvdata(drm->dev, tegra);
+       mutex_init(&tegra->clients_lock);
+       INIT_LIST_HEAD(&tegra->clients);
+       drm->dev_private = tegra;
+       tegra->drm = drm;
+
+       drm_mode_config_init(drm);
+
+       err = host1x_device_init(device);
+       if (err < 0)
+               return err;
+
+       /*
+        * We don't use the drm_irq_install() helpers provided by the DRM
+        * core, so we need to set this manually in order to allow the
+        * DRM_IOCTL_WAIT_VBLANK to operate correctly.
+        */
+       drm->irq_enabled = true;
+
+       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;
+
+       drm_kms_helper_poll_init(drm);
+
+       return 0;
+}
+
+static int tegra_drm_unload(struct drm_device *drm)
+{
+       struct host1x_device *device = to_host1x_device(drm->dev);
+       int err;
+
+       drm_kms_helper_poll_fini(drm);
+       tegra_drm_fb_exit(drm);
+
+       err = host1x_device_exit(device);
+       if (err < 0)
+               return err;
+
+       drm_mode_config_cleanup(drm);
+
+       return 0;
+}
+
+static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
+{
+       struct tegra_drm_file *fpriv;
+
+       fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
+       if (!fpriv)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&fpriv->contexts);
+       filp->driver_priv = fpriv;
+
+       return 0;
+}
+
+static void tegra_drm_context_free(struct tegra_drm_context *context)
+{
+       context->client->ops->close_channel(context);
+       kfree(context);
+}
+
+static void tegra_drm_lastclose(struct drm_device *drm)
+{
+       struct tegra_drm *tegra = drm->dev_private;
+
+       tegra_fbdev_restore_mode(tegra->fbdev);
+}
+
+#ifdef CONFIG_DRM_TEGRA_STAGING
+static struct tegra_drm_context *tegra_drm_get_context(__u64 context)
+{
+       return (struct tegra_drm_context *)(uintptr_t)context;
+}
+
+static bool tegra_drm_file_owns_context(struct tegra_drm_file *file,
+                                       struct tegra_drm_context *context)
+{
+       struct tegra_drm_context *ctx;
+
+       list_for_each_entry(ctx, &file->contexts, list)
+               if (ctx == context)
+                       return true;
+
+       return false;
+}
+
+static int tegra_gem_create(struct drm_device *drm, void *data,
+                           struct drm_file *file)
+{
+       struct drm_tegra_gem_create *args = data;
+       struct tegra_bo *bo;
+
+       bo = tegra_bo_create_with_handle(file, drm, args->size,
+                                        &args->handle);
+       if (IS_ERR(bo))
+               return PTR_ERR(bo);
+
+       return 0;
+}
+
+static int tegra_gem_mmap(struct drm_device *drm, void *data,
+                         struct drm_file *file)
+{
+       struct drm_tegra_gem_mmap *args = data;
+       struct drm_gem_object *gem;
+       struct tegra_bo *bo;
+
+       gem = drm_gem_object_lookup(drm, file, args->handle);
+       if (!gem)
+               return -EINVAL;
+
+       bo = to_tegra_bo(gem);
+
+       args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
+
+       drm_gem_object_unreference(gem);
+
+       return 0;
+}
+
+static int tegra_syncpt_read(struct drm_device *drm, void *data,
+                            struct drm_file *file)
+{
+       struct host1x *host = dev_get_drvdata(drm->dev->parent);
+       struct drm_tegra_syncpt_read *args = data;
+       struct host1x_syncpt *sp;
+
+       sp = host1x_syncpt_get(host, args->id);
+       if (!sp)
+               return -EINVAL;
+
+       args->value = host1x_syncpt_read_min(sp);
+       return 0;
+}
+
+static int tegra_syncpt_incr(struct drm_device *drm, void *data,
+                            struct drm_file *file)
+{
+       struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
+       struct drm_tegra_syncpt_incr *args = data;
+       struct host1x_syncpt *sp;
+
+       sp = host1x_syncpt_get(host1x, args->id);
+       if (!sp)
+               return -EINVAL;
+
+       return host1x_syncpt_incr(sp);
+}
+
+static int tegra_syncpt_wait(struct drm_device *drm, void *data,
+                            struct drm_file *file)
+{
+       struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
+       struct drm_tegra_syncpt_wait *args = data;
+       struct host1x_syncpt *sp;
+
+       sp = host1x_syncpt_get(host1x, args->id);
+       if (!sp)
+               return -EINVAL;
+
+       return host1x_syncpt_wait(sp, args->thresh, args->timeout,
+                                 &args->value);
+}
+
+static int tegra_open_channel(struct drm_device *drm, void *data,
+                             struct drm_file *file)
+{
+       struct tegra_drm_file *fpriv = file->driver_priv;
+       struct tegra_drm *tegra = drm->dev_private;
+       struct drm_tegra_open_channel *args = data;
+       struct tegra_drm_context *context;
+       struct tegra_drm_client *client;
+       int err = -ENODEV;
+
+       context = kzalloc(sizeof(*context), GFP_KERNEL);
+       if (!context)
+               return -ENOMEM;
+
+       list_for_each_entry(client, &tegra->clients, list)
+               if (client->base.class == args->client) {
+                       err = client->ops->open_channel(client, context);
+                       if (err)
+                               break;
+
+                       list_add(&context->list, &fpriv->contexts);
+                       args->context = (uintptr_t)context;
+                       context->client = client;
+                       return 0;
+               }
+
+       kfree(context);
+       return err;
+}
+
+static int tegra_close_channel(struct drm_device *drm, void *data,
+                              struct drm_file *file)
+{
+       struct tegra_drm_file *fpriv = file->driver_priv;
+       struct drm_tegra_close_channel *args = data;
+       struct tegra_drm_context *context;
+
+       context = tegra_drm_get_context(args->context);
+
+       if (!tegra_drm_file_owns_context(fpriv, context))
+               return -EINVAL;
+
+       list_del(&context->list);
+       tegra_drm_context_free(context);
+
+       return 0;
+}
+
+static int tegra_get_syncpt(struct drm_device *drm, void *data,
+                           struct drm_file *file)
+{
+       struct tegra_drm_file *fpriv = file->driver_priv;
+       struct drm_tegra_get_syncpt *args = data;
+       struct tegra_drm_context *context;
+       struct host1x_syncpt *syncpt;
+
+       context = tegra_drm_get_context(args->context);
+
+       if (!tegra_drm_file_owns_context(fpriv, context))
+               return -ENODEV;
+
+       if (args->index >= context->client->base.num_syncpts)
+               return -EINVAL;
+
+       syncpt = context->client->base.syncpts[args->index];
+       args->id = host1x_syncpt_id(syncpt);
+
+       return 0;
+}
+
+static int tegra_submit(struct drm_device *drm, void *data,
+                       struct drm_file *file)
+{
+       struct tegra_drm_file *fpriv = file->driver_priv;
+       struct drm_tegra_submit *args = data;
+       struct tegra_drm_context *context;
+
+       context = tegra_drm_get_context(args->context);
+
+       if (!tegra_drm_file_owns_context(fpriv, context))
+               return -ENODEV;
+
+       return context->client->ops->submit(context, args, drm, file);
+}
+#endif
+
+static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
+#ifdef CONFIG_DRM_TEGRA_STAGING
+       DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
+#endif
+};
+
+static const struct file_operations tegra_drm_fops = {
+       .owner = THIS_MODULE,
+       .open = drm_open,
+       .release = drm_release,
+       .unlocked_ioctl = drm_ioctl,
+       .mmap = tegra_drm_mmap,
+       .poll = drm_poll,
+       .read = drm_read,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
+       .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 tegra_drm_file *fpriv = file->driver_priv;
+       struct tegra_drm_context *context, *tmp;
+       struct drm_crtc *crtc;
+
+       list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
+               tegra_dc_cancel_page_flip(crtc, file);
+
+       list_for_each_entry_safe(context, tmp, &fpriv->contexts, list)
+               tegra_drm_context_free(context);
+
+       kfree(fpriv);
+}
+
+#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_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 = tegra_bo_free_object,
+       .gem_vm_ops = &tegra_bo_vm_ops,
+       .dumb_create = tegra_bo_dumb_create,
+       .dumb_map_offset = tegra_bo_dumb_map_offset,
+       .dumb_destroy = drm_gem_dumb_destroy,
+
+       .ioctls = tegra_drm_ioctls,
+       .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
+       .fops = &tegra_drm_fops,
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+int tegra_drm_register_client(struct tegra_drm *tegra,
+                             struct tegra_drm_client *client)
+{
+       mutex_lock(&tegra->clients_lock);
+       list_add_tail(&client->list, &tegra->clients);
+       mutex_unlock(&tegra->clients_lock);
+
+       return 0;
+}
+
+int tegra_drm_unregister_client(struct tegra_drm *tegra,
+                               struct tegra_drm_client *client)
+{
+       mutex_lock(&tegra->clients_lock);
+       list_del_init(&client->list);
+       mutex_unlock(&tegra->clients_lock);
+
+       return 0;
+}
+
+static int host1x_drm_probe(struct host1x_device *device)
+{
+       return drm_host1x_init(&tegra_drm_driver, device);
+}
+
+static int host1x_drm_remove(struct host1x_device *device)
+{
+       drm_host1x_exit(&tegra_drm_driver, device);
+
+       return 0;
+}
+
+static const struct of_device_id host1x_drm_subdevs[] = {
+       { .compatible = "nvidia,tegra20-dc", },
+       { .compatible = "nvidia,tegra20-hdmi", },
+       { .compatible = "nvidia,tegra20-gr2d", },
+       { .compatible = "nvidia,tegra30-dc", },
+       { .compatible = "nvidia,tegra30-hdmi", },
+       { .compatible = "nvidia,tegra30-gr2d", },
+       { /* sentinel */ }
+};
+
+static struct host1x_driver host1x_drm_driver = {
+       .name = "drm",
+       .probe = host1x_drm_probe,
+       .remove = host1x_drm_remove,
+       .subdevs = host1x_drm_subdevs,
+};
+
+static int __init host1x_drm_init(void)
+{
+       int err;
+
+       err = host1x_driver_register(&host1x_drm_driver);
+       if (err < 0)
+               return err;
+
+       err = platform_driver_register(&tegra_dc_driver);
+       if (err < 0)
+               goto unregister_host1x;
+
+       err = platform_driver_register(&tegra_hdmi_driver);
+       if (err < 0)
+               goto unregister_dc;
+
+       err = platform_driver_register(&tegra_gr2d_driver);
+       if (err < 0)
+               goto unregister_hdmi;
+
+       return 0;
+
+unregister_hdmi:
+       platform_driver_unregister(&tegra_hdmi_driver);
+unregister_dc:
+       platform_driver_unregister(&tegra_dc_driver);
+unregister_host1x:
+       host1x_driver_unregister(&host1x_drm_driver);
+       return err;
+}
+module_init(host1x_drm_init);
+
+static void __exit host1x_drm_exit(void)
+{
+       platform_driver_unregister(&tegra_gr2d_driver);
+       platform_driver_unregister(&tegra_hdmi_driver);
+       platform_driver_unregister(&tegra_dc_driver);
+       host1x_driver_unregister(&host1x_drm_driver);
+}
+module_exit(host1x_drm_exit);
+
+MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
+MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
new file mode 100644 (file)
index 0000000..25522e2
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef HOST1X_DRM_H
+#define HOST1X_DRM_H 1
+
+#include <uapi/drm/tegra_drm.h>
+#include <linux/host1x.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fixed.h>
+
+struct tegra_fb {
+       struct drm_framebuffer base;
+       struct tegra_bo **planes;
+       unsigned int num_planes;
+};
+
+struct tegra_fbdev {
+       struct drm_fb_helper base;
+       struct tegra_fb *fb;
+};
+
+struct tegra_drm {
+       struct drm_device *drm;
+
+       struct mutex clients_lock;
+       struct list_head clients;
+
+       struct tegra_fbdev *fbdev;
+};
+
+struct tegra_drm_client;
+
+struct tegra_drm_context {
+       struct tegra_drm_client *client;
+       struct host1x_channel *channel;
+       struct list_head list;
+};
+
+struct tegra_drm_client_ops {
+       int (*open_channel)(struct tegra_drm_client *client,
+                           struct tegra_drm_context *context);
+       void (*close_channel)(struct tegra_drm_context *context);
+       int (*submit)(struct tegra_drm_context *context,
+                     struct drm_tegra_submit *args, struct drm_device *drm,
+                     struct drm_file *file);
+};
+
+struct tegra_drm_client {
+       struct host1x_client base;
+       struct list_head list;
+
+       const struct tegra_drm_client_ops *ops;
+};
+
+static inline struct tegra_drm_client *
+host1x_to_drm_client(struct host1x_client *client)
+{
+       return container_of(client, struct tegra_drm_client, base);
+}
+
+extern int tegra_drm_register_client(struct tegra_drm *tegra,
+                                    struct tegra_drm_client *client);
+extern int tegra_drm_unregister_client(struct tegra_drm *tegra,
+                                      struct tegra_drm_client *client);
+
+extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
+extern int tegra_drm_exit(struct tegra_drm *tegra);
+
+struct tegra_output;
+
+struct tegra_dc {
+       struct host1x_client client;
+       struct device *dev;
+       spinlock_t lock;
+
+       struct drm_crtc base;
+       int pipe;
+
+       struct clk *clk;
+       void __iomem *regs;
+       int irq;
+
+       struct tegra_output *rgb;
+
+       struct list_head list;
+
+       struct drm_info_list *debugfs_files;
+       struct drm_minor *minor;
+       struct dentry *debugfs;
+
+       /* page-flip handling */
+       struct drm_pending_vblank_event *event;
+};
+
+static inline struct tegra_dc *
+host1x_client_to_dc(struct host1x_client *client)
+{
+       return container_of(client, struct tegra_dc, client);
+}
+
+static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
+{
+       return container_of(crtc, struct tegra_dc, base);
+}
+
+static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value,
+                                  unsigned long reg)
+{
+       writel(value, dc->regs + (reg << 2));
+}
+
+static inline unsigned long tegra_dc_readl(struct tegra_dc *dc,
+                                          unsigned long reg)
+{
+       return readl(dc->regs + (reg << 2));
+}
+
+struct tegra_dc_window {
+       struct {
+               unsigned int x;
+               unsigned int y;
+               unsigned int w;
+               unsigned int h;
+       } src;
+       struct {
+               unsigned int x;
+               unsigned int y;
+               unsigned int w;
+               unsigned int h;
+       } dst;
+       unsigned int bits_per_pixel;
+       unsigned int format;
+       unsigned int stride[2];
+       unsigned long base[3];
+};
+
+/* from dc.c */
+extern unsigned int tegra_dc_format(uint32_t format);
+extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
+                                const struct tegra_dc_window *window);
+extern void tegra_dc_enable_vblank(struct tegra_dc *dc);
+extern void tegra_dc_disable_vblank(struct tegra_dc *dc);
+extern void tegra_dc_cancel_page_flip(struct drm_crtc *crtc,
+                                     struct drm_file *file);
+
+struct tegra_output_ops {
+       int (*enable)(struct tegra_output *output);
+       int (*disable)(struct tegra_output *output);
+       int (*setup_clock)(struct tegra_output *output, struct clk *clk,
+                          unsigned long pclk);
+       int (*check_mode)(struct tegra_output *output,
+                         struct drm_display_mode *mode,
+                         enum drm_mode_status *status);
+};
+
+enum tegra_output_type {
+       TEGRA_OUTPUT_RGB,
+       TEGRA_OUTPUT_HDMI,
+};
+
+struct tegra_output {
+       struct device_node *of_node;
+       struct device *dev;
+
+       const struct tegra_output_ops *ops;
+       enum tegra_output_type type;
+
+       struct i2c_adapter *ddc;
+       const struct edid *edid;
+       unsigned int hpd_irq;
+       int hpd_gpio;
+
+       struct drm_encoder encoder;
+       struct drm_connector connector;
+};
+
+static inline struct tegra_output *encoder_to_output(struct drm_encoder *e)
+{
+       return container_of(e, struct tegra_output, encoder);
+}
+
+static inline struct tegra_output *connector_to_output(struct drm_connector *c)
+{
+       return container_of(c, struct tegra_output, connector);
+}
+
+static inline int tegra_output_enable(struct tegra_output *output)
+{
+       if (output && output->ops && output->ops->enable)
+               return output->ops->enable(output);
+
+       return output ? -ENOSYS : -EINVAL;
+}
+
+static inline int tegra_output_disable(struct tegra_output *output)
+{
+       if (output && output->ops && output->ops->disable)
+               return output->ops->disable(output);
+
+       return output ? -ENOSYS : -EINVAL;
+}
+
+static inline int tegra_output_setup_clock(struct tegra_output *output,
+                                          struct clk *clk, unsigned long pclk)
+{
+       if (output && output->ops && output->ops->setup_clock)
+               return output->ops->setup_clock(output, clk, pclk);
+
+       return output ? -ENOSYS : -EINVAL;
+}
+
+static inline int tegra_output_check_mode(struct tegra_output *output,
+                                         struct drm_display_mode *mode,
+                                         enum drm_mode_status *status)
+{
+       if (output && output->ops && output->ops->check_mode)
+               return output->ops->check_mode(output, mode, status);
+
+       return output ? -ENOSYS : -EINVAL;
+}
+
+/* from bus.c */
+int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device);
+void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device);
+
+/* from rgb.c */
+extern int tegra_dc_rgb_probe(struct tegra_dc *dc);
+extern int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc);
+extern int tegra_dc_rgb_exit(struct tegra_dc *dc);
+
+/* from output.c */
+extern int tegra_output_parse_dt(struct tegra_output *output);
+extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
+extern int tegra_output_exit(struct tegra_output *output);
+
+/* from fb.c */
+struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
+                                   unsigned int index);
+extern int tegra_drm_fb_init(struct drm_device *drm);
+extern void tegra_drm_fb_exit(struct drm_device *drm);
+extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
+
+extern struct platform_driver tegra_dc_driver;
+extern struct platform_driver tegra_hdmi_driver;
+extern struct platform_driver tegra_gr2d_driver;
+
+#endif /* HOST1X_DRM_H */
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
new file mode 100644 (file)
index 0000000..1fd4e19
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2012-2013 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Based on the KMS/FB CMA helpers
+ *   Copyright (C) 2012 Analog Device Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "drm.h"
+#include "gem.h"
+
+static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb)
+{
+       return container_of(fb, struct tegra_fb, base);
+}
+
+static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
+{
+       return container_of(helper, struct tegra_fbdev, base);
+}
+
+struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
+                                   unsigned int index)
+{
+       struct tegra_fb *fb = to_tegra_fb(framebuffer);
+
+       if (index >= drm_format_num_planes(framebuffer->pixel_format))
+               return NULL;
+
+       return fb->planes[index];
+}
+
+static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
+{
+       struct tegra_fb *fb = to_tegra_fb(framebuffer);
+       unsigned int i;
+
+       for (i = 0; i < fb->num_planes; i++) {
+               struct tegra_bo *bo = fb->planes[i];
+
+               if (bo)
+                       drm_gem_object_unreference_unlocked(&bo->gem);
+       }
+
+       drm_framebuffer_cleanup(framebuffer);
+       kfree(fb->planes);
+       kfree(fb);
+}
+
+static int tegra_fb_create_handle(struct drm_framebuffer *framebuffer,
+                                 struct drm_file *file, unsigned int *handle)
+{
+       struct tegra_fb *fb = to_tegra_fb(framebuffer);
+
+       return drm_gem_handle_create(file, &fb->planes[0]->gem, handle);
+}
+
+static struct drm_framebuffer_funcs tegra_fb_funcs = {
+       .destroy = tegra_fb_destroy,
+       .create_handle = tegra_fb_create_handle,
+};
+
+static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm,
+                                      struct drm_mode_fb_cmd2 *mode_cmd,
+                                      struct tegra_bo **planes,
+                                      unsigned int num_planes)
+{
+       struct tegra_fb *fb;
+       unsigned int i;
+       int err;
+
+       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+       if (!fb)
+               return ERR_PTR(-ENOMEM);
+
+       fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL);
+       if (!fb->planes)
+               return ERR_PTR(-ENOMEM);
+
+       fb->num_planes = num_planes;
+
+       drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
+
+       for (i = 0; i < fb->num_planes; i++)
+               fb->planes[i] = planes[i];
+
+       err = drm_framebuffer_init(drm, &fb->base, &tegra_fb_funcs);
+       if (err < 0) {
+               dev_err(drm->dev, "failed to initialize framebuffer: %d\n",
+                       err);
+               kfree(fb->planes);
+               kfree(fb);
+               return ERR_PTR(err);
+       }
+
+       return fb;
+}
+
+static struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
+                                              struct drm_file *file,
+                                              struct drm_mode_fb_cmd2 *cmd)
+{
+       unsigned int hsub, vsub, i;
+       struct tegra_bo *planes[4];
+       struct drm_gem_object *gem;
+       struct tegra_fb *fb;
+       int err;
+
+       hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format);
+       vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format);
+
+       for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) {
+               unsigned int width = cmd->width / (i ? hsub : 1);
+               unsigned int height = cmd->height / (i ? vsub : 1);
+               unsigned int size, bpp;
+
+               gem = drm_gem_object_lookup(drm, file, cmd->handles[i]);
+               if (!gem) {
+                       err = -ENXIO;
+                       goto unreference;
+               }
+
+               bpp = drm_format_plane_cpp(cmd->pixel_format, i);
+
+               size = (height - 1) * cmd->pitches[i] +
+                      width * bpp + cmd->offsets[i];
+
+               if (gem->size < size) {
+                       err = -EINVAL;
+                       goto unreference;
+               }
+
+               planes[i] = to_tegra_bo(gem);
+       }
+
+       fb = tegra_fb_alloc(drm, cmd, planes, i);
+       if (IS_ERR(fb)) {
+               err = PTR_ERR(fb);
+               goto unreference;
+       }
+
+       return &fb->base;
+
+unreference:
+       while (i--)
+               drm_gem_object_unreference_unlocked(&planes[i]->gem);
+
+       return ERR_PTR(err);
+}
+
+static struct fb_ops tegra_fb_ops = {
+       .owner = THIS_MODULE,
+       .fb_fillrect = sys_fillrect,
+       .fb_copyarea = sys_copyarea,
+       .fb_imageblit = sys_imageblit,
+       .fb_check_var = drm_fb_helper_check_var,
+       .fb_set_par = drm_fb_helper_set_par,
+       .fb_blank = drm_fb_helper_blank,
+       .fb_pan_display = drm_fb_helper_pan_display,
+       .fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int tegra_fbdev_probe(struct drm_fb_helper *helper,
+                            struct drm_fb_helper_surface_size *sizes)
+{
+       struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
+       struct drm_device *drm = helper->dev;
+       struct drm_mode_fb_cmd2 cmd = { 0 };
+       unsigned int bytes_per_pixel;
+       struct drm_framebuffer *fb;
+       unsigned long offset;
+       struct fb_info *info;
+       struct tegra_bo *bo;
+       size_t size;
+       int err;
+
+       bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+       cmd.width = sizes->surface_width;
+       cmd.height = sizes->surface_height;
+       cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
+       cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+                                                    sizes->surface_depth);
+
+       size = cmd.pitches[0] * cmd.height;
+
+       bo = tegra_bo_create(drm, size);
+       if (IS_ERR(bo))
+               return PTR_ERR(bo);
+
+       info = framebuffer_alloc(0, drm->dev);
+       if (!info) {
+               dev_err(drm->dev, "failed to allocate framebuffer info\n");
+               tegra_bo_free_object(&bo->gem);
+               return -ENOMEM;
+       }
+
+       fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1);
+       if (IS_ERR(fbdev->fb)) {
+               dev_err(drm->dev, "failed to allocate DRM framebuffer\n");
+               err = PTR_ERR(fbdev->fb);
+               goto release;
+       }
+
+       fb = &fbdev->fb->base;
+       helper->fb = fb;
+       helper->fbdev = info;
+
+       info->par = helper;
+       info->flags = FBINFO_FLAG_DEFAULT;
+       info->fbops = &tegra_fb_ops;
+
+       err = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (err < 0) {
+               dev_err(drm->dev, "failed to allocate color map: %d\n", err);
+               goto destroy;
+       }
+
+       drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+       drm_fb_helper_fill_var(info, helper, fb->width, fb->height);
+
+       offset = info->var.xoffset * bytes_per_pixel +
+                info->var.yoffset * fb->pitches[0];
+
+       drm->mode_config.fb_base = (resource_size_t)bo->paddr;
+       info->screen_base = bo->vaddr + offset;
+       info->screen_size = size;
+       info->fix.smem_start = (unsigned long)(bo->paddr + offset);
+       info->fix.smem_len = size;
+
+       return 0;
+
+destroy:
+       drm_framebuffer_unregister_private(fb);
+       tegra_fb_destroy(fb);
+release:
+       framebuffer_release(info);
+       return err;
+}
+
+static struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
+       .fb_probe = tegra_fbdev_probe,
+};
+
+static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
+                                             unsigned int preferred_bpp,
+                                             unsigned int num_crtc,
+                                             unsigned int max_connectors)
+{
+       struct drm_fb_helper *helper;
+       struct tegra_fbdev *fbdev;
+       int err;
+
+       fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+       if (!fbdev) {
+               dev_err(drm->dev, "failed to allocate DRM fbdev\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       fbdev->base.funcs = &tegra_fb_helper_funcs;
+       helper = &fbdev->base;
+
+       err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
+       if (err < 0) {
+               dev_err(drm->dev, "failed to initialize DRM FB helper\n");
+               goto free;
+       }
+
+       err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
+       if (err < 0) {
+               dev_err(drm->dev, "failed to add connectors\n");
+               goto fini;
+       }
+
+       drm_helper_disable_unused_functions(drm);
+
+       err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
+       if (err < 0) {
+               dev_err(drm->dev, "failed to set initial configuration\n");
+               goto fini;
+       }
+
+       return fbdev;
+
+fini:
+       drm_fb_helper_fini(&fbdev->base);
+free:
+       kfree(fbdev);
+       return ERR_PTR(err);
+}
+
+static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
+{
+       struct fb_info *info = fbdev->base.fbdev;
+
+       if (info) {
+               int err;
+
+               err = unregister_framebuffer(info);
+               if (err < 0)
+                       DRM_DEBUG_KMS("failed to unregister framebuffer\n");
+
+               if (info->cmap.len)
+                       fb_dealloc_cmap(&info->cmap);
+
+               framebuffer_release(info);
+       }
+
+       if (fbdev->fb) {
+               drm_framebuffer_unregister_private(&fbdev->fb->base);
+               tegra_fb_destroy(&fbdev->fb->base);
+       }
+
+       drm_fb_helper_fini(&fbdev->base);
+       kfree(fbdev);
+}
+
+static void tegra_fb_output_poll_changed(struct drm_device *drm)
+{
+       struct tegra_drm *tegra = drm->dev_private;
+
+       if (tegra->fbdev)
+               drm_fb_helper_hotplug_event(&tegra->fbdev->base);
+}
+
+static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
+       .fb_create = tegra_fb_create,
+       .output_poll_changed = tegra_fb_output_poll_changed,
+};
+
+int tegra_drm_fb_init(struct drm_device *drm)
+{
+       struct tegra_drm *tegra = drm->dev_private;
+       struct tegra_fbdev *fbdev;
+
+       drm->mode_config.min_width = 0;
+       drm->mode_config.min_height = 0;
+
+       drm->mode_config.max_width = 4096;
+       drm->mode_config.max_height = 4096;
+
+       drm->mode_config.funcs = &tegra_drm_mode_funcs;
+
+       fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
+                                  drm->mode_config.num_connector);
+       if (IS_ERR(fbdev))
+               return PTR_ERR(fbdev);
+
+       tegra->fbdev = fbdev;
+
+       return 0;
+}
+
+void tegra_drm_fb_exit(struct drm_device *drm)
+{
+       struct tegra_drm *tegra = drm->dev_private;
+
+       tegra_fbdev_free(tegra->fbdev);
+}
+
+void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
+{
+       if (fbdev) {
+               drm_modeset_lock_all(fbdev->base.dev);
+               drm_fb_helper_restore_fbdev_mode(&fbdev->base);
+               drm_modeset_unlock_all(fbdev->base.dev);
+       }
+}
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
new file mode 100644 (file)
index 0000000..267c0c2
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * NVIDIA Tegra DRM GEM helper functions
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved.
+ *
+ * Based on the GEM/CMA helpers
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "gem.h"
+
+static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
+{
+       return container_of(bo, struct tegra_bo, base);
+}
+
+static void tegra_bo_put(struct host1x_bo *bo)
+{
+       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+       struct drm_device *drm = obj->gem.dev;
+
+       mutex_lock(&drm->struct_mutex);
+       drm_gem_object_unreference(&obj->gem);
+       mutex_unlock(&drm->struct_mutex);
+}
+
+static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt)
+{
+       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+
+       return obj->paddr;
+}
+
+static void tegra_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt)
+{
+}
+
+static void *tegra_bo_mmap(struct host1x_bo *bo)
+{
+       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+
+       return obj->vaddr;
+}
+
+static void tegra_bo_munmap(struct host1x_bo *bo, void *addr)
+{
+}
+
+static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page)
+{
+       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+
+       return obj->vaddr + page * PAGE_SIZE;
+}
+
+static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page,
+                           void *addr)
+{
+}
+
+static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
+{
+       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+       struct drm_device *drm = obj->gem.dev;
+
+       mutex_lock(&drm->struct_mutex);
+       drm_gem_object_reference(&obj->gem);
+       mutex_unlock(&drm->struct_mutex);
+
+       return bo;
+}
+
+const struct host1x_bo_ops tegra_bo_ops = {
+       .get = tegra_bo_get,
+       .put = tegra_bo_put,
+       .pin = tegra_bo_pin,
+       .unpin = tegra_bo_unpin,
+       .mmap = tegra_bo_mmap,
+       .munmap = tegra_bo_munmap,
+       .kmap = tegra_bo_kmap,
+       .kunmap = tegra_bo_kunmap,
+};
+
+static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo)
+{
+       dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr);
+}
+
+struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size)
+{
+       struct tegra_bo *bo;
+       int err;
+
+       bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+       if (!bo)
+               return ERR_PTR(-ENOMEM);
+
+       host1x_bo_init(&bo->base, &tegra_bo_ops);
+       size = round_up(size, PAGE_SIZE);
+
+       bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr,
+                                          GFP_KERNEL | __GFP_NOWARN);
+       if (!bo->vaddr) {
+               dev_err(drm->dev, "failed to allocate buffer with size %u\n",
+                       size);
+               err = -ENOMEM;
+               goto err_dma;
+       }
+
+       err = drm_gem_object_init(drm, &bo->gem, size);
+       if (err)
+               goto err_init;
+
+       err = drm_gem_create_mmap_offset(&bo->gem);
+       if (err)
+               goto err_mmap;
+
+       return bo;
+
+err_mmap:
+       drm_gem_object_release(&bo->gem);
+err_init:
+       tegra_bo_destroy(drm, bo);
+err_dma:
+       kfree(bo);
+
+       return ERR_PTR(err);
+
+}
+
+struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
+                                            struct drm_device *drm,
+                                            unsigned int size,
+                                            unsigned int *handle)
+{
+       struct tegra_bo *bo;
+       int ret;
+
+       bo = tegra_bo_create(drm, size);
+       if (IS_ERR(bo))
+               return bo;
+
+       ret = drm_gem_handle_create(file, &bo->gem, handle);
+       if (ret)
+               goto err;
+
+       drm_gem_object_unreference_unlocked(&bo->gem);
+
+       return bo;
+
+err:
+       tegra_bo_free_object(&bo->gem);
+       return ERR_PTR(ret);
+}
+
+void tegra_bo_free_object(struct drm_gem_object *gem)
+{
+       struct tegra_bo *bo = to_tegra_bo(gem);
+
+       drm_gem_free_mmap_offset(gem);
+       drm_gem_object_release(gem);
+       tegra_bo_destroy(gem->dev, bo);
+
+       kfree(bo);
+}
+
+int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
+                        struct drm_mode_create_dumb *args)
+{
+       int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+       struct tegra_bo *bo;
+
+       if (args->pitch < min_pitch)
+               args->pitch = min_pitch;
+
+       if (args->size < args->pitch * args->height)
+               args->size = args->pitch * args->height;
+
+       bo = tegra_bo_create_with_handle(file, drm, args->size,
+                                        &args->handle);
+       if (IS_ERR(bo))
+               return PTR_ERR(bo);
+
+       return 0;
+}
+
+int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
+                            uint32_t handle, uint64_t *offset)
+{
+       struct drm_gem_object *gem;
+       struct tegra_bo *bo;
+
+       mutex_lock(&drm->struct_mutex);
+
+       gem = drm_gem_object_lookup(drm, file, handle);
+       if (!gem) {
+               dev_err(drm->dev, "failed to lookup GEM object\n");
+               mutex_unlock(&drm->struct_mutex);
+               return -EINVAL;
+       }
+
+       bo = to_tegra_bo(gem);
+
+       *offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
+
+       drm_gem_object_unreference(gem);
+
+       mutex_unlock(&drm->struct_mutex);
+
+       return 0;
+}
+
+const struct vm_operations_struct tegra_bo_vm_ops = {
+       .open = drm_gem_vm_open,
+       .close = drm_gem_vm_close,
+};
+
+int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct drm_gem_object *gem;
+       struct tegra_bo *bo;
+       int ret;
+
+       ret = drm_gem_mmap(file, vma);
+       if (ret)
+               return ret;
+
+       gem = vma->vm_private_data;
+       bo = to_tegra_bo(gem);
+
+       ret = remap_pfn_range(vma, vma->vm_start, bo->paddr >> PAGE_SHIFT,
+                             vma->vm_end - vma->vm_start, vma->vm_page_prot);
+       if (ret)
+               drm_gem_vm_close(vma);
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h
new file mode 100644 (file)
index 0000000..2b54f14
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Tegra host1x GEM implementation
+ *
+ * Copyright (c) 2012-2013, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HOST1X_GEM_H
+#define __HOST1X_GEM_H
+
+#include <linux/host1x.h>
+
+#include <drm/drm.h>
+#include <drm/drmP.h>
+
+struct tegra_bo {
+       struct drm_gem_object gem;
+       struct host1x_bo base;
+       dma_addr_t paddr;
+       void *vaddr;
+};
+
+static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
+{
+       return container_of(gem, struct tegra_bo, gem);
+}
+
+extern const struct host1x_bo_ops tegra_bo_ops;
+
+struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size);
+struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
+                                           struct drm_device *drm,
+                                           unsigned int size,
+                                           unsigned int *handle);
+void tegra_bo_free_object(struct drm_gem_object *gem);
+int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
+                        struct drm_mode_create_dumb *args);
+int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
+                            uint32_t handle, uint64_t *offset);
+
+int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma);
+
+extern const struct vm_operations_struct tegra_bo_vm_ops;
+
+#endif
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
new file mode 100644 (file)
index 0000000..4e407e3
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2012-2013, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+
+#include "drm.h"
+#include "gem.h"
+
+#define GR2D_NUM_REGS 0x4d
+
+struct gr2d {
+       struct tegra_drm_client client;
+       struct host1x_channel *channel;
+       struct clk *clk;
+
+       DECLARE_BITMAP(addr_regs, GR2D_NUM_REGS);
+};
+
+static inline struct gr2d *to_gr2d(struct tegra_drm_client *client)
+{
+       return container_of(client, struct gr2d, client);
+}
+
+static int gr2d_init(struct host1x_client *client)
+{
+       struct tegra_drm_client *drm = host1x_to_drm_client(client);
+       struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+       struct gr2d *gr2d = to_gr2d(drm);
+
+       gr2d->channel = host1x_channel_request(client->dev);
+       if (!gr2d->channel)
+               return -ENOMEM;
+
+       client->syncpts[0] = host1x_syncpt_request(client->dev, false);
+       if (!client->syncpts[0]) {
+               host1x_channel_free(gr2d->channel);
+               return -ENOMEM;
+       }
+
+       return tegra_drm_register_client(tegra, drm);
+}
+
+static int gr2d_exit(struct host1x_client *client)
+{
+       struct tegra_drm_client *drm = host1x_to_drm_client(client);
+       struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+       struct gr2d *gr2d = to_gr2d(drm);
+       int err;
+
+       err = tegra_drm_unregister_client(tegra, drm);
+       if (err < 0)
+               return err;
+
+       host1x_syncpt_free(client->syncpts[0]);
+       host1x_channel_free(gr2d->channel);
+
+       return 0;
+}
+
+static const struct host1x_client_ops gr2d_client_ops = {
+       .init = gr2d_init,
+       .exit = gr2d_exit,
+};
+
+static int gr2d_open_channel(struct tegra_drm_client *client,
+                            struct tegra_drm_context *context)
+{
+       struct gr2d *gr2d = to_gr2d(client);
+
+       context->channel = host1x_channel_get(gr2d->channel);
+       if (!context->channel)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void gr2d_close_channel(struct tegra_drm_context *context)
+{
+       host1x_channel_put(context->channel);
+}
+
+static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm,
+                                         struct drm_file *file,
+                                         u32 handle)
+{
+       struct drm_gem_object *gem;
+       struct tegra_bo *bo;
+
+       gem = drm_gem_object_lookup(drm, file, handle);
+       if (!gem)
+               return NULL;
+
+       mutex_lock(&drm->struct_mutex);
+       drm_gem_object_unreference(gem);
+       mutex_unlock(&drm->struct_mutex);
+
+       bo = to_tegra_bo(gem);
+       return &bo->base;
+}
+
+static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset)
+{
+       struct gr2d *gr2d = dev_get_drvdata(dev);
+
+       switch (class) {
+       case HOST1X_CLASS_HOST1X:
+               if (offset == 0x2b)
+                       return 1;
+
+               break;
+
+       case HOST1X_CLASS_GR2D:
+       case HOST1X_CLASS_GR2D_SB:
+               if (offset >= GR2D_NUM_REGS)
+                       break;
+
+               if (test_bit(offset, gr2d->addr_regs))
+                       return 1;
+
+               break;
+       }
+
+       return 0;
+}
+
+static int gr2d_submit(struct tegra_drm_context *context,
+                      struct drm_tegra_submit *args, struct drm_device *drm,
+                      struct drm_file *file)
+{
+       unsigned int num_cmdbufs = args->num_cmdbufs;
+       unsigned int num_relocs = args->num_relocs;
+       unsigned int num_waitchks = args->num_waitchks;
+       struct drm_tegra_cmdbuf __user *cmdbufs =
+               (void * __user)(uintptr_t)args->cmdbufs;
+       struct drm_tegra_reloc __user *relocs =
+               (void * __user)(uintptr_t)args->relocs;
+       struct drm_tegra_waitchk __user *waitchks =
+               (void * __user)(uintptr_t)args->waitchks;
+       struct drm_tegra_syncpt syncpt;
+       struct host1x_job *job;
+       int err;
+
+       /* We don't yet support other than one syncpt_incr struct per submit */
+       if (args->num_syncpts != 1)
+               return -EINVAL;
+
+       job = host1x_job_alloc(context->channel, args->num_cmdbufs,
+                              args->num_relocs, args->num_waitchks);
+       if (!job)
+               return -ENOMEM;
+
+       job->num_relocs = args->num_relocs;
+       job->num_waitchk = args->num_waitchks;
+       job->client = (u32)args->context;
+       job->class = context->client->base.class;
+       job->serialize = true;
+
+       while (num_cmdbufs) {
+               struct drm_tegra_cmdbuf cmdbuf;
+               struct host1x_bo *bo;
+
+               err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf));
+               if (err)
+                       goto fail;
+
+               bo = host1x_bo_lookup(drm, file, cmdbuf.handle);
+               if (!bo) {
+                       err = -ENOENT;
+                       goto fail;
+               }
+
+               host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset);
+               num_cmdbufs--;
+               cmdbufs++;
+       }
+
+       err = copy_from_user(job->relocarray, relocs,
+                            sizeof(*relocs) * num_relocs);
+       if (err)
+               goto fail;
+
+       while (num_relocs--) {
+               struct host1x_reloc *reloc = &job->relocarray[num_relocs];
+               struct host1x_bo *cmdbuf, *target;
+
+               cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf);
+               target = host1x_bo_lookup(drm, file, (u32)reloc->target);
+
+               reloc->cmdbuf = cmdbuf;
+               reloc->target = target;
+
+               if (!reloc->target || !reloc->cmdbuf) {
+                       err = -ENOENT;
+                       goto fail;
+               }
+       }
+
+       err = copy_from_user(job->waitchk, waitchks,
+                            sizeof(*waitchks) * num_waitchks);
+       if (err)
+               goto fail;
+
+       err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts,
+                            sizeof(syncpt));
+       if (err)
+               goto fail;
+
+       job->syncpt_id = syncpt.id;
+       job->syncpt_incrs = syncpt.incrs;
+       job->timeout = 10000;
+       job->is_addr_reg = gr2d_is_addr_reg;
+
+       if (args->timeout && args->timeout < 10000)
+               job->timeout = args->timeout;
+
+       err = host1x_job_pin(job, context->client->base.dev);
+       if (err)
+               goto fail;
+
+       err = host1x_job_submit(job);
+       if (err)
+               goto fail_submit;
+
+       args->fence = job->syncpt_end;
+
+       host1x_job_put(job);
+       return 0;
+
+fail_submit:
+       host1x_job_unpin(job);
+fail:
+       host1x_job_put(job);
+       return err;
+}
+
+static const struct tegra_drm_client_ops gr2d_ops = {
+       .open_channel = gr2d_open_channel,
+       .close_channel = gr2d_close_channel,
+       .submit = gr2d_submit,
+};
+
+static const struct of_device_id gr2d_match[] = {
+       { .compatible = "nvidia,tegra30-gr2d" },
+       { .compatible = "nvidia,tegra20-gr2d" },
+       { },
+};
+
+static const u32 gr2d_addr_regs[] = {
+       0x1a, 0x1b, 0x26, 0x2b, 0x2c, 0x2d, 0x31, 0x32,
+       0x48, 0x49, 0x4a, 0x4b, 0x4c
+};
+
+static int gr2d_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct host1x_syncpt **syncpts;
+       struct gr2d *gr2d;
+       unsigned int i;
+       int err;
+
+       gr2d = devm_kzalloc(dev, sizeof(*gr2d), GFP_KERNEL);
+       if (!gr2d)
+               return -ENOMEM;
+
+       syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
+       if (!syncpts)
+               return -ENOMEM;
+
+       gr2d->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(gr2d->clk)) {
+               dev_err(dev, "cannot get clock\n");
+               return PTR_ERR(gr2d->clk);
+       }
+
+       err = clk_prepare_enable(gr2d->clk);
+       if (err) {
+               dev_err(dev, "cannot turn on clock\n");
+               return err;
+       }
+
+       INIT_LIST_HEAD(&gr2d->client.base.list);
+       gr2d->client.base.ops = &gr2d_client_ops;
+       gr2d->client.base.dev = dev;
+       gr2d->client.base.class = HOST1X_CLASS_GR2D;
+       gr2d->client.base.syncpts = syncpts;
+       gr2d->client.base.num_syncpts = 1;
+
+       INIT_LIST_HEAD(&gr2d->client.list);
+       gr2d->client.ops = &gr2d_ops;
+
+       err = host1x_client_register(&gr2d->client.base);
+       if (err < 0) {
+               dev_err(dev, "failed to register host1x client: %d\n", err);
+               return err;
+       }
+
+       /* initialize address register map */
+       for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); i++)
+               set_bit(gr2d_addr_regs[i], gr2d->addr_regs);
+
+       platform_set_drvdata(pdev, gr2d);
+
+       return 0;
+}
+
+static int gr2d_remove(struct platform_device *pdev)
+{
+       struct gr2d *gr2d = platform_get_drvdata(pdev);
+       int err;
+
+       err = host1x_client_unregister(&gr2d->client.base);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
+                       err);
+               return err;
+       }
+
+       clk_disable_unprepare(gr2d->clk);
+
+       return 0;
+}
+
+struct platform_driver tegra_gr2d_driver = {
+       .driver = {
+               .name = "tegra-gr2d",
+               .of_match_table = gr2d_match,
+       },
+       .probe = gr2d_probe,
+       .remove = gr2d_remove,
+};
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
new file mode 100644 (file)
index 0000000..f5663d1
--- /dev/null
@@ -0,0 +1,1295 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk/tegra.h>
+#include <linux/debugfs.h>
+#include <linux/hdmi.h>
+#include <linux/regulator/consumer.h>
+
+#include "hdmi.h"
+#include "drm.h"
+#include "dc.h"
+
+struct tegra_hdmi {
+       struct host1x_client client;
+       struct tegra_output output;
+       struct device *dev;
+
+       struct regulator *vdd;
+       struct regulator *pll;
+
+       void __iomem *regs;
+       unsigned int irq;
+
+       struct clk *clk_parent;
+       struct clk *clk;
+
+       unsigned int audio_source;
+       unsigned int audio_freq;
+       bool stereo;
+       bool dvi;
+
+       struct drm_info_list *debugfs_files;
+       struct drm_minor *minor;
+       struct dentry *debugfs;
+};
+
+static inline struct tegra_hdmi *
+host1x_client_to_hdmi(struct host1x_client *client)
+{
+       return container_of(client, struct tegra_hdmi, client);
+}
+
+static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output)
+{
+       return container_of(output, struct tegra_hdmi, output);
+}
+
+#define HDMI_AUDIOCLK_FREQ 216000000
+#define HDMI_REKEY_DEFAULT 56
+
+enum {
+       AUTO = 0,
+       SPDIF,
+       HDA,
+};
+
+static inline unsigned long tegra_hdmi_readl(struct tegra_hdmi *hdmi,
+                                            unsigned long reg)
+{
+       return readl(hdmi->regs + (reg << 2));
+}
+
+static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, unsigned long val,
+                                    unsigned long reg)
+{
+       writel(val, hdmi->regs + (reg << 2));
+}
+
+struct tegra_hdmi_audio_config {
+       unsigned int pclk;
+       unsigned int n;
+       unsigned int cts;
+       unsigned int aval;
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
+       {  25200000, 4096,  25200, 24000 },
+       {  27000000, 4096,  27000, 24000 },
+       {  74250000, 4096,  74250, 24000 },
+       { 148500000, 4096, 148500, 24000 },
+       {         0,    0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
+       {  25200000, 5880,  26250, 25000 },
+       {  27000000, 5880,  28125, 25000 },
+       {  74250000, 4704,  61875, 20000 },
+       { 148500000, 4704, 123750, 20000 },
+       {         0,    0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
+       {  25200000, 6144,  25200, 24000 },
+       {  27000000, 6144,  27000, 24000 },
+       {  74250000, 6144,  74250, 24000 },
+       { 148500000, 6144, 148500, 24000 },
+       {         0,    0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
+       {  25200000, 11760,  26250, 25000 },
+       {  27000000, 11760,  28125, 25000 },
+       {  74250000,  9408,  61875, 20000 },
+       { 148500000,  9408, 123750, 20000 },
+       {         0,     0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
+       {  25200000, 12288,  25200, 24000 },
+       {  27000000, 12288,  27000, 24000 },
+       {  74250000, 12288,  74250, 24000 },
+       { 148500000, 12288, 148500, 24000 },
+       {         0,     0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
+       {  25200000, 23520,  26250, 25000 },
+       {  27000000, 23520,  28125, 25000 },
+       {  74250000, 18816,  61875, 20000 },
+       { 148500000, 18816, 123750, 20000 },
+       {         0,     0,      0,     0 },
+};
+
+static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
+       {  25200000, 24576,  25200, 24000 },
+       {  27000000, 24576,  27000, 24000 },
+       {  74250000, 24576,  74250, 24000 },
+       { 148500000, 24576, 148500, 24000 },
+       {         0,     0,      0,     0 },
+};
+
+struct tmds_config {
+       unsigned int pclk;
+       u32 pll0;
+       u32 pll1;
+       u32 pe_current;
+       u32 drive_current;
+};
+
+static const struct tmds_config tegra2_tmds_config[] = {
+       { /* slow pixel clock modes */
+               .pclk = 27000000,
+               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
+                       SOR_PLL_TX_REG_LOAD(3),
+               .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
+               .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
+                       PE_CURRENT1(PE_CURRENT_0_0_mA) |
+                       PE_CURRENT2(PE_CURRENT_0_0_mA) |
+                       PE_CURRENT3(PE_CURRENT_0_0_mA),
+               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
+                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
+                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
+                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
+       },
+       { /* high pixel clock modes */
+               .pclk = UINT_MAX,
+               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
+                       SOR_PLL_TX_REG_LOAD(3),
+               .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
+               .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
+                       PE_CURRENT1(PE_CURRENT_6_0_mA) |
+                       PE_CURRENT2(PE_CURRENT_6_0_mA) |
+                       PE_CURRENT3(PE_CURRENT_6_0_mA),
+               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
+                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
+                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
+                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
+       },
+};
+
+static const struct tmds_config tegra3_tmds_config[] = {
+       { /* 480p modes */
+               .pclk = 27000000,
+               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
+                       SOR_PLL_TX_REG_LOAD(0),
+               .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
+               .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
+                       PE_CURRENT1(PE_CURRENT_0_0_mA) |
+                       PE_CURRENT2(PE_CURRENT_0_0_mA) |
+                       PE_CURRENT3(PE_CURRENT_0_0_mA),
+               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
+                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
+                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
+                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
+       }, { /* 720p modes */
+               .pclk = 74250000,
+               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
+                       SOR_PLL_TX_REG_LOAD(0),
+               .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
+               .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
+                       PE_CURRENT1(PE_CURRENT_5_0_mA) |
+                       PE_CURRENT2(PE_CURRENT_5_0_mA) |
+                       PE_CURRENT3(PE_CURRENT_5_0_mA),
+               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
+                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
+                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
+                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
+       }, { /* 1080p modes */
+               .pclk = UINT_MAX,
+               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
+                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) |
+                       SOR_PLL_TX_REG_LOAD(0),
+               .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
+               .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
+                       PE_CURRENT1(PE_CURRENT_5_0_mA) |
+                       PE_CURRENT2(PE_CURRENT_5_0_mA) |
+                       PE_CURRENT3(PE_CURRENT_5_0_mA),
+               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
+                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
+                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
+                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
+       },
+};
+
+static const struct tegra_hdmi_audio_config *
+tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
+{
+       const struct tegra_hdmi_audio_config *table;
+
+       switch (audio_freq) {
+       case 32000:
+               table = tegra_hdmi_audio_32k;
+               break;
+
+       case 44100:
+               table = tegra_hdmi_audio_44_1k;
+               break;
+
+       case 48000:
+               table = tegra_hdmi_audio_48k;
+               break;
+
+       case 88200:
+               table = tegra_hdmi_audio_88_2k;
+               break;
+
+       case 96000:
+               table = tegra_hdmi_audio_96k;
+               break;
+
+       case 176400:
+               table = tegra_hdmi_audio_176_4k;
+               break;
+
+       case 192000:
+               table = tegra_hdmi_audio_192k;
+               break;
+
+       default:
+               return NULL;
+       }
+
+       while (table->pclk) {
+               if (table->pclk == pclk)
+                       return table;
+
+               table++;
+       }
+
+       return NULL;
+}
+
+static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
+{
+       const unsigned int freqs[] = {
+               32000, 44100, 48000, 88200, 96000, 176400, 192000
+       };
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(freqs); i++) {
+               unsigned int f = freqs[i];
+               unsigned int eight_half;
+               unsigned long value;
+               unsigned int delta;
+
+               if (f > 96000)
+                       delta = 2;
+               else if (f > 480000)
+                       delta = 6;
+               else
+                       delta = 9;
+
+               eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
+               value = AUDIO_FS_LOW(eight_half - delta) |
+                       AUDIO_FS_HIGH(eight_half + delta);
+               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i));
+       }
+}
+
+static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
+{
+       struct device_node *node = hdmi->dev->of_node;
+       const struct tegra_hdmi_audio_config *config;
+       unsigned int offset = 0;
+       unsigned long value;
+
+       switch (hdmi->audio_source) {
+       case HDA:
+               value = AUDIO_CNTRL0_SOURCE_SELECT_HDAL;
+               break;
+
+       case SPDIF:
+               value = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF;
+               break;
+
+       default:
+               value = AUDIO_CNTRL0_SOURCE_SELECT_AUTO;
+               break;
+       }
+
+       if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
+               value |= AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
+                        AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
+               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
+       } else {
+               value |= AUDIO_CNTRL0_INJECT_NULLSMPL;
+               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
+
+               value = AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
+                       AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
+               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
+       }
+
+       config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk);
+       if (!config) {
+               dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n",
+                       hdmi->audio_freq, pclk);
+               return -EINVAL;
+       }
+
+       tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
+
+       value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE |
+               AUDIO_N_VALUE(config->n - 1);
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
+
+       tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
+                         HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
+
+       value = ACR_SUBPACK_CTS(config->cts);
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
+
+       value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1);
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE);
+
+       value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N);
+       value &= ~AUDIO_N_RESETF;
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
+
+       if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
+               switch (hdmi->audio_freq) {
+               case 32000:
+                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320;
+                       break;
+
+               case 44100:
+                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441;
+                       break;
+
+               case 48000:
+                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480;
+                       break;
+
+               case 88200:
+                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882;
+                       break;
+
+               case 96000:
+                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960;
+                       break;
+
+               case 176400:
+                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764;
+                       break;
+
+               case 192000:
+                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920;
+                       break;
+               }
+
+               tegra_hdmi_writel(hdmi, config->aval, offset);
+       }
+
+       tegra_hdmi_setup_audio_fs_tables(hdmi);
+
+       return 0;
+}
+
+static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size)
+{
+       unsigned long value = 0;
+       size_t i;
+
+       for (i = size; i > 0; i--)
+               value = (value << 8) | ptr[i - 1];
+
+       return value;
+}
+
+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;
+
+       switch (ptr[0]) {
+       case HDMI_INFOFRAME_TYPE_AVI:
+               offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER;
+               break;
+
+       case HDMI_INFOFRAME_TYPE_AUDIO:
+               offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER;
+               break;
+
+       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;
+       }
+
+       value = INFOFRAME_HEADER_TYPE(ptr[0]) |
+               INFOFRAME_HEADER_VERSION(ptr[1]) |
+               INFOFRAME_HEADER_LEN(ptr[2]);
+       tegra_hdmi_writel(hdmi, value, offset);
+       offset++;
+
+       /*
+        * 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);
+
+               value = tegra_hdmi_subpack(&ptr[i], num);
+               tegra_hdmi_writel(hdmi, value, offset++);
+
+               num = min_t(size_t, rem - num, 3);
+
+               value = tegra_hdmi_subpack(&ptr[i + 4], num);
+               tegra_hdmi_writel(hdmi, value, offset++);
+       }
+}
+
+static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
+                                          struct drm_display_mode *mode)
+{
+       struct hdmi_avi_infoframe frame;
+       u8 buffer[17];
+       ssize_t err;
+
+       if (hdmi->dvi) {
+               tegra_hdmi_writel(hdmi, 0,
+                                 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
+               return;
+       }
+
+       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;
+       }
+
+       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, 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,
+                                 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
+               return;
+       }
+
+       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;
+       }
+
+       /*
+        * 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_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);
+               value &= ~GENERIC_CTRL_ENABLE;
+               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+               return;
+       }
+
+       hdmi_vendor_infoframe_init(&frame);
+       frame.s3d_struct = HDMI_3D_STRUCTURE_FRAME_PACKING;
+
+       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, buffer, err);
+
+       value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+       value |= GENERIC_CTRL_ENABLE;
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+}
+
+static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
+                                 const struct tmds_config *tmds)
+{
+       unsigned long value;
+
+       tegra_hdmi_writel(hdmi, tmds->pll0, HDMI_NV_PDISP_SOR_PLL0);
+       tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
+       tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
+
+       value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
+}
+
+static int tegra_output_hdmi_enable(struct tegra_output *output)
+{
+       unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
+       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct drm_display_mode *mode = &dc->base.mode;
+       struct tegra_hdmi *hdmi = to_hdmi(output);
+       struct device_node *node = hdmi->dev->of_node;
+       unsigned int pulse_start, div82, pclk;
+       const struct tmds_config *tmds;
+       unsigned int num_tmds;
+       unsigned long value;
+       int retries = 1000;
+       int err;
+
+       pclk = mode->clock * 1000;
+       h_sync_width = mode->hsync_end - mode->hsync_start;
+       h_back_porch = mode->htotal - mode->hsync_end;
+       h_front_porch = mode->hsync_start - mode->hdisplay;
+
+       err = regulator_enable(hdmi->vdd);
+       if (err < 0) {
+               dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n", err);
+               return err;
+       }
+
+       err = regulator_enable(hdmi->pll);
+       if (err < 0) {
+               dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n", err);
+               return err;
+       }
+
+       /*
+        * This assumes that the display controller will divide its parent
+        * clock by 2 to generate the pixel clock.
+        */
+       err = tegra_output_setup_clock(output, hdmi->clk, pclk * 2);
+       if (err < 0) {
+               dev_err(hdmi->dev, "failed to setup clock: %d\n", err);
+               return err;
+       }
+
+       err = clk_set_rate(hdmi->clk, pclk);
+       if (err < 0)
+               return err;
+
+       err = clk_enable(hdmi->clk);
+       if (err < 0) {
+               dev_err(hdmi->dev, "failed to enable clock: %d\n", err);
+               return err;
+       }
+
+       tegra_periph_reset_assert(hdmi->clk);
+       usleep_range(1000, 2000);
+       tegra_periph_reset_deassert(hdmi->clk);
+
+       tegra_dc_writel(dc, VSYNC_H_POSITION(1),
+                       DC_DISP_DISP_TIMING_OPTIONS);
+       tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
+                       DC_DISP_DISP_COLOR_CONTROL);
+
+       /* video_preamble uses h_pulse2 */
+       pulse_start = 1 + h_sync_width + h_back_porch - 10;
+
+       tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
+
+       value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE |
+               PULSE_LAST_END_A;
+       tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
+
+       value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8);
+       tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
+
+       value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) |
+               VSYNC_WINDOW_ENABLE;
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
+
+       if (dc->pipe)
+               value = HDMI_SRC_DISPLAYB;
+       else
+               value = HDMI_SRC_DISPLAYA;
+
+       if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) ||
+                                       (mode->vdisplay == 576)))
+               tegra_hdmi_writel(hdmi,
+                                 value | ARM_VIDEO_RANGE_FULL,
+                                 HDMI_NV_PDISP_INPUT_CONTROL);
+       else
+               tegra_hdmi_writel(hdmi,
+                                 value | ARM_VIDEO_RANGE_LIMITED,
+                                 HDMI_NV_PDISP_INPUT_CONTROL);
+
+       div82 = clk_get_rate(hdmi->clk) / 1000000 * 4;
+       value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82);
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK);
+
+       if (!hdmi->dvi) {
+               err = tegra_hdmi_setup_audio(hdmi, pclk);
+               if (err < 0)
+                       hdmi->dvi = true;
+       }
+
+       if (of_device_is_compatible(node, "nvidia,tegra20-hdmi")) {
+               /*
+                * TODO: add ELD support
+                */
+       }
+
+       rekey = HDMI_REKEY_DEFAULT;
+       value = HDMI_CTRL_REKEY(rekey);
+       value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch +
+                                         h_front_porch - rekey - 18) / 32);
+
+       if (!hdmi->dvi)
+               value |= HDMI_CTRL_ENABLE;
+
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL);
+
+       if (hdmi->dvi)
+               tegra_hdmi_writel(hdmi, 0x0,
+                                 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+       else
+               tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
+                                 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+
+       tegra_hdmi_setup_avi_infoframe(hdmi, mode);
+       tegra_hdmi_setup_audio_infoframe(hdmi);
+       tegra_hdmi_setup_stereo_infoframe(hdmi);
+
+       /* TMDS CONFIG */
+       if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
+               num_tmds = ARRAY_SIZE(tegra3_tmds_config);
+               tmds = tegra3_tmds_config;
+       } else {
+               num_tmds = ARRAY_SIZE(tegra2_tmds_config);
+               tmds = tegra2_tmds_config;
+       }
+
+       for (i = 0; i < num_tmds; i++) {
+               if (pclk <= tmds[i].pclk) {
+                       tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
+                       break;
+               }
+       }
+
+       tegra_hdmi_writel(hdmi,
+                         SOR_SEQ_CTL_PU_PC(0) |
+                         SOR_SEQ_PU_PC_ALT(0) |
+                         SOR_SEQ_PD_PC(8) |
+                         SOR_SEQ_PD_PC_ALT(8),
+                         HDMI_NV_PDISP_SOR_SEQ_CTL);
+
+       value = SOR_SEQ_INST_WAIT_TIME(1) |
+               SOR_SEQ_INST_WAIT_UNITS_VSYNC |
+               SOR_SEQ_INST_HALT |
+               SOR_SEQ_INST_PIN_A_LOW |
+               SOR_SEQ_INST_PIN_B_LOW |
+               SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
+
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0));
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8));
+
+       value = 0x1c800;
+       value &= ~SOR_CSTM_ROTCLK(~0);
+       value |= SOR_CSTM_ROTCLK(2);
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
+
+       tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
+       tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+       tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+       /* start SOR */
+       tegra_hdmi_writel(hdmi,
+                         SOR_PWR_NORMAL_STATE_PU |
+                         SOR_PWR_NORMAL_START_NORMAL |
+                         SOR_PWR_SAFE_STATE_PD |
+                         SOR_PWR_SETTING_NEW_TRIGGER,
+                         HDMI_NV_PDISP_SOR_PWR);
+       tegra_hdmi_writel(hdmi,
+                         SOR_PWR_NORMAL_STATE_PU |
+                         SOR_PWR_NORMAL_START_NORMAL |
+                         SOR_PWR_SAFE_STATE_PD |
+                         SOR_PWR_SETTING_NEW_DONE,
+                         HDMI_NV_PDISP_SOR_PWR);
+
+       do {
+               BUG_ON(--retries < 0);
+               value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR);
+       } while (value & SOR_PWR_SETTING_NEW_PENDING);
+
+       value = SOR_STATE_ASY_CRCMODE_COMPLETE |
+               SOR_STATE_ASY_OWNER_HEAD0 |
+               SOR_STATE_ASY_SUBOWNER_BOTH |
+               SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
+               SOR_STATE_ASY_DEPOL_POS;
+
+       /* setup sync polarities */
+       if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+               value |= SOR_STATE_ASY_HSYNCPOL_POS;
+
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+               value |= SOR_STATE_ASY_HSYNCPOL_NEG;
+
+       if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+               value |= SOR_STATE_ASY_VSYNCPOL_POS;
+
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+               value |= SOR_STATE_ASY_VSYNCPOL_NEG;
+
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2);
+
+       value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
+       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1);
+
+       tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
+       tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0);
+       tegra_hdmi_writel(hdmi, value | SOR_STATE_ATTACHED,
+                         HDMI_NV_PDISP_SOR_STATE1);
+       tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
+
+       tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
+
+       value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+               PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
+       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
+
+       value = DISP_CTRL_MODE_C_DISPLAY;
+       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+       tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+       tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+
+       /* TODO: add HDCP support */
+
+       return 0;
+}
+
+static int tegra_output_hdmi_disable(struct tegra_output *output)
+{
+       struct tegra_hdmi *hdmi = to_hdmi(output);
+
+       tegra_periph_reset_assert(hdmi->clk);
+       clk_disable(hdmi->clk);
+       regulator_disable(hdmi->pll);
+       regulator_disable(hdmi->vdd);
+
+       return 0;
+}
+
+static int tegra_output_hdmi_setup_clock(struct tegra_output *output,
+                                        struct clk *clk, unsigned long pclk)
+{
+       struct tegra_hdmi *hdmi = to_hdmi(output);
+       struct clk *base;
+       int err;
+
+       err = clk_set_parent(clk, hdmi->clk_parent);
+       if (err < 0) {
+               dev_err(output->dev, "failed to set parent: %d\n", err);
+               return err;
+       }
+
+       base = clk_get_parent(hdmi->clk_parent);
+
+       /*
+        * This assumes that the parent clock is pll_d_out0 or pll_d2_out
+        * respectively, each of which divides the base pll_d by 2.
+        */
+       err = clk_set_rate(base, pclk * 2);
+       if (err < 0)
+               dev_err(output->dev,
+                       "failed to set base clock rate to %lu Hz\n",
+                       pclk * 2);
+
+       return 0;
+}
+
+static int tegra_output_hdmi_check_mode(struct tegra_output *output,
+                                       struct drm_display_mode *mode,
+                                       enum drm_mode_status *status)
+{
+       struct tegra_hdmi *hdmi = to_hdmi(output);
+       unsigned long pclk = mode->clock * 1000;
+       struct clk *parent;
+       long err;
+
+       parent = clk_get_parent(hdmi->clk_parent);
+
+       err = clk_round_rate(parent, pclk * 4);
+       if (err < 0)
+               *status = MODE_NOCLOCK;
+       else
+               *status = MODE_OK;
+
+       return 0;
+}
+
+static const struct tegra_output_ops hdmi_ops = {
+       .enable = tegra_output_hdmi_enable,
+       .disable = tegra_output_hdmi_disable,
+       .setup_clock = tegra_output_hdmi_setup_clock,
+       .check_mode = tegra_output_hdmi_check_mode,
+};
+
+static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
+{
+       struct drm_info_node *node = s->private;
+       struct tegra_hdmi *hdmi = node->info_ent->data;
+       int err;
+
+       err = clk_enable(hdmi->clk);
+       if (err)
+               return err;
+
+#define DUMP_REG(name)                                         \
+       seq_printf(s, "%-56s %#05x %08lx\n", #name, name,       \
+               tegra_hdmi_readl(hdmi, name))
+
+       DUMP_REG(HDMI_CTXSW);
+       DUMP_REG(HDMI_NV_PDISP_SOR_STATE0);
+       DUMP_REG(HDMI_NV_PDISP_SOR_STATE1);
+       DUMP_REG(HDMI_NV_PDISP_SOR_STATE2);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB);
+       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2);
+       DUMP_REG(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL);
+       DUMP_REG(HDMI_NV_PDISP_SOR_CAP);
+       DUMP_REG(HDMI_NV_PDISP_SOR_PWR);
+       DUMP_REG(HDMI_NV_PDISP_SOR_TEST);
+       DUMP_REG(HDMI_NV_PDISP_SOR_PLL0);
+       DUMP_REG(HDMI_NV_PDISP_SOR_PLL1);
+       DUMP_REG(HDMI_NV_PDISP_SOR_PLL2);
+       DUMP_REG(HDMI_NV_PDISP_SOR_CSTM);
+       DUMP_REG(HDMI_NV_PDISP_SOR_LVDS);
+       DUMP_REG(HDMI_NV_PDISP_SOR_CRCA);
+       DUMP_REG(HDMI_NV_PDISP_SOR_CRCB);
+       DUMP_REG(HDMI_NV_PDISP_SOR_BLANK);
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL);
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(0));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(1));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(2));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(3));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(4));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(5));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(6));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(7));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(8));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(9));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(10));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(11));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(12));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(13));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(14));
+       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(15));
+       DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0);
+       DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1);
+       DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0);
+       DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1);
+       DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0);
+       DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1);
+       DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0);
+       DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1);
+       DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0);
+       DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1);
+       DUMP_REG(HDMI_NV_PDISP_SOR_TRIG);
+       DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK);
+       DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
+       DUMP_REG(HDMI_NV_PDISP_AUDIO_N);
+       DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING);
+       DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK);
+       DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL);
+       DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL);
+       DUMP_REG(HDMI_NV_PDISP_SCRATCH);
+       DUMP_REG(HDMI_NV_PDISP_PE_CURRENT);
+       DUMP_REG(HDMI_NV_PDISP_KEY_CTRL);
+       DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0);
+       DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1);
+       DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2);
+       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0);
+       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1);
+       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2);
+       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3);
+       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
+       DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX);
+       DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
+       DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
+       DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
+
+#undef DUMP_REG
+
+       clk_disable(hdmi->clk);
+
+       return 0;
+}
+
+static struct drm_info_list debugfs_files[] = {
+       { "regs", tegra_hdmi_show_regs, 0, NULL },
+};
+
+static int tegra_hdmi_debugfs_init(struct tegra_hdmi *hdmi,
+                                  struct drm_minor *minor)
+{
+       unsigned int i;
+       int err;
+
+       hdmi->debugfs = debugfs_create_dir("hdmi", minor->debugfs_root);
+       if (!hdmi->debugfs)
+               return -ENOMEM;
+
+       hdmi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
+                                     GFP_KERNEL);
+       if (!hdmi->debugfs_files) {
+               err = -ENOMEM;
+               goto remove;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
+               hdmi->debugfs_files[i].data = hdmi;
+
+       err = drm_debugfs_create_files(hdmi->debugfs_files,
+                                      ARRAY_SIZE(debugfs_files),
+                                      hdmi->debugfs, minor);
+       if (err < 0)
+               goto free;
+
+       hdmi->minor = minor;
+
+       return 0;
+
+free:
+       kfree(hdmi->debugfs_files);
+       hdmi->debugfs_files = NULL;
+remove:
+       debugfs_remove(hdmi->debugfs);
+       hdmi->debugfs = NULL;
+
+       return err;
+}
+
+static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
+{
+       drm_debugfs_remove_files(hdmi->debugfs_files, ARRAY_SIZE(debugfs_files),
+                                hdmi->minor);
+       hdmi->minor = NULL;
+
+       kfree(hdmi->debugfs_files);
+       hdmi->debugfs_files = NULL;
+
+       debugfs_remove(hdmi->debugfs);
+       hdmi->debugfs = NULL;
+
+       return 0;
+}
+
+static int tegra_hdmi_init(struct host1x_client *client)
+{
+       struct tegra_drm *tegra = dev_get_drvdata(client->parent);
+       struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
+       int err;
+
+       hdmi->output.type = TEGRA_OUTPUT_HDMI;
+       hdmi->output.dev = client->dev;
+       hdmi->output.ops = &hdmi_ops;
+
+       err = tegra_output_init(tegra->drm, &hdmi->output);
+       if (err < 0) {
+               dev_err(client->dev, "output setup failed: %d\n", err);
+               return err;
+       }
+
+       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+               err = tegra_hdmi_debugfs_init(hdmi, tegra->drm->primary);
+               if (err < 0)
+                       dev_err(client->dev, "debugfs setup failed: %d\n", err);
+       }
+
+       return 0;
+}
+
+static int tegra_hdmi_exit(struct host1x_client *client)
+{
+       struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
+       int err;
+
+       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
+               err = tegra_hdmi_debugfs_exit(hdmi);
+               if (err < 0)
+                       dev_err(client->dev, "debugfs cleanup failed: %d\n",
+                               err);
+       }
+
+       err = tegra_output_disable(&hdmi->output);
+       if (err < 0) {
+               dev_err(client->dev, "output failed to disable: %d\n", err);
+               return err;
+       }
+
+       err = tegra_output_exit(&hdmi->output);
+       if (err < 0) {
+               dev_err(client->dev, "output cleanup failed: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static const struct host1x_client_ops hdmi_client_ops = {
+       .init = tegra_hdmi_init,
+       .exit = tegra_hdmi_exit,
+};
+
+static int tegra_hdmi_probe(struct platform_device *pdev)
+{
+       struct tegra_hdmi *hdmi;
+       struct resource *regs;
+       int err;
+
+       hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+       if (!hdmi)
+               return -ENOMEM;
+
+       hdmi->dev = &pdev->dev;
+       hdmi->audio_source = AUTO;
+       hdmi->audio_freq = 44100;
+       hdmi->stereo = false;
+       hdmi->dvi = false;
+
+       hdmi->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(hdmi->clk)) {
+               dev_err(&pdev->dev, "failed to get clock\n");
+               return PTR_ERR(hdmi->clk);
+       }
+
+       err = clk_prepare(hdmi->clk);
+       if (err < 0)
+               return err;
+
+       hdmi->clk_parent = devm_clk_get(&pdev->dev, "parent");
+       if (IS_ERR(hdmi->clk_parent))
+               return PTR_ERR(hdmi->clk_parent);
+
+       err = clk_prepare(hdmi->clk_parent);
+       if (err < 0)
+               return err;
+
+       err = clk_set_parent(hdmi->clk, hdmi->clk_parent);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to setup clocks: %d\n", err);
+               return err;
+       }
+
+       hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
+       if (IS_ERR(hdmi->vdd)) {
+               dev_err(&pdev->dev, "failed to get VDD regulator\n");
+               return PTR_ERR(hdmi->vdd);
+       }
+
+       hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
+       if (IS_ERR(hdmi->pll)) {
+               dev_err(&pdev->dev, "failed to get PLL regulator\n");
+               return PTR_ERR(hdmi->pll);
+       }
+
+       hdmi->output.dev = &pdev->dev;
+
+       err = tegra_output_parse_dt(&hdmi->output);
+       if (err < 0)
+               return err;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!regs)
+               return -ENXIO;
+
+       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)
+               return err;
+
+       hdmi->irq = err;
+
+       INIT_LIST_HEAD(&hdmi->client.list);
+       hdmi->client.ops = &hdmi_client_ops;
+       hdmi->client.dev = &pdev->dev;
+
+       err = host1x_client_register(&hdmi->client);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to register host1x client: %d\n",
+                       err);
+               return err;
+       }
+
+       platform_set_drvdata(pdev, hdmi);
+
+       return 0;
+}
+
+static int tegra_hdmi_remove(struct platform_device *pdev)
+{
+       struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
+       int err;
+
+       err = host1x_client_unregister(&hdmi->client);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
+                       err);
+               return err;
+       }
+
+       clk_unprepare(hdmi->clk_parent);
+       clk_unprepare(hdmi->clk);
+
+       return 0;
+}
+
+static struct of_device_id tegra_hdmi_of_match[] = {
+       { .compatible = "nvidia,tegra30-hdmi", },
+       { .compatible = "nvidia,tegra20-hdmi", },
+       { },
+};
+
+struct platform_driver tegra_hdmi_driver = {
+       .driver = {
+               .name = "tegra-hdmi",
+               .owner = THIS_MODULE,
+               .of_match_table = tegra_hdmi_of_match,
+       },
+       .probe = tegra_hdmi_probe,
+       .remove = tegra_hdmi_remove,
+};
diff --git a/drivers/gpu/drm/tegra/hdmi.h b/drivers/gpu/drm/tegra/hdmi.h
new file mode 100644 (file)
index 0000000..52ac36e
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef TEGRA_HDMI_H
+#define TEGRA_HDMI_H 1
+
+/* register definitions */
+#define HDMI_CTXSW                                             0x00
+
+#define HDMI_NV_PDISP_SOR_STATE0                               0x01
+#define SOR_STATE_UPDATE (1 << 0)
+
+#define HDMI_NV_PDISP_SOR_STATE1                               0x02
+#define SOR_STATE_ASY_HEAD_OPMODE_AWAKE (2 << 0)
+#define SOR_STATE_ASY_ORMODE_NORMAL     (1 << 2)
+#define SOR_STATE_ATTACHED              (1 << 3)
+
+#define HDMI_NV_PDISP_SOR_STATE2                               0x03
+#define SOR_STATE_ASY_OWNER_NONE         (0 <<  0)
+#define SOR_STATE_ASY_OWNER_HEAD0        (1 <<  0)
+#define SOR_STATE_ASY_SUBOWNER_NONE      (0 <<  4)
+#define SOR_STATE_ASY_SUBOWNER_SUBHEAD0  (1 <<  4)
+#define SOR_STATE_ASY_SUBOWNER_SUBHEAD1  (2 <<  4)
+#define SOR_STATE_ASY_SUBOWNER_BOTH      (3 <<  4)
+#define SOR_STATE_ASY_CRCMODE_ACTIVE     (0 <<  6)
+#define SOR_STATE_ASY_CRCMODE_COMPLETE   (1 <<  6)
+#define SOR_STATE_ASY_CRCMODE_NON_ACTIVE (2 <<  6)
+#define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (1 << 8)
+#define SOR_STATE_ASY_PROTOCOL_CUSTOM        (15 << 8)
+#define SOR_STATE_ASY_HSYNCPOL_POS       (0 << 12)
+#define SOR_STATE_ASY_HSYNCPOL_NEG       (1 << 12)
+#define SOR_STATE_ASY_VSYNCPOL_POS       (0 << 13)
+#define SOR_STATE_ASY_VSYNCPOL_NEG       (1 << 13)
+#define SOR_STATE_ASY_DEPOL_POS          (0 << 14)
+#define SOR_STATE_ASY_DEPOL_NEG          (1 << 14)
+
+#define HDMI_NV_PDISP_RG_HDCP_AN_MSB                           0x04
+#define HDMI_NV_PDISP_RG_HDCP_AN_LSB                           0x05
+#define HDMI_NV_PDISP_RG_HDCP_CN_MSB                           0x06
+#define HDMI_NV_PDISP_RG_HDCP_CN_LSB                           0x07
+#define HDMI_NV_PDISP_RG_HDCP_AKSV_MSB                         0x08
+#define HDMI_NV_PDISP_RG_HDCP_AKSV_LSB                         0x09
+#define HDMI_NV_PDISP_RG_HDCP_BKSV_MSB                         0x0a
+#define HDMI_NV_PDISP_RG_HDCP_BKSV_LSB                         0x0b
+#define HDMI_NV_PDISP_RG_HDCP_CKSV_MSB                         0x0c
+#define HDMI_NV_PDISP_RG_HDCP_CKSV_LSB                         0x0d
+#define HDMI_NV_PDISP_RG_HDCP_DKSV_MSB                         0x0e
+#define HDMI_NV_PDISP_RG_HDCP_DKSV_LSB                         0x0f
+#define HDMI_NV_PDISP_RG_HDCP_CTRL                             0x10
+#define HDMI_NV_PDISP_RG_HDCP_CMODE                            0x11
+#define HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB                       0x12
+#define HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB                       0x13
+#define HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB                       0x14
+#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2                      0x15
+#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1                      0x16
+#define HDMI_NV_PDISP_RG_HDCP_RI                               0x17
+#define HDMI_NV_PDISP_RG_HDCP_CS_MSB                           0x18
+#define HDMI_NV_PDISP_RG_HDCP_CS_LSB                           0x19
+#define HDMI_NV_PDISP_HDMI_AUDIO_EMU0                          0x1a
+#define HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0                    0x1b
+#define HDMI_NV_PDISP_HDMI_AUDIO_EMU1                          0x1c
+#define HDMI_NV_PDISP_HDMI_AUDIO_EMU2                          0x1d
+
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL                        0x1e
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS              0x1f
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER              0x20
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW                0x21
+#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH       0x22
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL                  0x23
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS                        0x24
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER                        0x25
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW          0x26
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH         0x27
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW          0x28
+#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH         0x29
+
+#define INFOFRAME_CTRL_ENABLE (1 << 0)
+
+#define INFOFRAME_HEADER_TYPE(x)    (((x) & 0xff) <<  0)
+#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
+#define INFOFRAME_HEADER_LEN(x)     (((x) & 0x0f) << 16)
+
+#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL                                0x2a
+#define GENERIC_CTRL_ENABLE (1 <<  0)
+#define GENERIC_CTRL_OTHER  (1 <<  4)
+#define GENERIC_CTRL_SINGLE (1 <<  8)
+#define GENERIC_CTRL_HBLANK (1 << 12)
+#define GENERIC_CTRL_AUDIO  (1 << 16)
+
+#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS                      0x2b
+#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER                      0x2c
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW                        0x2d
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH               0x2e
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW                        0x2f
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH               0x30
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW                        0x31
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH               0x32
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW                        0x33
+#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH               0x34
+
+#define HDMI_NV_PDISP_HDMI_ACR_CTRL                            0x35
+#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW                        0x36
+#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH               0x37
+#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW                        0x38
+#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH               0x39
+#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW                        0x3a
+#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH               0x3b
+#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW                        0x3c
+#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH               0x3d
+#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW                        0x3e
+#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH               0x3f
+#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW                        0x40
+#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH               0x41
+#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW                        0x42
+#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH               0x43
+
+#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8)
+#define ACR_SUBPACK_N(x)   (((x) & 0xffffff) << 0)
+#define ACR_ENABLE         (1 << 31)
+
+#define HDMI_NV_PDISP_HDMI_CTRL                                        0x44
+#define HDMI_CTRL_REKEY(x)         (((x) & 0x7f) <<  0)
+#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16)
+#define HDMI_CTRL_ENABLE           (1 << 30)
+
+#define HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT                       0x45
+#define HDMI_NV_PDISP_HDMI_VSYNC_WINDOW                                0x46
+#define VSYNC_WINDOW_END(x)   (((x) & 0x3ff) <<  0)
+#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16)
+#define VSYNC_WINDOW_ENABLE   (1 << 31)
+
+#define HDMI_NV_PDISP_HDMI_GCP_CTRL                            0x47
+#define HDMI_NV_PDISP_HDMI_GCP_STATUS                          0x48
+#define HDMI_NV_PDISP_HDMI_GCP_SUBPACK                         0x49
+#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1                     0x4a
+#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2                     0x4b
+#define HDMI_NV_PDISP_HDMI_EMU0                                        0x4c
+#define HDMI_NV_PDISP_HDMI_EMU1                                        0x4d
+#define HDMI_NV_PDISP_HDMI_EMU1_RDATA                          0x4e
+
+#define HDMI_NV_PDISP_HDMI_SPARE                               0x4f
+#define SPARE_HW_CTS           (1 << 0)
+#define SPARE_FORCE_SW_CTS     (1 << 1)
+#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16)
+
+#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1                   0x50
+#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2                   0x51
+#define HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL                    0x53
+#define HDMI_NV_PDISP_SOR_CAP                                  0x54
+#define HDMI_NV_PDISP_SOR_PWR                                  0x55
+#define SOR_PWR_NORMAL_STATE_PD     (0 <<  0)
+#define SOR_PWR_NORMAL_STATE_PU     (1 <<  0)
+#define SOR_PWR_NORMAL_START_NORMAL (0 <<  1)
+#define SOR_PWR_NORMAL_START_ALT    (1 <<  1)
+#define SOR_PWR_SAFE_STATE_PD       (0 << 16)
+#define SOR_PWR_SAFE_STATE_PU       (1 << 16)
+#define SOR_PWR_SETTING_NEW_DONE    (0 << 31)
+#define SOR_PWR_SETTING_NEW_PENDING (1 << 31)
+#define SOR_PWR_SETTING_NEW_TRIGGER (1 << 31)
+
+#define HDMI_NV_PDISP_SOR_TEST                                 0x56
+#define HDMI_NV_PDISP_SOR_PLL0                                 0x57
+#define SOR_PLL_PWR            (1 << 0)
+#define SOR_PLL_PDBG           (1 << 1)
+#define SOR_PLL_VCAPD          (1 << 2)
+#define SOR_PLL_PDPORT         (1 << 3)
+#define SOR_PLL_RESISTORSEL    (1 << 4)
+#define SOR_PLL_PULLDOWN       (1 << 5)
+#define SOR_PLL_VCOCAP(x)      (((x) & 0xf) <<  8)
+#define SOR_PLL_BG_V17_S(x)    (((x) & 0xf) << 12)
+#define SOR_PLL_FILTER(x)      (((x) & 0xf) << 16)
+#define SOR_PLL_ICHPMP(x)      (((x) & 0xf) << 24)
+#define SOR_PLL_TX_REG_LOAD(x) (((x) & 0xf) << 28)
+
+#define HDMI_NV_PDISP_SOR_PLL1                                 0x58
+#define SOR_PLL_TMDS_TERM_ENABLE (1 << 8)
+#define SOR_PLL_TMDS_TERMADJ(x)  (((x) & 0xf) <<  9)
+#define SOR_PLL_LOADADJ(x)       (((x) & 0xf) << 20)
+#define SOR_PLL_PE_EN            (1 << 28)
+#define SOR_PLL_HALF_FULL_PE     (1 << 29)
+#define SOR_PLL_S_D_PIN_PE       (1 << 30)
+
+#define HDMI_NV_PDISP_SOR_PLL2                                 0x59
+
+#define HDMI_NV_PDISP_SOR_CSTM                                 0x5a
+#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24)
+
+#define HDMI_NV_PDISP_SOR_LVDS                                 0x5b
+#define HDMI_NV_PDISP_SOR_CRCA                                 0x5c
+#define HDMI_NV_PDISP_SOR_CRCB                                 0x5d
+#define HDMI_NV_PDISP_SOR_BLANK                                        0x5e
+#define HDMI_NV_PDISP_SOR_SEQ_CTL                              0x5f
+#define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) <<  0)
+#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) <<  4)
+#define SOR_SEQ_PD_PC(x)     (((x) & 0xf) <<  8)
+#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12)
+#define SOR_SEQ_PC(x)        (((x) & 0xf) << 16)
+#define SOR_SEQ_STATUS       (1 << 28)
+#define SOR_SEQ_SWITCH       (1 << 30)
+
+#define HDMI_NV_PDISP_SOR_SEQ_INST(x)                          (0x60 + (x))
+
+#define SOR_SEQ_INST_WAIT_TIME(x)     (((x) & 0x3ff) << 0)
+#define SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12)
+#define SOR_SEQ_INST_HALT             (1 << 15)
+#define SOR_SEQ_INST_PIN_A_LOW        (0 << 21)
+#define SOR_SEQ_INST_PIN_A_HIGH       (1 << 21)
+#define SOR_SEQ_INST_PIN_B_LOW        (0 << 22)
+#define SOR_SEQ_INST_PIN_B_HIGH       (1 << 22)
+#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23)
+
+#define HDMI_NV_PDISP_SOR_VCRCA0                               0x72
+#define HDMI_NV_PDISP_SOR_VCRCA1                               0x73
+#define HDMI_NV_PDISP_SOR_CCRCA0                               0x74
+#define HDMI_NV_PDISP_SOR_CCRCA1                               0x75
+#define HDMI_NV_PDISP_SOR_EDATAA0                              0x76
+#define HDMI_NV_PDISP_SOR_EDATAA1                              0x77
+#define HDMI_NV_PDISP_SOR_COUNTA0                              0x78
+#define HDMI_NV_PDISP_SOR_COUNTA1                              0x79
+#define HDMI_NV_PDISP_SOR_DEBUGA0                              0x7a
+#define HDMI_NV_PDISP_SOR_DEBUGA1                              0x7b
+#define HDMI_NV_PDISP_SOR_TRIG                                 0x7c
+#define HDMI_NV_PDISP_SOR_MSCHECK                              0x7d
+
+#define HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT                   0x7e
+#define DRIVE_CURRENT_LANE0(x)      (((x) & 0x3f) <<  0)
+#define DRIVE_CURRENT_LANE1(x)      (((x) & 0x3f) <<  8)
+#define DRIVE_CURRENT_LANE2(x)      (((x) & 0x3f) << 16)
+#define DRIVE_CURRENT_LANE3(x)      (((x) & 0x3f) << 24)
+#define DRIVE_CURRENT_FUSE_OVERRIDE (1 << 31)
+
+#define DRIVE_CURRENT_1_500_mA  0x00
+#define DRIVE_CURRENT_1_875_mA  0x01
+#define DRIVE_CURRENT_2_250_mA  0x02
+#define DRIVE_CURRENT_2_625_mA  0x03
+#define DRIVE_CURRENT_3_000_mA  0x04
+#define DRIVE_CURRENT_3_375_mA  0x05
+#define DRIVE_CURRENT_3_750_mA  0x06
+#define DRIVE_CURRENT_4_125_mA  0x07
+#define DRIVE_CURRENT_4_500_mA  0x08
+#define DRIVE_CURRENT_4_875_mA  0x09
+#define DRIVE_CURRENT_5_250_mA  0x0a
+#define DRIVE_CURRENT_5_625_mA  0x0b
+#define DRIVE_CURRENT_6_000_mA  0x0c
+#define DRIVE_CURRENT_6_375_mA  0x0d
+#define DRIVE_CURRENT_6_750_mA  0x0e
+#define DRIVE_CURRENT_7_125_mA  0x0f
+#define DRIVE_CURRENT_7_500_mA  0x10
+#define DRIVE_CURRENT_7_875_mA  0x11
+#define DRIVE_CURRENT_8_250_mA  0x12
+#define DRIVE_CURRENT_8_625_mA  0x13
+#define DRIVE_CURRENT_9_000_mA  0x14
+#define DRIVE_CURRENT_9_375_mA  0x15
+#define DRIVE_CURRENT_9_750_mA  0x16
+#define DRIVE_CURRENT_10_125_mA 0x17
+#define DRIVE_CURRENT_10_500_mA 0x18
+#define DRIVE_CURRENT_10_875_mA 0x19
+#define DRIVE_CURRENT_11_250_mA 0x1a
+#define DRIVE_CURRENT_11_625_mA 0x1b
+#define DRIVE_CURRENT_12_000_mA 0x1c
+#define DRIVE_CURRENT_12_375_mA 0x1d
+#define DRIVE_CURRENT_12_750_mA 0x1e
+#define DRIVE_CURRENT_13_125_mA 0x1f
+#define DRIVE_CURRENT_13_500_mA 0x20
+#define DRIVE_CURRENT_13_875_mA 0x21
+#define DRIVE_CURRENT_14_250_mA 0x22
+#define DRIVE_CURRENT_14_625_mA 0x23
+#define DRIVE_CURRENT_15_000_mA 0x24
+#define DRIVE_CURRENT_15_375_mA 0x25
+#define DRIVE_CURRENT_15_750_mA 0x26
+#define DRIVE_CURRENT_16_125_mA 0x27
+#define DRIVE_CURRENT_16_500_mA 0x28
+#define DRIVE_CURRENT_16_875_mA 0x29
+#define DRIVE_CURRENT_17_250_mA 0x2a
+#define DRIVE_CURRENT_17_625_mA 0x2b
+#define DRIVE_CURRENT_18_000_mA 0x2c
+#define DRIVE_CURRENT_18_375_mA 0x2d
+#define DRIVE_CURRENT_18_750_mA 0x2e
+#define DRIVE_CURRENT_19_125_mA 0x2f
+#define DRIVE_CURRENT_19_500_mA 0x30
+#define DRIVE_CURRENT_19_875_mA 0x31
+#define DRIVE_CURRENT_20_250_mA 0x32
+#define DRIVE_CURRENT_20_625_mA 0x33
+#define DRIVE_CURRENT_21_000_mA 0x34
+#define DRIVE_CURRENT_21_375_mA 0x35
+#define DRIVE_CURRENT_21_750_mA 0x36
+#define DRIVE_CURRENT_22_125_mA 0x37
+#define DRIVE_CURRENT_22_500_mA 0x38
+#define DRIVE_CURRENT_22_875_mA 0x39
+#define DRIVE_CURRENT_23_250_mA 0x3a
+#define DRIVE_CURRENT_23_625_mA 0x3b
+#define DRIVE_CURRENT_24_000_mA 0x3c
+#define DRIVE_CURRENT_24_375_mA 0x3d
+#define DRIVE_CURRENT_24_750_mA 0x3e
+
+#define HDMI_NV_PDISP_AUDIO_DEBUG0                             0x7f
+#define HDMI_NV_PDISP_AUDIO_DEBUG1                             0x80
+#define HDMI_NV_PDISP_AUDIO_DEBUG2                             0x81
+
+#define HDMI_NV_PDISP_AUDIO_FS(x)                              (0x82 + (x))
+#define AUDIO_FS_LOW(x)  (((x) & 0xfff) <<  0)
+#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16)
+
+#define HDMI_NV_PDISP_AUDIO_PULSE_WIDTH                                0x89
+#define HDMI_NV_PDISP_AUDIO_THRESHOLD                          0x8a
+#define HDMI_NV_PDISP_AUDIO_CNTRL0                             0x8b
+#define AUDIO_CNTRL0_ERROR_TOLERANCE(x)  (((x) & 0xff) << 0)
+#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO  (0 << 20)
+#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20)
+#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL  (2 << 20)
+#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24)
+
+#define HDMI_NV_PDISP_AUDIO_N                                  0x8c
+#define AUDIO_N_VALUE(x)           (((x) & 0xfffff) << 0)
+#define AUDIO_N_RESETF             (1 << 20)
+#define AUDIO_N_GENERATE_NORMAL    (0 << 24)
+#define AUDIO_N_GENERATE_ALTERNATE (1 << 24)
+
+#define HDMI_NV_PDISP_HDCPRIF_ROM_TIMING                       0x94
+#define HDMI_NV_PDISP_SOR_REFCLK                               0x95
+#define SOR_REFCLK_DIV_INT(x)  (((x) & 0xff) << 8)
+#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x03) << 6)
+
+#define HDMI_NV_PDISP_CRC_CONTROL                              0x96
+#define HDMI_NV_PDISP_INPUT_CONTROL                            0x97
+#define HDMI_SRC_DISPLAYA       (0 << 0)
+#define HDMI_SRC_DISPLAYB       (1 << 0)
+#define ARM_VIDEO_RANGE_FULL    (0 << 1)
+#define ARM_VIDEO_RANGE_LIMITED (1 << 1)
+
+#define HDMI_NV_PDISP_SCRATCH                                  0x98
+#define HDMI_NV_PDISP_PE_CURRENT                               0x99
+#define PE_CURRENT0(x) (((x) & 0xf) << 0)
+#define PE_CURRENT1(x) (((x) & 0xf) << 8)
+#define PE_CURRENT2(x) (((x) & 0xf) << 16)
+#define PE_CURRENT3(x) (((x) & 0xf) << 24)
+
+#define PE_CURRENT_0_0_mA 0x0
+#define PE_CURRENT_0_5_mA 0x1
+#define PE_CURRENT_1_0_mA 0x2
+#define PE_CURRENT_1_5_mA 0x3
+#define PE_CURRENT_2_0_mA 0x4
+#define PE_CURRENT_2_5_mA 0x5
+#define PE_CURRENT_3_0_mA 0x6
+#define PE_CURRENT_3_5_mA 0x7
+#define PE_CURRENT_4_0_mA 0x8
+#define PE_CURRENT_4_5_mA 0x9
+#define PE_CURRENT_5_0_mA 0xa
+#define PE_CURRENT_5_5_mA 0xb
+#define PE_CURRENT_6_0_mA 0xc
+#define PE_CURRENT_6_5_mA 0xd
+#define PE_CURRENT_7_0_mA 0xe
+#define PE_CURRENT_7_5_mA 0xf
+
+#define HDMI_NV_PDISP_KEY_CTRL                                 0x9a
+#define HDMI_NV_PDISP_KEY_DEBUG0                               0x9b
+#define HDMI_NV_PDISP_KEY_DEBUG1                               0x9c
+#define HDMI_NV_PDISP_KEY_DEBUG2                               0x9d
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_0                           0x9e
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_1                           0x9f
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_2                           0xa0
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_3                           0xa1
+#define HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG                                0xa2
+#define HDMI_NV_PDISP_KEY_SKEY_INDEX                           0xa3
+
+#define HDMI_NV_PDISP_SOR_AUDIO_CNTRL0                         0xac
+#define AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29)
+#define HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR                  0xbc
+#define HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE                   0xbd
+
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320    0xbf
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441    0xc0
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882    0xc1
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764    0xc2
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480    0xc3
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960    0xc4
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920    0xc5
+#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT 0xc5
+
+#endif /* TEGRA_HDMI_H */
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
new file mode 100644 (file)
index 0000000..8f40fa6
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/of_gpio.h>
+
+#include "drm.h"
+
+static int tegra_connector_get_modes(struct drm_connector *connector)
+{
+       struct tegra_output *output = connector_to_output(connector);
+       struct edid *edid = NULL;
+       int err = 0;
+
+       if (output->edid)
+               edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
+       else if (output->ddc)
+               edid = drm_get_edid(connector, output->ddc);
+
+       drm_mode_connector_update_edid_property(connector, edid);
+
+       if (edid) {
+               err = drm_add_edid_modes(connector, edid);
+               kfree(edid);
+       }
+
+       return err;
+}
+
+static int tegra_connector_mode_valid(struct drm_connector *connector,
+                                     struct drm_display_mode *mode)
+{
+       struct tegra_output *output = connector_to_output(connector);
+       enum drm_mode_status status = MODE_OK;
+       int err;
+
+       err = tegra_output_check_mode(output, mode, &status);
+       if (err < 0)
+               return MODE_ERROR;
+
+       return status;
+}
+
+static struct drm_encoder *
+tegra_connector_best_encoder(struct drm_connector *connector)
+{
+       struct tegra_output *output = connector_to_output(connector);
+
+       return &output->encoder;
+}
+
+static const struct drm_connector_helper_funcs connector_helper_funcs = {
+       .get_modes = tegra_connector_get_modes,
+       .mode_valid = tegra_connector_mode_valid,
+       .best_encoder = tegra_connector_best_encoder,
+};
+
+static enum drm_connector_status
+tegra_connector_detect(struct drm_connector *connector, bool force)
+{
+       struct tegra_output *output = connector_to_output(connector);
+       enum drm_connector_status status = connector_status_unknown;
+
+       if (gpio_is_valid(output->hpd_gpio)) {
+               if (gpio_get_value(output->hpd_gpio) == 0)
+                       status = connector_status_disconnected;
+               else
+                       status = connector_status_connected;
+       } else {
+               if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+                       status = connector_status_connected;
+       }
+
+       return status;
+}
+
+static void tegra_connector_destroy(struct drm_connector *connector)
+{
+       drm_sysfs_connector_remove(connector);
+       drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = tegra_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = tegra_connector_destroy,
+};
+
+static void tegra_encoder_destroy(struct drm_encoder *encoder)
+{
+       drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs encoder_funcs = {
+       .destroy = tegra_encoder_destroy,
+};
+
+static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+}
+
+static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
+                                    const struct drm_display_mode *mode,
+                                    struct drm_display_mode *adjusted)
+{
+       return true;
+}
+
+static void tegra_encoder_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void tegra_encoder_commit(struct drm_encoder *encoder)
+{
+}
+
+static void tegra_encoder_mode_set(struct drm_encoder *encoder,
+                                  struct drm_display_mode *mode,
+                                  struct drm_display_mode *adjusted)
+{
+       struct tegra_output *output = encoder_to_output(encoder);
+       int err;
+
+       err = tegra_output_enable(output);
+       if (err < 0)
+               dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err);
+}
+
+static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
+       .dpms = tegra_encoder_dpms,
+       .mode_fixup = tegra_encoder_mode_fixup,
+       .prepare = tegra_encoder_prepare,
+       .commit = tegra_encoder_commit,
+       .mode_set = tegra_encoder_mode_set,
+};
+
+static irqreturn_t hpd_irq(int irq, void *data)
+{
+       struct tegra_output *output = data;
+
+       drm_helper_hpd_irq_event(output->connector.dev);
+
+       return IRQ_HANDLED;
+}
+
+int tegra_output_parse_dt(struct tegra_output *output)
+{
+       enum of_gpio_flags flags;
+       struct device_node *ddc;
+       size_t size;
+       int err;
+
+       if (!output->of_node)
+               output->of_node = output->dev->of_node;
+
+       output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
+
+       ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
+       if (ddc) {
+               output->ddc = of_find_i2c_adapter_by_node(ddc);
+               if (!output->ddc) {
+                       err = -EPROBE_DEFER;
+                       of_node_put(ddc);
+                       return err;
+               }
+
+               of_node_put(ddc);
+       }
+
+       if (!output->edid && !output->ddc)
+               return -ENODEV;
+
+       output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
+                                                  "nvidia,hpd-gpio", 0,
+                                                  &flags);
+
+       return 0;
+}
+
+int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
+{
+       int connector, encoder, err;
+
+       if (gpio_is_valid(output->hpd_gpio)) {
+               unsigned long flags;
+
+               err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN,
+                                      "HDMI hotplug detect");
+               if (err < 0) {
+                       dev_err(output->dev, "gpio_request_one(): %d\n", err);
+                       return err;
+               }
+
+               err = gpio_to_irq(output->hpd_gpio);
+               if (err < 0) {
+                       dev_err(output->dev, "gpio_to_irq(): %d\n", err);
+                       goto free_hpd;
+               }
+
+               output->hpd_irq = err;
+
+               flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+                       IRQF_ONESHOT;
+
+               err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq,
+                                          flags, "hpd", output);
+               if (err < 0) {
+                       dev_err(output->dev, "failed to request IRQ#%u: %d\n",
+                               output->hpd_irq, err);
+                       goto free_hpd;
+               }
+
+               output->connector.polled = DRM_CONNECTOR_POLL_HPD;
+       }
+
+       switch (output->type) {
+       case TEGRA_OUTPUT_RGB:
+               connector = DRM_MODE_CONNECTOR_LVDS;
+               encoder = DRM_MODE_ENCODER_LVDS;
+               break;
+
+       case TEGRA_OUTPUT_HDMI:
+               connector = DRM_MODE_CONNECTOR_HDMIA;
+               encoder = DRM_MODE_ENCODER_TMDS;
+               break;
+
+       default:
+               connector = DRM_MODE_CONNECTOR_Unknown;
+               encoder = DRM_MODE_ENCODER_NONE;
+               break;
+       }
+
+       drm_connector_init(drm, &output->connector, &connector_funcs,
+                          connector);
+       drm_connector_helper_add(&output->connector, &connector_helper_funcs);
+
+       drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
+       drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
+
+       drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
+       drm_sysfs_connector_add(&output->connector);
+
+       output->encoder.possible_crtcs = 0x3;
+
+       return 0;
+
+free_hpd:
+       gpio_free(output->hpd_gpio);
+
+       return err;
+}
+
+int tegra_output_exit(struct tegra_output *output)
+{
+       if (gpio_is_valid(output->hpd_gpio)) {
+               free_irq(output->hpd_irq, output);
+               gpio_free(output->hpd_gpio);
+       }
+
+       if (output->ddc)
+               put_device(&output->ddc->dev);
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
new file mode 100644 (file)
index 0000000..e4d2841
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+
+#include "drm.h"
+#include "dc.h"
+
+struct tegra_rgb {
+       struct tegra_output output;
+       struct clk *clk_parent;
+       struct clk *clk;
+};
+
+static inline struct tegra_rgb *to_rgb(struct tegra_output *output)
+{
+       return container_of(output, struct tegra_rgb, output);
+}
+
+struct reg_entry {
+       unsigned long offset;
+       unsigned long value;
+};
+
+static const struct reg_entry rgb_enable[] = {
+       { DC_COM_PIN_OUTPUT_ENABLE(0),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_ENABLE(1),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_ENABLE(2),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_ENABLE(3),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
+       { DC_COM_PIN_OUTPUT_POLARITY(1), 0x01000000 },
+       { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
+       { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
+       { DC_COM_PIN_OUTPUT_DATA(0),     0x00000000 },
+       { DC_COM_PIN_OUTPUT_DATA(1),     0x00000000 },
+       { DC_COM_PIN_OUTPUT_DATA(2),     0x00000000 },
+       { DC_COM_PIN_OUTPUT_DATA(3),     0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(0),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(1),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(2),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(3),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(4),   0x00210222 },
+       { DC_COM_PIN_OUTPUT_SELECT(5),   0x00002200 },
+       { DC_COM_PIN_OUTPUT_SELECT(6),   0x00020000 },
+};
+
+static const struct reg_entry rgb_disable[] = {
+       { DC_COM_PIN_OUTPUT_SELECT(6),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(5),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(4),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(3),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(2),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(1),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_SELECT(0),   0x00000000 },
+       { DC_COM_PIN_OUTPUT_DATA(3),     0xaaaaaaaa },
+       { DC_COM_PIN_OUTPUT_DATA(2),     0xaaaaaaaa },
+       { DC_COM_PIN_OUTPUT_DATA(1),     0xaaaaaaaa },
+       { DC_COM_PIN_OUTPUT_DATA(0),     0xaaaaaaaa },
+       { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
+       { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
+       { DC_COM_PIN_OUTPUT_POLARITY(1), 0x00000000 },
+       { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
+       { DC_COM_PIN_OUTPUT_ENABLE(3),   0x55555555 },
+       { DC_COM_PIN_OUTPUT_ENABLE(2),   0x55555555 },
+       { DC_COM_PIN_OUTPUT_ENABLE(1),   0x55150005 },
+       { DC_COM_PIN_OUTPUT_ENABLE(0),   0x55555555 },
+};
+
+static void tegra_dc_write_regs(struct tegra_dc *dc,
+                               const struct reg_entry *table,
+                               unsigned int num)
+{
+       unsigned int i;
+
+       for (i = 0; i < num; i++)
+               tegra_dc_writel(dc, table[i].value, table[i].offset);
+}
+
+static int tegra_output_rgb_enable(struct tegra_output *output)
+{
+       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+
+       tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable));
+
+       return 0;
+}
+
+static int tegra_output_rgb_disable(struct tegra_output *output)
+{
+       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+
+       tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable));
+
+       return 0;
+}
+
+static int tegra_output_rgb_setup_clock(struct tegra_output *output,
+                                       struct clk *clk, unsigned long pclk)
+{
+       struct tegra_rgb *rgb = to_rgb(output);
+
+       return clk_set_parent(clk, rgb->clk_parent);
+}
+
+static int tegra_output_rgb_check_mode(struct tegra_output *output,
+                                      struct drm_display_mode *mode,
+                                      enum drm_mode_status *status)
+{
+       /*
+        * FIXME: For now, always assume that the mode is okay. There are
+        * unresolved issues with clk_round_rate(), which doesn't always
+        * reliably report whether a frequency can be set or not.
+        */
+
+       *status = MODE_OK;
+
+       return 0;
+}
+
+static const struct tegra_output_ops rgb_ops = {
+       .enable = tegra_output_rgb_enable,
+       .disable = tegra_output_rgb_disable,
+       .setup_clock = tegra_output_rgb_setup_clock,
+       .check_mode = tegra_output_rgb_check_mode,
+};
+
+int tegra_dc_rgb_probe(struct tegra_dc *dc)
+{
+       struct device_node *np;
+       struct tegra_rgb *rgb;
+       int err;
+
+       np = of_get_child_by_name(dc->dev->of_node, "rgb");
+       if (!np || !of_device_is_available(np))
+               return -ENODEV;
+
+       rgb = devm_kzalloc(dc->dev, sizeof(*rgb), GFP_KERNEL);
+       if (!rgb)
+               return -ENOMEM;
+
+       rgb->output.dev = dc->dev;
+       rgb->output.of_node = np;
+
+       err = tegra_output_parse_dt(&rgb->output);
+       if (err < 0)
+               return err;
+
+       rgb->clk = devm_clk_get(dc->dev, NULL);
+       if (IS_ERR(rgb->clk)) {
+               dev_err(dc->dev, "failed to get clock\n");
+               return PTR_ERR(rgb->clk);
+       }
+
+       rgb->clk_parent = devm_clk_get(dc->dev, "parent");
+       if (IS_ERR(rgb->clk_parent)) {
+               dev_err(dc->dev, "failed to get parent clock\n");
+               return PTR_ERR(rgb->clk_parent);
+       }
+
+       err = clk_set_parent(rgb->clk, rgb->clk_parent);
+       if (err < 0) {
+               dev_err(dc->dev, "failed to set parent clock: %d\n", err);
+               return err;
+       }
+
+       dc->rgb = &rgb->output;
+
+       return 0;
+}
+
+int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
+{
+       struct tegra_rgb *rgb = to_rgb(dc->rgb);
+       int err;
+
+       if (!dc->rgb)
+               return -ENODEV;
+
+       rgb->output.type = TEGRA_OUTPUT_RGB;
+       rgb->output.ops = &rgb_ops;
+
+       err = tegra_output_init(dc->base.dev, &rgb->output);
+       if (err < 0) {
+               dev_err(dc->dev, "output setup failed: %d\n", err);
+               return err;
+       }
+
+       /*
+        * By default, outputs can be associated with each display controller.
+        * RGB outputs are an exception, so we make sure they can be attached
+        * to only their parent display controller.
+        */
+       rgb->output.encoder.possible_crtcs = 1 << dc->pipe;
+
+       return 0;
+}
+
+int tegra_dc_rgb_exit(struct tegra_dc *dc)
+{
+       if (dc->rgb) {
+               int err;
+
+               err = tegra_output_disable(dc->rgb);
+               if (err < 0) {
+                       dev_err(dc->dev, "output failed to disable: %d\n", err);
+                       return err;
+               }
+
+               err = tegra_output_exit(dc->rgb);
+               if (err < 0) {
+                       dev_err(dc->dev, "output cleanup failed: %d\n", err);
+                       return err;
+               }
+
+               dc->rgb = NULL;
+       }
+
+       return 0;
+}
index ccfd42b236060ffa17329d95a114029ef1faa89c..7d6bed2225422fa2413130a606d2b20fd084cfd4 100644 (file)
@@ -19,6 +19,4 @@ config TEGRA_HOST1X_FIREWALL
 
          If unsure, choose Y.
 
-source "drivers/gpu/host1x/drm/Kconfig"
-
 endif
index 616fe82ce715f158584168f4abc1b925225549a6..889217cfb79dd1998a0609866e25283d85a0e760 100644 (file)
@@ -9,12 +9,4 @@ host1x-y = \
        debug.o \
        hw/host1x01.o
 
-ccflags-y += -Iinclude/drm
-ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG
-
-host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o
-host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
-host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o
-host1x-$(CONFIG_DRM_TEGRA) += drm/gr2d.o
-host1x-$(CONFIG_DRM_TEGRA) += drm/bus.o
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/drm/Kconfig b/drivers/gpu/host1x/drm/Kconfig
deleted file mode 100644 (file)
index 69853a4..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-config DRM_TEGRA
-       bool "NVIDIA Tegra DRM"
-       depends on DRM
-       select DRM_KMS_HELPER
-       select FB_SYS_FILLRECT
-       select FB_SYS_COPYAREA
-       select FB_SYS_IMAGEBLIT
-       help
-         Choose this option if you have an NVIDIA Tegra SoC.
-
-         To compile this driver as a module, choose M here: the module
-         will be called tegra-drm.
-
-if DRM_TEGRA
-
-config DRM_TEGRA_STAGING
-       bool "Enable HOST1X interface"
-       depends on STAGING
-       help
-         Say yes if HOST1X should be available for userspace DRM users.
-
-         If unsure, choose N.
-
-config DRM_TEGRA_DEBUG
-       bool "NVIDIA Tegra DRM debug support"
-       help
-         Say yes here to enable debugging support.
-
-endif
diff --git a/drivers/gpu/host1x/drm/bus.c b/drivers/gpu/host1x/drm/bus.c
deleted file mode 100644 (file)
index 565f8f7..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2013 NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "drm.h"
-
-static int drm_host1x_set_busid(struct drm_device *dev,
-                               struct drm_master *master)
-{
-       const char *device = dev_name(dev->dev);
-       const char *driver = dev->driver->name;
-       const char *bus = dev->dev->bus->name;
-       int length;
-
-       master->unique_len = strlen(bus) + 1 + strlen(device);
-       master->unique_size = master->unique_len;
-
-       master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
-       if (!master->unique)
-               return -ENOMEM;
-
-       snprintf(master->unique, master->unique_len + 1, "%s:%s", bus, device);
-
-       length = strlen(driver) + 1 + master->unique_len;
-
-       dev->devname = kmalloc(length + 1, GFP_KERNEL);
-       if (!dev->devname)
-               return -ENOMEM;
-
-       snprintf(dev->devname, length + 1, "%s@%s", driver, master->unique);
-
-       return 0;
-}
-
-static struct drm_bus drm_host1x_bus = {
-       .bus_type = DRIVER_BUS_HOST1X,
-       .set_busid = drm_host1x_set_busid,
-};
-
-int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
-{
-       struct drm_device *drm;
-       int ret;
-
-       INIT_LIST_HEAD(&driver->device_list);
-       driver->bus = &drm_host1x_bus;
-
-       drm = drm_dev_alloc(driver, &device->dev);
-       if (!drm)
-               return -ENOMEM;
-
-       ret = drm_dev_register(drm, 0);
-       if (ret)
-               goto err_free;
-
-       DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name,
-                driver->major, driver->minor, driver->patchlevel,
-                driver->date, drm->primary->index);
-
-       return 0;
-
-err_free:
-       drm_dev_free(drm);
-       return ret;
-}
-
-void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device)
-{
-       struct tegra_drm *tegra = dev_get_drvdata(&device->dev);
-
-       drm_put_dev(tegra->drm);
-}
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c
deleted file mode 100644 (file)
index 588d4ba..0000000
+++ /dev/null
@@ -1,1194 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/clk/tegra.h>
-#include <linux/debugfs.h>
-
-#include "dc.h"
-#include "drm.h"
-#include "gem.h"
-
-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 tegra_bo *bo = tegra_fb_get_plane(fb, i);
-
-               window.base[i] = bo->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;
-
-       if (!plane->crtc)
-               return 0;
-
-       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_XBGR8888,
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_RGB565,
-       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)
-{
-       unsigned int format = tegra_dc_format(fb->pixel_format);
-       struct tegra_bo *bo = tegra_fb_get_plane(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, bo->paddr + value, DC_WINBUF_START_ADDR);
-       tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
-       tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
-
-       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;
-       unsigned long flags, base;
-       struct tegra_bo *bo;
-
-       if (!dc->event)
-               return;
-
-       bo = tegra_fb_get_plane(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 == bo->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, uint32_t page_flip_flags)
-{
-       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_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,
-                                 const struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted)
-{
-       return true;
-}
-
-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;
-
-       if (v)
-               max = 15;
-       else {
-               switch (bpp) {
-               case 2:
-                       max = 8;
-                       break;
-
-               default:
-                       WARN_ON_ONCE(1);
-                       /* fallthrough */
-               case 4:
-                       max = 4;
-                       break;
-               }
-       }
-
-       outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
-       inf.full -= dfixed_const(1);
-
-       dda_inc = dfixed_div(inf, outf);
-       dda_inc = min_t(u32, dda_inc, dfixed_const(max));
-
-       return dda_inc;
-}
-
-static inline u32 compute_initial_dda(unsigned int in)
-{
-       fixed20_12 inf = dfixed_init(in);
-       return dfixed_frac(inf);
-}
-
-static int tegra_dc_set_timings(struct tegra_dc *dc,
-                               struct drm_display_mode *mode)
-{
-       /* TODO: For HDMI compliance, h & v ref_to_sync should be set to 1 */
-       unsigned int h_ref_to_sync = 0;
-       unsigned int v_ref_to_sync = 0;
-       unsigned long value;
-
-       tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
-
-       value = (v_ref_to_sync << 16) | h_ref_to_sync;
-       tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
-
-       value = ((mode->vsync_end - mode->vsync_start) << 16) |
-               ((mode->hsync_end - mode->hsync_start) <<  0);
-       tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
-
-       value = ((mode->vtotal - mode->vsync_end) << 16) |
-               ((mode->htotal - mode->hsync_end) <<  0);
-       tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
-
-       value = ((mode->vsync_start - mode->vdisplay) << 16) |
-               ((mode->hsync_start - mode->hdisplay) <<  0);
-       tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
-
-       value = (mode->vdisplay << 16) | mode->hdisplay;
-       tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
-
-       return 0;
-}
-
-static int tegra_crtc_setup_clk(struct drm_crtc *crtc,
-                               struct drm_display_mode *mode,
-                               unsigned long *div)
-{
-       unsigned long pclk = mode->clock * 1000, rate;
-       struct tegra_dc *dc = to_tegra_dc(crtc);
-       struct tegra_output *output = NULL;
-       struct drm_encoder *encoder;
-       long err;
-
-       list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, head)
-               if (encoder->crtc == crtc) {
-                       output = encoder_to_output(encoder);
-                       break;
-               }
-
-       if (!output)
-               return -ENODEV;
-
-       /*
-        * This assumes that the display controller will divide its parent
-        * clock by 2 to generate the pixel clock.
-        */
-       err = tegra_output_setup_clock(output, dc->clk, pclk * 2);
-       if (err < 0) {
-               dev_err(dc->dev, "failed to setup clock: %ld\n", err);
-               return err;
-       }
-
-       rate = clk_get_rate(dc->clk);
-       *div = (rate * 2 / pclk) - 2;
-
-       DRM_DEBUG_KMS("rate: %lu, div: %lu\n", rate, *div);
-
-       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_XBGR8888:
-               return WIN_COLOR_DEPTH_R8G8B8A8;
-
-       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_bo *bo = tegra_fb_get_plane(crtc->fb, 0);
-       struct tegra_dc *dc = to_tegra_dc(crtc);
-       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);
-               return err;
-       }
-
-       /* program display mode */
-       tegra_dc_set_timings(dc, mode);
-
-       value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
-       tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
-
-       value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1));
-       value &= ~LVS_OUTPUT_POLARITY_LOW;
-       value &= ~LHS_OUTPUT_POLARITY_LOW;
-       tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1));
-
-       value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB |
-               DISP_ORDER_RED_BLUE;
-       tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL);
-
-       tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS);
-
-       value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
-       tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
-
-       /* setup window parameters */
-       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] = bo->paddr;
-
-       err = tegra_dc_setup_window(dc, 0, &window);
-       if (err < 0)
-               dev_err(dc->dev, "failed to enable root plane\n");
-
-       return 0;
-}
-
-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 tegra_dc_set_base(dc, x, y, crtc->fb);
-}
-
-static void tegra_crtc_prepare(struct drm_crtc *crtc)
-{
-       struct tegra_dc *dc = to_tegra_dc(crtc);
-       unsigned int syncpt;
-       unsigned long value;
-
-       /* hardware initialization */
-       tegra_periph_reset_deassert(dc->clk);
-       usleep_range(10000, 20000);
-
-       if (dc->pipe)
-               syncpt = SYNCPT_VBLANK1;
-       else
-               syncpt = SYNCPT_VBLANK0;
-
-       /* initialize display controller */
-       tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
-       tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
-
-       value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
-       tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
-
-       value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
-               WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
-       tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
-
-       value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
-               PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
-       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
-
-       value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
-       value |= DISP_CTRL_MODE_C_DISPLAY;
-       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
-
-       /* initialize timer */
-       value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
-               WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
-       tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
-
-       value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
-               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_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 value;
-
-       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);
-
-       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 = {
-       .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_dc_irq(int irq, void *data)
-{
-       struct tegra_dc *dc = data;
-       unsigned long status;
-
-       status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
-       tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
-
-       if (status & FRAME_END_INT) {
-               /*
-               dev_dbg(dc->dev, "%s(): frame end\n", __func__);
-               */
-       }
-
-       if (status & VBLANK_INT) {
-               /*
-               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)) {
-               /*
-               dev_dbg(dc->dev, "%s(): underflow\n", __func__);
-               */
-       }
-
-       return IRQ_HANDLED;
-}
-
-static int tegra_dc_show_regs(struct seq_file *s, void *data)
-{
-       struct drm_info_node *node = s->private;
-       struct tegra_dc *dc = node->info_ent->data;
-
-#define DUMP_REG(name)                                         \
-       seq_printf(s, "%-40s %#05x %08lx\n", #name, name,       \
-                  tegra_dc_readl(dc, name))
-
-       DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT);
-       DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
-       DUMP_REG(DC_CMD_GENERAL_INCR_SYNCPT_ERROR);
-       DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT);
-       DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL);
-       DUMP_REG(DC_CMD_WIN_A_INCR_SYNCPT_ERROR);
-       DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT);
-       DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL);
-       DUMP_REG(DC_CMD_WIN_B_INCR_SYNCPT_ERROR);
-       DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT);
-       DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL);
-       DUMP_REG(DC_CMD_WIN_C_INCR_SYNCPT_ERROR);
-       DUMP_REG(DC_CMD_CONT_SYNCPT_VSYNC);
-       DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
-       DUMP_REG(DC_CMD_DISPLAY_COMMAND);
-       DUMP_REG(DC_CMD_SIGNAL_RAISE);
-       DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL);
-       DUMP_REG(DC_CMD_INT_STATUS);
-       DUMP_REG(DC_CMD_INT_MASK);
-       DUMP_REG(DC_CMD_INT_ENABLE);
-       DUMP_REG(DC_CMD_INT_TYPE);
-       DUMP_REG(DC_CMD_INT_POLARITY);
-       DUMP_REG(DC_CMD_SIGNAL_RAISE1);
-       DUMP_REG(DC_CMD_SIGNAL_RAISE2);
-       DUMP_REG(DC_CMD_SIGNAL_RAISE3);
-       DUMP_REG(DC_CMD_STATE_ACCESS);
-       DUMP_REG(DC_CMD_STATE_CONTROL);
-       DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
-       DUMP_REG(DC_CMD_REG_ACT_CONTROL);
-       DUMP_REG(DC_COM_CRC_CONTROL);
-       DUMP_REG(DC_COM_CRC_CHECKSUM);
-       DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(0));
-       DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(1));
-       DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(2));
-       DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE(3));
-       DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(0));
-       DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(1));
-       DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(2));
-       DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY(3));
-       DUMP_REG(DC_COM_PIN_OUTPUT_DATA(0));
-       DUMP_REG(DC_COM_PIN_OUTPUT_DATA(1));
-       DUMP_REG(DC_COM_PIN_OUTPUT_DATA(2));
-       DUMP_REG(DC_COM_PIN_OUTPUT_DATA(3));
-       DUMP_REG(DC_COM_PIN_INPUT_ENABLE(0));
-       DUMP_REG(DC_COM_PIN_INPUT_ENABLE(1));
-       DUMP_REG(DC_COM_PIN_INPUT_ENABLE(2));
-       DUMP_REG(DC_COM_PIN_INPUT_ENABLE(3));
-       DUMP_REG(DC_COM_PIN_INPUT_DATA(0));
-       DUMP_REG(DC_COM_PIN_INPUT_DATA(1));
-       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(0));
-       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(1));
-       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(2));
-       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(3));
-       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(4));
-       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(5));
-       DUMP_REG(DC_COM_PIN_OUTPUT_SELECT(6));
-       DUMP_REG(DC_COM_PIN_MISC_CONTROL);
-       DUMP_REG(DC_COM_PIN_PM0_CONTROL);
-       DUMP_REG(DC_COM_PIN_PM0_DUTY_CYCLE);
-       DUMP_REG(DC_COM_PIN_PM1_CONTROL);
-       DUMP_REG(DC_COM_PIN_PM1_DUTY_CYCLE);
-       DUMP_REG(DC_COM_SPI_CONTROL);
-       DUMP_REG(DC_COM_SPI_START_BYTE);
-       DUMP_REG(DC_COM_HSPI_WRITE_DATA_AB);
-       DUMP_REG(DC_COM_HSPI_WRITE_DATA_CD);
-       DUMP_REG(DC_COM_HSPI_CS_DC);
-       DUMP_REG(DC_COM_SCRATCH_REGISTER_A);
-       DUMP_REG(DC_COM_SCRATCH_REGISTER_B);
-       DUMP_REG(DC_COM_GPIO_CTRL);
-       DUMP_REG(DC_COM_GPIO_DEBOUNCE_COUNTER);
-       DUMP_REG(DC_COM_CRC_CHECKSUM_LATCHED);
-       DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
-       DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
-       DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
-       DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY);
-       DUMP_REG(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
-       DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
-       DUMP_REG(DC_DISP_REF_TO_SYNC);
-       DUMP_REG(DC_DISP_SYNC_WIDTH);
-       DUMP_REG(DC_DISP_BACK_PORCH);
-       DUMP_REG(DC_DISP_ACTIVE);
-       DUMP_REG(DC_DISP_FRONT_PORCH);
-       DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
-       DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
-       DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
-       DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
-       DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
-       DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
-       DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
-       DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
-       DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
-       DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
-       DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
-       DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
-       DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
-       DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
-       DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
-       DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
-       DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
-       DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
-       DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
-       DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
-       DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
-       DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
-       DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
-       DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
-       DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
-       DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
-       DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
-       DUMP_REG(DC_DISP_M0_CONTROL);
-       DUMP_REG(DC_DISP_M1_CONTROL);
-       DUMP_REG(DC_DISP_DI_CONTROL);
-       DUMP_REG(DC_DISP_PP_CONTROL);
-       DUMP_REG(DC_DISP_PP_SELECT_A);
-       DUMP_REG(DC_DISP_PP_SELECT_B);
-       DUMP_REG(DC_DISP_PP_SELECT_C);
-       DUMP_REG(DC_DISP_PP_SELECT_D);
-       DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
-       DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
-       DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
-       DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
-       DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
-       DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
-       DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
-       DUMP_REG(DC_DISP_BORDER_COLOR);
-       DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
-       DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
-       DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
-       DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
-       DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
-       DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
-       DUMP_REG(DC_DISP_CURSOR_START_ADDR);
-       DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
-       DUMP_REG(DC_DISP_CURSOR_POSITION);
-       DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
-       DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
-       DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
-       DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
-       DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
-       DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
-       DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
-       DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
-       DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
-       DUMP_REG(DC_DISP_MCCIF_DISPLAY1A_HYST);
-       DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
-       DUMP_REG(DC_DISP_DAC_CRT_CTRL);
-       DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
-       DUMP_REG(DC_DISP_SD_CONTROL);
-       DUMP_REG(DC_DISP_SD_CSC_COEFF);
-       DUMP_REG(DC_DISP_SD_LUT(0));
-       DUMP_REG(DC_DISP_SD_LUT(1));
-       DUMP_REG(DC_DISP_SD_LUT(2));
-       DUMP_REG(DC_DISP_SD_LUT(3));
-       DUMP_REG(DC_DISP_SD_LUT(4));
-       DUMP_REG(DC_DISP_SD_LUT(5));
-       DUMP_REG(DC_DISP_SD_LUT(6));
-       DUMP_REG(DC_DISP_SD_LUT(7));
-       DUMP_REG(DC_DISP_SD_LUT(8));
-       DUMP_REG(DC_DISP_SD_FLICKER_CONTROL);
-       DUMP_REG(DC_DISP_DC_PIXEL_COUNT);
-       DUMP_REG(DC_DISP_SD_HISTOGRAM(0));
-       DUMP_REG(DC_DISP_SD_HISTOGRAM(1));
-       DUMP_REG(DC_DISP_SD_HISTOGRAM(2));
-       DUMP_REG(DC_DISP_SD_HISTOGRAM(3));
-       DUMP_REG(DC_DISP_SD_HISTOGRAM(4));
-       DUMP_REG(DC_DISP_SD_HISTOGRAM(5));
-       DUMP_REG(DC_DISP_SD_HISTOGRAM(6));
-       DUMP_REG(DC_DISP_SD_HISTOGRAM(7));
-       DUMP_REG(DC_DISP_SD_BL_TF(0));
-       DUMP_REG(DC_DISP_SD_BL_TF(1));
-       DUMP_REG(DC_DISP_SD_BL_TF(2));
-       DUMP_REG(DC_DISP_SD_BL_TF(3));
-       DUMP_REG(DC_DISP_SD_BL_CONTROL);
-       DUMP_REG(DC_DISP_SD_HW_K_VALUES);
-       DUMP_REG(DC_DISP_SD_MAN_K_VALUES);
-       DUMP_REG(DC_WIN_WIN_OPTIONS);
-       DUMP_REG(DC_WIN_BYTE_SWAP);
-       DUMP_REG(DC_WIN_BUFFER_CONTROL);
-       DUMP_REG(DC_WIN_COLOR_DEPTH);
-       DUMP_REG(DC_WIN_POSITION);
-       DUMP_REG(DC_WIN_SIZE);
-       DUMP_REG(DC_WIN_PRESCALED_SIZE);
-       DUMP_REG(DC_WIN_H_INITIAL_DDA);
-       DUMP_REG(DC_WIN_V_INITIAL_DDA);
-       DUMP_REG(DC_WIN_DDA_INC);
-       DUMP_REG(DC_WIN_LINE_STRIDE);
-       DUMP_REG(DC_WIN_BUF_STRIDE);
-       DUMP_REG(DC_WIN_UV_BUF_STRIDE);
-       DUMP_REG(DC_WIN_BUFFER_ADDR_MODE);
-       DUMP_REG(DC_WIN_DV_CONTROL);
-       DUMP_REG(DC_WIN_BLEND_NOKEY);
-       DUMP_REG(DC_WIN_BLEND_1WIN);
-       DUMP_REG(DC_WIN_BLEND_2WIN_X);
-       DUMP_REG(DC_WIN_BLEND_2WIN_Y);
-       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);
-       DUMP_REG(DC_WINBUF_START_ADDR_U);
-       DUMP_REG(DC_WINBUF_START_ADDR_U_NS);
-       DUMP_REG(DC_WINBUF_START_ADDR_V);
-       DUMP_REG(DC_WINBUF_START_ADDR_V_NS);
-       DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
-       DUMP_REG(DC_WINBUF_ADDR_H_OFFSET_NS);
-       DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
-       DUMP_REG(DC_WINBUF_ADDR_V_OFFSET_NS);
-       DUMP_REG(DC_WINBUF_UFLOW_STATUS);
-       DUMP_REG(DC_WINBUF_AD_UFLOW_STATUS);
-       DUMP_REG(DC_WINBUF_BD_UFLOW_STATUS);
-       DUMP_REG(DC_WINBUF_CD_UFLOW_STATUS);
-
-#undef DUMP_REG
-
-       return 0;
-}
-
-static struct drm_info_list debugfs_files[] = {
-       { "regs", tegra_dc_show_regs, 0, NULL },
-};
-
-static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
-{
-       unsigned int i;
-       char *name;
-       int err;
-
-       name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe);
-       dc->debugfs = debugfs_create_dir(name, minor->debugfs_root);
-       kfree(name);
-
-       if (!dc->debugfs)
-               return -ENOMEM;
-
-       dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
-                                   GFP_KERNEL);
-       if (!dc->debugfs_files) {
-               err = -ENOMEM;
-               goto remove;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
-               dc->debugfs_files[i].data = dc;
-
-       err = drm_debugfs_create_files(dc->debugfs_files,
-                                      ARRAY_SIZE(debugfs_files),
-                                      dc->debugfs, minor);
-       if (err < 0)
-               goto free;
-
-       dc->minor = minor;
-
-       return 0;
-
-free:
-       kfree(dc->debugfs_files);
-       dc->debugfs_files = NULL;
-remove:
-       debugfs_remove(dc->debugfs);
-       dc->debugfs = NULL;
-
-       return err;
-}
-
-static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
-{
-       drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files),
-                                dc->minor);
-       dc->minor = NULL;
-
-       kfree(dc->debugfs_files);
-       dc->debugfs_files = NULL;
-
-       debugfs_remove(dc->debugfs);
-       dc->debugfs = NULL;
-
-       return 0;
-}
-
-static int tegra_dc_init(struct host1x_client *client)
-{
-       struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-       struct tegra_dc *dc = host1x_client_to_dc(client);
-       int err;
-
-       dc->pipe = tegra->drm->mode_config.num_crtc;
-
-       drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
-       drm_mode_crtc_set_gamma_size(&dc->base, 256);
-       drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
-
-       err = tegra_dc_rgb_init(tegra->drm, dc);
-       if (err < 0 && err != -ENODEV) {
-               dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
-               return err;
-       }
-
-       err = tegra_dc_add_planes(tegra->drm, dc);
-       if (err < 0)
-               return err;
-
-       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-               err = tegra_dc_debugfs_init(dc, tegra->drm->primary);
-               if (err < 0)
-                       dev_err(dc->dev, "debugfs setup failed: %d\n", err);
-       }
-
-       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,
-                       err);
-               return err;
-       }
-
-       return 0;
-}
-
-static int tegra_dc_exit(struct host1x_client *client)
-{
-       struct tegra_dc *dc = host1x_client_to_dc(client);
-       int err;
-
-       devm_free_irq(dc->dev, dc->irq, dc);
-
-       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-               err = tegra_dc_debugfs_exit(dc);
-               if (err < 0)
-                       dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
-       }
-
-       err = tegra_dc_rgb_exit(dc);
-       if (err) {
-               dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
-               return err;
-       }
-
-       return 0;
-}
-
-static const struct host1x_client_ops dc_client_ops = {
-       .init = tegra_dc_init,
-       .exit = tegra_dc_exit,
-};
-
-static int tegra_dc_probe(struct platform_device *pdev)
-{
-       struct resource *regs;
-       struct tegra_dc *dc;
-       int err;
-
-       dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
-       if (!dc)
-               return -ENOMEM;
-
-       spin_lock_init(&dc->lock);
-       INIT_LIST_HEAD(&dc->list);
-       dc->dev = &pdev->dev;
-
-       dc->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(dc->clk)) {
-               dev_err(&pdev->dev, "failed to get clock\n");
-               return PTR_ERR(dc->clk);
-       }
-
-       err = clk_prepare_enable(dc->clk);
-       if (err < 0)
-               return err;
-
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       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) {
-               dev_err(&pdev->dev, "failed to get IRQ\n");
-               return -ENXIO;
-       }
-
-       INIT_LIST_HEAD(&dc->client.list);
-       dc->client.ops = &dc_client_ops;
-       dc->client.dev = &pdev->dev;
-
-       err = tegra_dc_rgb_probe(dc);
-       if (err < 0 && err != -ENODEV) {
-               dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
-               return err;
-       }
-
-       err = host1x_client_register(&dc->client);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to register host1x client: %d\n",
-                       err);
-               return err;
-       }
-
-       platform_set_drvdata(pdev, dc);
-
-       return 0;
-}
-
-static int tegra_dc_remove(struct platform_device *pdev)
-{
-       struct tegra_dc *dc = platform_get_drvdata(pdev);
-       int err;
-
-       err = host1x_client_unregister(&dc->client);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
-                       err);
-               return err;
-       }
-
-       clk_disable_unprepare(dc->clk);
-
-       return 0;
-}
-
-static struct of_device_id tegra_dc_of_match[] = {
-       { .compatible = "nvidia,tegra30-dc", },
-       { .compatible = "nvidia,tegra20-dc", },
-       { },
-};
-
-struct platform_driver tegra_dc_driver = {
-       .driver = {
-               .name = "tegra-dc",
-               .owner = THIS_MODULE,
-               .of_match_table = tegra_dc_of_match,
-       },
-       .probe = tegra_dc_probe,
-       .remove = tegra_dc_remove,
-};
diff --git a/drivers/gpu/host1x/drm/dc.h b/drivers/gpu/host1x/drm/dc.h
deleted file mode 100644 (file)
index 79eaec9..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef TEGRA_DC_H
-#define TEGRA_DC_H 1
-
-#define DC_CMD_GENERAL_INCR_SYNCPT             0x000
-#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL       0x001
-#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR       0x002
-#define DC_CMD_WIN_A_INCR_SYNCPT               0x008
-#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL         0x009
-#define DC_CMD_WIN_A_INCR_SYNCPT_ERROR         0x00a
-#define DC_CMD_WIN_B_INCR_SYNCPT               0x010
-#define DC_CMD_WIN_B_INCR_SYNCPT_CNTRL         0x011
-#define DC_CMD_WIN_B_INCR_SYNCPT_ERROR         0x012
-#define DC_CMD_WIN_C_INCR_SYNCPT               0x018
-#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL         0x019
-#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR         0x01a
-#define DC_CMD_CONT_SYNCPT_VSYNC               0x028
-#define DC_CMD_DISPLAY_COMMAND_OPTION0         0x031
-#define DC_CMD_DISPLAY_COMMAND                 0x032
-#define DISP_CTRL_MODE_STOP (0 << 5)
-#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
-#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
-#define DC_CMD_SIGNAL_RAISE                    0x033
-#define DC_CMD_DISPLAY_POWER_CONTROL           0x036
-#define PW0_ENABLE (1 <<  0)
-#define PW1_ENABLE (1 <<  2)
-#define PW2_ENABLE (1 <<  4)
-#define PW3_ENABLE (1 <<  6)
-#define PW4_ENABLE (1 <<  8)
-#define PM0_ENABLE (1 << 16)
-#define PM1_ENABLE (1 << 18)
-
-#define DC_CMD_INT_STATUS                      0x037
-#define DC_CMD_INT_MASK                                0x038
-#define DC_CMD_INT_ENABLE                      0x039
-#define DC_CMD_INT_TYPE                                0x03a
-#define DC_CMD_INT_POLARITY                    0x03b
-#define CTXSW_INT     (1 << 0)
-#define FRAME_END_INT (1 << 1)
-#define VBLANK_INT    (1 << 2)
-#define WIN_A_UF_INT  (1 << 8)
-#define WIN_B_UF_INT  (1 << 9)
-#define WIN_C_UF_INT  (1 << 10)
-#define WIN_A_OF_INT  (1 << 14)
-#define WIN_B_OF_INT  (1 << 15)
-#define WIN_C_OF_INT  (1 << 16)
-
-#define DC_CMD_SIGNAL_RAISE1                   0x03c
-#define DC_CMD_SIGNAL_RAISE2                   0x03d
-#define DC_CMD_SIGNAL_RAISE3                   0x03e
-
-#define DC_CMD_STATE_ACCESS                    0x040
-#define READ_MUX  (1 << 0)
-#define WRITE_MUX (1 << 2)
-
-#define DC_CMD_STATE_CONTROL                   0x041
-#define GENERAL_ACT_REQ (1 <<  0)
-#define WIN_A_ACT_REQ   (1 <<  1)
-#define WIN_B_ACT_REQ   (1 <<  2)
-#define WIN_C_ACT_REQ   (1 <<  3)
-#define GENERAL_UPDATE  (1 <<  8)
-#define WIN_A_UPDATE    (1 <<  9)
-#define WIN_B_UPDATE    (1 << 10)
-#define WIN_C_UPDATE    (1 << 11)
-#define NC_HOST_TRIG    (1 << 24)
-
-#define DC_CMD_DISPLAY_WINDOW_HEADER           0x042
-#define WINDOW_A_SELECT (1 << 4)
-#define WINDOW_B_SELECT (1 << 5)
-#define WINDOW_C_SELECT (1 << 6)
-
-#define DC_CMD_REG_ACT_CONTROL                 0x043
-
-#define DC_COM_CRC_CONTROL                     0x300
-#define DC_COM_CRC_CHECKSUM                    0x301
-#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x))
-#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x))
-#define LVS_OUTPUT_POLARITY_LOW (1 << 28)
-#define LHS_OUTPUT_POLARITY_LOW (1 << 30)
-#define DC_COM_PIN_OUTPUT_DATA(x) (0x30a + (x))
-#define DC_COM_PIN_INPUT_ENABLE(x) (0x30e + (x))
-#define DC_COM_PIN_INPUT_DATA(x) (0x312 + (x))
-#define DC_COM_PIN_OUTPUT_SELECT(x) (0x314 + (x))
-
-#define DC_COM_PIN_MISC_CONTROL                        0x31b
-#define DC_COM_PIN_PM0_CONTROL                 0x31c
-#define DC_COM_PIN_PM0_DUTY_CYCLE              0x31d
-#define DC_COM_PIN_PM1_CONTROL                 0x31e
-#define DC_COM_PIN_PM1_DUTY_CYCLE              0x31f
-
-#define DC_COM_SPI_CONTROL                     0x320
-#define DC_COM_SPI_START_BYTE                  0x321
-#define DC_COM_HSPI_WRITE_DATA_AB              0x322
-#define DC_COM_HSPI_WRITE_DATA_CD              0x323
-#define DC_COM_HSPI_CS_DC                      0x324
-#define DC_COM_SCRATCH_REGISTER_A              0x325
-#define DC_COM_SCRATCH_REGISTER_B              0x326
-#define DC_COM_GPIO_CTRL                       0x327
-#define DC_COM_GPIO_DEBOUNCE_COUNTER           0x328
-#define DC_COM_CRC_CHECKSUM_LATCHED            0x329
-
-#define DC_DISP_DISP_SIGNAL_OPTIONS0           0x400
-#define H_PULSE_0_ENABLE (1 <<  8)
-#define H_PULSE_1_ENABLE (1 << 10)
-#define H_PULSE_2_ENABLE (1 << 12)
-
-#define DC_DISP_DISP_SIGNAL_OPTIONS1           0x401
-
-#define DC_DISP_DISP_WIN_OPTIONS               0x402
-#define HDMI_ENABLE (1 << 30)
-
-#define DC_DISP_DISP_MEM_HIGH_PRIORITY         0x403
-#define CURSOR_THRESHOLD(x)   (((x) & 0x03) << 24)
-#define WINDOW_A_THRESHOLD(x) (((x) & 0x7f) << 16)
-#define WINDOW_B_THRESHOLD(x) (((x) & 0x7f) <<  8)
-#define WINDOW_C_THRESHOLD(x) (((x) & 0xff) <<  0)
-
-#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER   0x404
-#define CURSOR_DELAY(x)   (((x) & 0x3f) << 24)
-#define WINDOW_A_DELAY(x) (((x) & 0x3f) << 16)
-#define WINDOW_B_DELAY(x) (((x) & 0x3f) <<  8)
-#define WINDOW_C_DELAY(x) (((x) & 0x3f) <<  0)
-
-#define DC_DISP_DISP_TIMING_OPTIONS            0x405
-#define VSYNC_H_POSITION(x) ((x) & 0xfff)
-
-#define DC_DISP_REF_TO_SYNC                    0x406
-#define DC_DISP_SYNC_WIDTH                     0x407
-#define DC_DISP_BACK_PORCH                     0x408
-#define DC_DISP_ACTIVE                         0x409
-#define DC_DISP_FRONT_PORCH                    0x40a
-#define DC_DISP_H_PULSE0_CONTROL               0x40b
-#define DC_DISP_H_PULSE0_POSITION_A            0x40c
-#define DC_DISP_H_PULSE0_POSITION_B            0x40d
-#define DC_DISP_H_PULSE0_POSITION_C            0x40e
-#define DC_DISP_H_PULSE0_POSITION_D            0x40f
-#define DC_DISP_H_PULSE1_CONTROL               0x410
-#define DC_DISP_H_PULSE1_POSITION_A            0x411
-#define DC_DISP_H_PULSE1_POSITION_B            0x412
-#define DC_DISP_H_PULSE1_POSITION_C            0x413
-#define DC_DISP_H_PULSE1_POSITION_D            0x414
-#define DC_DISP_H_PULSE2_CONTROL               0x415
-#define DC_DISP_H_PULSE2_POSITION_A            0x416
-#define DC_DISP_H_PULSE2_POSITION_B            0x417
-#define DC_DISP_H_PULSE2_POSITION_C            0x418
-#define DC_DISP_H_PULSE2_POSITION_D            0x419
-#define DC_DISP_V_PULSE0_CONTROL               0x41a
-#define DC_DISP_V_PULSE0_POSITION_A            0x41b
-#define DC_DISP_V_PULSE0_POSITION_B            0x41c
-#define DC_DISP_V_PULSE0_POSITION_C            0x41d
-#define DC_DISP_V_PULSE1_CONTROL               0x41e
-#define DC_DISP_V_PULSE1_POSITION_A            0x41f
-#define DC_DISP_V_PULSE1_POSITION_B            0x420
-#define DC_DISP_V_PULSE1_POSITION_C            0x421
-#define DC_DISP_V_PULSE2_CONTROL               0x422
-#define DC_DISP_V_PULSE2_POSITION_A            0x423
-#define DC_DISP_V_PULSE3_CONTROL               0x424
-#define DC_DISP_V_PULSE3_POSITION_A            0x425
-#define DC_DISP_M0_CONTROL                     0x426
-#define DC_DISP_M1_CONTROL                     0x427
-#define DC_DISP_DI_CONTROL                     0x428
-#define DC_DISP_PP_CONTROL                     0x429
-#define DC_DISP_PP_SELECT_A                    0x42a
-#define DC_DISP_PP_SELECT_B                    0x42b
-#define DC_DISP_PP_SELECT_C                    0x42c
-#define DC_DISP_PP_SELECT_D                    0x42d
-
-#define PULSE_MODE_NORMAL    (0 << 3)
-#define PULSE_MODE_ONE_CLOCK (1 << 3)
-#define PULSE_POLARITY_HIGH  (0 << 4)
-#define PULSE_POLARITY_LOW   (1 << 4)
-#define PULSE_QUAL_ALWAYS    (0 << 6)
-#define PULSE_QUAL_VACTIVE   (2 << 6)
-#define PULSE_QUAL_VACTIVE1  (3 << 6)
-#define PULSE_LAST_START_A   (0 << 8)
-#define PULSE_LAST_END_A     (1 << 8)
-#define PULSE_LAST_START_B   (2 << 8)
-#define PULSE_LAST_END_B     (3 << 8)
-#define PULSE_LAST_START_C   (4 << 8)
-#define PULSE_LAST_END_C     (5 << 8)
-#define PULSE_LAST_START_D   (6 << 8)
-#define PULSE_LAST_END_D     (7 << 8)
-
-#define PULSE_START(x) (((x) & 0xfff) <<  0)
-#define PULSE_END(x)   (((x) & 0xfff) << 16)
-
-#define DC_DISP_DISP_CLOCK_CONTROL             0x42e
-#define PIXEL_CLK_DIVIDER_PCD1  (0 << 8)
-#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
-#define PIXEL_CLK_DIVIDER_PCD2  (2 << 8)
-#define PIXEL_CLK_DIVIDER_PCD3  (3 << 8)
-#define PIXEL_CLK_DIVIDER_PCD4  (4 << 8)
-#define PIXEL_CLK_DIVIDER_PCD6  (5 << 8)
-#define PIXEL_CLK_DIVIDER_PCD8  (6 << 8)
-#define PIXEL_CLK_DIVIDER_PCD9  (7 << 8)
-#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
-#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
-#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
-#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
-#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
-#define SHIFT_CLK_DIVIDER(x)    ((x) & 0xff)
-
-#define DC_DISP_DISP_INTERFACE_CONTROL         0x42f
-#define DISP_DATA_FORMAT_DF1P1C    (0 << 0)
-#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
-#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
-#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
-#define DISP_DATA_FORMAT_DF2S      (4 << 0)
-#define DISP_DATA_FORMAT_DF3S      (5 << 0)
-#define DISP_DATA_FORMAT_DFSPI     (6 << 0)
-#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0)
-#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0)
-#define DISP_ALIGNMENT_MSB         (0 << 8)
-#define DISP_ALIGNMENT_LSB         (1 << 8)
-#define DISP_ORDER_RED_BLUE        (0 << 9)
-#define DISP_ORDER_BLUE_RED        (1 << 9)
-
-#define DC_DISP_DISP_COLOR_CONTROL             0x430
-#define BASE_COLOR_SIZE666     (0 << 0)
-#define BASE_COLOR_SIZE111     (1 << 0)
-#define BASE_COLOR_SIZE222     (2 << 0)
-#define BASE_COLOR_SIZE333     (3 << 0)
-#define BASE_COLOR_SIZE444     (4 << 0)
-#define BASE_COLOR_SIZE555     (5 << 0)
-#define BASE_COLOR_SIZE565     (6 << 0)
-#define BASE_COLOR_SIZE332     (7 << 0)
-#define BASE_COLOR_SIZE888     (8 << 0)
-#define DITHER_CONTROL_DISABLE (0 << 8)
-#define DITHER_CONTROL_ORDERED (2 << 8)
-#define DITHER_CONTROL_ERRDIFF (3 << 8)
-
-#define DC_DISP_SHIFT_CLOCK_OPTIONS            0x431
-
-#define DC_DISP_DATA_ENABLE_OPTIONS            0x432
-#define DE_SELECT_ACTIVE_BLANK  (0 << 0)
-#define DE_SELECT_ACTIVE        (1 << 0)
-#define DE_SELECT_ACTIVE_IS     (2 << 0)
-#define DE_CONTROL_ONECLK       (0 << 2)
-#define DE_CONTROL_NORMAL       (1 << 2)
-#define DE_CONTROL_EARLY_EXT    (2 << 2)
-#define DE_CONTROL_EARLY        (3 << 2)
-#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
-
-#define DC_DISP_SERIAL_INTERFACE_OPTIONS       0x433
-#define DC_DISP_LCD_SPI_OPTIONS                        0x434
-#define DC_DISP_BORDER_COLOR                   0x435
-#define DC_DISP_COLOR_KEY0_LOWER               0x436
-#define DC_DISP_COLOR_KEY0_UPPER               0x437
-#define DC_DISP_COLOR_KEY1_LOWER               0x438
-#define DC_DISP_COLOR_KEY1_UPPER               0x439
-
-#define DC_DISP_CURSOR_FOREGROUND              0x43c
-#define DC_DISP_CURSOR_BACKGROUND              0x43d
-
-#define DC_DISP_CURSOR_START_ADDR              0x43e
-#define DC_DISP_CURSOR_START_ADDR_NS           0x43f
-
-#define DC_DISP_CURSOR_POSITION                        0x440
-#define DC_DISP_CURSOR_POSITION_NS             0x441
-
-#define DC_DISP_INIT_SEQ_CONTROL               0x442
-#define DC_DISP_SPI_INIT_SEQ_DATA_A            0x443
-#define DC_DISP_SPI_INIT_SEQ_DATA_B            0x444
-#define DC_DISP_SPI_INIT_SEQ_DATA_C            0x445
-#define DC_DISP_SPI_INIT_SEQ_DATA_D            0x446
-
-#define DC_DISP_DC_MCCIF_FIFOCTRL              0x480
-#define DC_DISP_MCCIF_DISPLAY0A_HYST           0x481
-#define DC_DISP_MCCIF_DISPLAY0B_HYST           0x482
-#define DC_DISP_MCCIF_DISPLAY1A_HYST           0x483
-#define DC_DISP_MCCIF_DISPLAY1B_HYST           0x484
-
-#define DC_DISP_DAC_CRT_CTRL                   0x4c0
-#define DC_DISP_DISP_MISC_CONTROL              0x4c1
-#define DC_DISP_SD_CONTROL                     0x4c2
-#define DC_DISP_SD_CSC_COEFF                   0x4c3
-#define DC_DISP_SD_LUT(x)                      (0x4c4 + (x))
-#define DC_DISP_SD_FLICKER_CONTROL             0x4cd
-#define DC_DISP_DC_PIXEL_COUNT                 0x4ce
-#define DC_DISP_SD_HISTOGRAM(x)                        (0x4cf + (x))
-#define DC_DISP_SD_BL_PARAMETERS               0x4d7
-#define DC_DISP_SD_BL_TF(x)                    (0x4d8 + (x))
-#define DC_DISP_SD_BL_CONTROL                  0x4dc
-#define DC_DISP_SD_HW_K_VALUES                 0x4dd
-#define DC_DISP_SD_MAN_K_VALUES                        0x4de
-
-#define DC_WIN_CSC_YOF                         0x611
-#define DC_WIN_CSC_KYRGB                       0x612
-#define DC_WIN_CSC_KUR                         0x613
-#define DC_WIN_CSC_KVR                         0x614
-#define DC_WIN_CSC_KUG                         0x615
-#define DC_WIN_CSC_KVG                         0x616
-#define DC_WIN_CSC_KUB                         0x617
-#define DC_WIN_CSC_KVB                         0x618
-
-#define DC_WIN_WIN_OPTIONS                     0x700
-#define COLOR_EXPAND (1 <<  6)
-#define CSC_ENABLE   (1 << 18)
-#define WIN_ENABLE   (1 << 30)
-
-#define DC_WIN_BYTE_SWAP                       0x701
-#define BYTE_SWAP_NOSWAP  (0 << 0)
-#define BYTE_SWAP_SWAP2   (1 << 0)
-#define BYTE_SWAP_SWAP4   (2 << 0)
-#define BYTE_SWAP_SWAP4HW (3 << 0)
-
-#define DC_WIN_BUFFER_CONTROL                  0x702
-#define BUFFER_CONTROL_HOST  (0 << 0)
-#define BUFFER_CONTROL_VI    (1 << 0)
-#define BUFFER_CONTROL_EPP   (2 << 0)
-#define BUFFER_CONTROL_MPEGE (3 << 0)
-#define BUFFER_CONTROL_SB2D  (4 << 0)
-
-#define DC_WIN_COLOR_DEPTH                     0x703
-#define WIN_COLOR_DEPTH_P1              0
-#define WIN_COLOR_DEPTH_P2              1
-#define WIN_COLOR_DEPTH_P4              2
-#define WIN_COLOR_DEPTH_P8              3
-#define WIN_COLOR_DEPTH_B4G4R4A4        4
-#define WIN_COLOR_DEPTH_B5G5R5A         5
-#define WIN_COLOR_DEPTH_B5G6R5          6
-#define WIN_COLOR_DEPTH_AB5G5R5         7
-#define WIN_COLOR_DEPTH_B8G8R8A8       12
-#define WIN_COLOR_DEPTH_R8G8B8A8       13
-#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 14
-#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 15
-#define WIN_COLOR_DEPTH_YCbCr422       16
-#define WIN_COLOR_DEPTH_YUV422         17
-#define WIN_COLOR_DEPTH_YCbCr420P      18
-#define WIN_COLOR_DEPTH_YUV420P        19
-#define WIN_COLOR_DEPTH_YCbCr422P      20
-#define WIN_COLOR_DEPTH_YUV422P        21
-#define WIN_COLOR_DEPTH_YCbCr422R      22
-#define WIN_COLOR_DEPTH_YUV422R        23
-#define WIN_COLOR_DEPTH_YCbCr422RA     24
-#define WIN_COLOR_DEPTH_YUV422RA       25
-
-#define DC_WIN_POSITION                                0x704
-#define H_POSITION(x) (((x) & 0x1fff) <<  0)
-#define V_POSITION(x) (((x) & 0x1fff) << 16)
-
-#define DC_WIN_SIZE                            0x705
-#define H_SIZE(x) (((x) & 0x1fff) <<  0)
-#define V_SIZE(x) (((x) & 0x1fff) << 16)
-
-#define DC_WIN_PRESCALED_SIZE                  0x706
-#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) <<  0)
-#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
-
-#define DC_WIN_H_INITIAL_DDA                   0x707
-#define DC_WIN_V_INITIAL_DDA                   0x708
-#define DC_WIN_DDA_INC                         0x709
-#define H_DDA_INC(x) (((x) & 0xffff) <<  0)
-#define V_DDA_INC(x) (((x) & 0xffff) << 16)
-
-#define DC_WIN_LINE_STRIDE                     0x70a
-#define DC_WIN_BUF_STRIDE                      0x70b
-#define DC_WIN_UV_BUF_STRIDE                   0x70c
-#define DC_WIN_BUFFER_ADDR_MODE                        0x70d
-#define DC_WIN_DV_CONTROL                      0x70e
-
-#define DC_WIN_BLEND_NOKEY                     0x70f
-#define DC_WIN_BLEND_1WIN                      0x710
-#define DC_WIN_BLEND_2WIN_X                    0x711
-#define DC_WIN_BLEND_2WIN_Y                    0x712
-#define DC_WIN_BLEND_3WIN_XY                   0x713
-
-#define DC_WIN_HP_FETCH_CONTROL                        0x714
-
-#define DC_WINBUF_START_ADDR                   0x800
-#define DC_WINBUF_START_ADDR_NS                        0x801
-#define DC_WINBUF_START_ADDR_U                 0x802
-#define DC_WINBUF_START_ADDR_U_NS              0x803
-#define DC_WINBUF_START_ADDR_V                 0x804
-#define DC_WINBUF_START_ADDR_V_NS              0x805
-
-#define DC_WINBUF_ADDR_H_OFFSET                        0x806
-#define DC_WINBUF_ADDR_H_OFFSET_NS             0x807
-#define DC_WINBUF_ADDR_V_OFFSET                        0x808
-#define DC_WINBUF_ADDR_V_OFFSET_NS             0x809
-
-#define DC_WINBUF_UFLOW_STATUS                 0x80a
-
-#define DC_WINBUF_AD_UFLOW_STATUS              0xbca
-#define DC_WINBUF_BD_UFLOW_STATUS              0xdca
-#define DC_WINBUF_CD_UFLOW_STATUS              0xfca
-
-/* synchronization points */
-#define SYNCPT_VBLANK0 26
-#define SYNCPT_VBLANK1 27
-
-#endif /* TEGRA_DC_H */
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
deleted file mode 100644 (file)
index c2db409..0000000
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/host1x.h>
-
-#include "drm.h"
-#include "gem.h"
-
-#define DRIVER_NAME "tegra"
-#define DRIVER_DESC "NVIDIA Tegra graphics"
-#define DRIVER_DATE "20120330"
-#define DRIVER_MAJOR 0
-#define DRIVER_MINOR 0
-#define DRIVER_PATCHLEVEL 0
-
-struct tegra_drm_file {
-       struct list_head contexts;
-};
-
-static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
-{
-       struct host1x_device *device = to_host1x_device(drm->dev);
-       struct tegra_drm *tegra;
-       int err;
-
-       tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
-       if (!tegra)
-               return -ENOMEM;
-
-       dev_set_drvdata(drm->dev, tegra);
-       mutex_init(&tegra->clients_lock);
-       INIT_LIST_HEAD(&tegra->clients);
-       drm->dev_private = tegra;
-       tegra->drm = drm;
-
-       drm_mode_config_init(drm);
-
-       err = host1x_device_init(device);
-       if (err < 0)
-               return err;
-
-       /*
-        * We don't use the drm_irq_install() helpers provided by the DRM
-        * core, so we need to set this manually in order to allow the
-        * DRM_IOCTL_WAIT_VBLANK to operate correctly.
-        */
-       drm->irq_enabled = true;
-
-       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;
-
-       drm_kms_helper_poll_init(drm);
-
-       return 0;
-}
-
-static int tegra_drm_unload(struct drm_device *drm)
-{
-       struct host1x_device *device = to_host1x_device(drm->dev);
-       int err;
-
-       drm_kms_helper_poll_fini(drm);
-       tegra_drm_fb_exit(drm);
-
-       err = host1x_device_exit(device);
-       if (err < 0)
-               return err;
-
-       drm_mode_config_cleanup(drm);
-
-       return 0;
-}
-
-static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
-{
-       struct tegra_drm_file *fpriv;
-
-       fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
-       if (!fpriv)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&fpriv->contexts);
-       filp->driver_priv = fpriv;
-
-       return 0;
-}
-
-static void tegra_drm_context_free(struct tegra_drm_context *context)
-{
-       context->client->ops->close_channel(context);
-       kfree(context);
-}
-
-static void tegra_drm_lastclose(struct drm_device *drm)
-{
-       struct tegra_drm *tegra = drm->dev_private;
-
-       tegra_fbdev_restore_mode(tegra->fbdev);
-}
-
-#ifdef CONFIG_DRM_TEGRA_STAGING
-static struct tegra_drm_context *tegra_drm_get_context(__u64 context)
-{
-       return (struct tegra_drm_context *)(uintptr_t)context;
-}
-
-static bool tegra_drm_file_owns_context(struct tegra_drm_file *file,
-                                       struct tegra_drm_context *context)
-{
-       struct tegra_drm_context *ctx;
-
-       list_for_each_entry(ctx, &file->contexts, list)
-               if (ctx == context)
-                       return true;
-
-       return false;
-}
-
-static int tegra_gem_create(struct drm_device *drm, void *data,
-                           struct drm_file *file)
-{
-       struct drm_tegra_gem_create *args = data;
-       struct tegra_bo *bo;
-
-       bo = tegra_bo_create_with_handle(file, drm, args->size,
-                                        &args->handle);
-       if (IS_ERR(bo))
-               return PTR_ERR(bo);
-
-       return 0;
-}
-
-static int tegra_gem_mmap(struct drm_device *drm, void *data,
-                         struct drm_file *file)
-{
-       struct drm_tegra_gem_mmap *args = data;
-       struct drm_gem_object *gem;
-       struct tegra_bo *bo;
-
-       gem = drm_gem_object_lookup(drm, file, args->handle);
-       if (!gem)
-               return -EINVAL;
-
-       bo = to_tegra_bo(gem);
-
-       args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
-
-       drm_gem_object_unreference(gem);
-
-       return 0;
-}
-
-static int tegra_syncpt_read(struct drm_device *drm, void *data,
-                            struct drm_file *file)
-{
-       struct host1x *host = dev_get_drvdata(drm->dev->parent);
-       struct drm_tegra_syncpt_read *args = data;
-       struct host1x_syncpt *sp;
-
-       sp = host1x_syncpt_get(host, args->id);
-       if (!sp)
-               return -EINVAL;
-
-       args->value = host1x_syncpt_read_min(sp);
-       return 0;
-}
-
-static int tegra_syncpt_incr(struct drm_device *drm, void *data,
-                            struct drm_file *file)
-{
-       struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
-       struct drm_tegra_syncpt_incr *args = data;
-       struct host1x_syncpt *sp;
-
-       sp = host1x_syncpt_get(host1x, args->id);
-       if (!sp)
-               return -EINVAL;
-
-       return host1x_syncpt_incr(sp);
-}
-
-static int tegra_syncpt_wait(struct drm_device *drm, void *data,
-                            struct drm_file *file)
-{
-       struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
-       struct drm_tegra_syncpt_wait *args = data;
-       struct host1x_syncpt *sp;
-
-       sp = host1x_syncpt_get(host1x, args->id);
-       if (!sp)
-               return -EINVAL;
-
-       return host1x_syncpt_wait(sp, args->thresh, args->timeout,
-                                 &args->value);
-}
-
-static int tegra_open_channel(struct drm_device *drm, void *data,
-                             struct drm_file *file)
-{
-       struct tegra_drm_file *fpriv = file->driver_priv;
-       struct tegra_drm *tegra = drm->dev_private;
-       struct drm_tegra_open_channel *args = data;
-       struct tegra_drm_context *context;
-       struct tegra_drm_client *client;
-       int err = -ENODEV;
-
-       context = kzalloc(sizeof(*context), GFP_KERNEL);
-       if (!context)
-               return -ENOMEM;
-
-       list_for_each_entry(client, &tegra->clients, list)
-               if (client->base.class == args->client) {
-                       err = client->ops->open_channel(client, context);
-                       if (err)
-                               break;
-
-                       list_add(&context->list, &fpriv->contexts);
-                       args->context = (uintptr_t)context;
-                       context->client = client;
-                       return 0;
-               }
-
-       kfree(context);
-       return err;
-}
-
-static int tegra_close_channel(struct drm_device *drm, void *data,
-                              struct drm_file *file)
-{
-       struct tegra_drm_file *fpriv = file->driver_priv;
-       struct drm_tegra_close_channel *args = data;
-       struct tegra_drm_context *context;
-
-       context = tegra_drm_get_context(args->context);
-
-       if (!tegra_drm_file_owns_context(fpriv, context))
-               return -EINVAL;
-
-       list_del(&context->list);
-       tegra_drm_context_free(context);
-
-       return 0;
-}
-
-static int tegra_get_syncpt(struct drm_device *drm, void *data,
-                           struct drm_file *file)
-{
-       struct tegra_drm_file *fpriv = file->driver_priv;
-       struct drm_tegra_get_syncpt *args = data;
-       struct tegra_drm_context *context;
-       struct host1x_syncpt *syncpt;
-
-       context = tegra_drm_get_context(args->context);
-
-       if (!tegra_drm_file_owns_context(fpriv, context))
-               return -ENODEV;
-
-       if (args->index >= context->client->base.num_syncpts)
-               return -EINVAL;
-
-       syncpt = context->client->base.syncpts[args->index];
-       args->id = host1x_syncpt_id(syncpt);
-
-       return 0;
-}
-
-static int tegra_submit(struct drm_device *drm, void *data,
-                       struct drm_file *file)
-{
-       struct tegra_drm_file *fpriv = file->driver_priv;
-       struct drm_tegra_submit *args = data;
-       struct tegra_drm_context *context;
-
-       context = tegra_drm_get_context(args->context);
-
-       if (!tegra_drm_file_owns_context(fpriv, context))
-               return -ENODEV;
-
-       return context->client->ops->submit(context, args, drm, file);
-}
-#endif
-
-static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
-#ifdef CONFIG_DRM_TEGRA_STAGING
-       DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
-#endif
-};
-
-static const struct file_operations tegra_drm_fops = {
-       .owner = THIS_MODULE,
-       .open = drm_open,
-       .release = drm_release,
-       .unlocked_ioctl = drm_ioctl,
-       .mmap = tegra_drm_mmap,
-       .poll = drm_poll,
-       .read = drm_read,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = drm_compat_ioctl,
-#endif
-       .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 tegra_drm_file *fpriv = file->driver_priv;
-       struct tegra_drm_context *context, *tmp;
-       struct drm_crtc *crtc;
-
-       list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
-               tegra_dc_cancel_page_flip(crtc, file);
-
-       list_for_each_entry_safe(context, tmp, &fpriv->contexts, list)
-               tegra_drm_context_free(context);
-
-       kfree(fpriv);
-}
-
-#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_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 = tegra_bo_free_object,
-       .gem_vm_ops = &tegra_bo_vm_ops,
-       .dumb_create = tegra_bo_dumb_create,
-       .dumb_map_offset = tegra_bo_dumb_map_offset,
-       .dumb_destroy = drm_gem_dumb_destroy,
-
-       .ioctls = tegra_drm_ioctls,
-       .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
-       .fops = &tegra_drm_fops,
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-int tegra_drm_register_client(struct tegra_drm *tegra,
-                             struct tegra_drm_client *client)
-{
-       mutex_lock(&tegra->clients_lock);
-       list_add_tail(&client->list, &tegra->clients);
-       mutex_unlock(&tegra->clients_lock);
-
-       return 0;
-}
-
-int tegra_drm_unregister_client(struct tegra_drm *tegra,
-                               struct tegra_drm_client *client)
-{
-       mutex_lock(&tegra->clients_lock);
-       list_del_init(&client->list);
-       mutex_unlock(&tegra->clients_lock);
-
-       return 0;
-}
-
-static int host1x_drm_probe(struct host1x_device *device)
-{
-       return drm_host1x_init(&tegra_drm_driver, device);
-}
-
-static int host1x_drm_remove(struct host1x_device *device)
-{
-       drm_host1x_exit(&tegra_drm_driver, device);
-
-       return 0;
-}
-
-static const struct of_device_id host1x_drm_subdevs[] = {
-       { .compatible = "nvidia,tegra20-dc", },
-       { .compatible = "nvidia,tegra20-hdmi", },
-       { .compatible = "nvidia,tegra20-gr2d", },
-       { .compatible = "nvidia,tegra30-dc", },
-       { .compatible = "nvidia,tegra30-hdmi", },
-       { .compatible = "nvidia,tegra30-gr2d", },
-       { /* sentinel */ }
-};
-
-static struct host1x_driver host1x_drm_driver = {
-       .name = "drm",
-       .probe = host1x_drm_probe,
-       .remove = host1x_drm_remove,
-       .subdevs = host1x_drm_subdevs,
-};
-
-static int __init host1x_drm_init(void)
-{
-       int err;
-
-       err = host1x_driver_register(&host1x_drm_driver);
-       if (err < 0)
-               return err;
-
-       err = platform_driver_register(&tegra_dc_driver);
-       if (err < 0)
-               goto unregister_host1x;
-
-       err = platform_driver_register(&tegra_hdmi_driver);
-       if (err < 0)
-               goto unregister_dc;
-
-       err = platform_driver_register(&tegra_gr2d_driver);
-       if (err < 0)
-               goto unregister_hdmi;
-
-       return 0;
-
-unregister_hdmi:
-       platform_driver_unregister(&tegra_hdmi_driver);
-unregister_dc:
-       platform_driver_unregister(&tegra_dc_driver);
-unregister_host1x:
-       host1x_driver_unregister(&host1x_drm_driver);
-       return err;
-}
-module_init(host1x_drm_init);
-
-static void __exit host1x_drm_exit(void)
-{
-       platform_driver_unregister(&tegra_gr2d_driver);
-       platform_driver_unregister(&tegra_hdmi_driver);
-       platform_driver_unregister(&tegra_dc_driver);
-       host1x_driver_unregister(&host1x_drm_driver);
-}
-module_exit(host1x_drm_exit);
-
-MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
-MODULE_DESCRIPTION("NVIDIA Tegra DRM driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h
deleted file mode 100644 (file)
index 25522e2..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012-2013 NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef HOST1X_DRM_H
-#define HOST1X_DRM_H 1
-
-#include <uapi/drm/tegra_drm.h>
-#include <linux/host1x.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_fixed.h>
-
-struct tegra_fb {
-       struct drm_framebuffer base;
-       struct tegra_bo **planes;
-       unsigned int num_planes;
-};
-
-struct tegra_fbdev {
-       struct drm_fb_helper base;
-       struct tegra_fb *fb;
-};
-
-struct tegra_drm {
-       struct drm_device *drm;
-
-       struct mutex clients_lock;
-       struct list_head clients;
-
-       struct tegra_fbdev *fbdev;
-};
-
-struct tegra_drm_client;
-
-struct tegra_drm_context {
-       struct tegra_drm_client *client;
-       struct host1x_channel *channel;
-       struct list_head list;
-};
-
-struct tegra_drm_client_ops {
-       int (*open_channel)(struct tegra_drm_client *client,
-                           struct tegra_drm_context *context);
-       void (*close_channel)(struct tegra_drm_context *context);
-       int (*submit)(struct tegra_drm_context *context,
-                     struct drm_tegra_submit *args, struct drm_device *drm,
-                     struct drm_file *file);
-};
-
-struct tegra_drm_client {
-       struct host1x_client base;
-       struct list_head list;
-
-       const struct tegra_drm_client_ops *ops;
-};
-
-static inline struct tegra_drm_client *
-host1x_to_drm_client(struct host1x_client *client)
-{
-       return container_of(client, struct tegra_drm_client, base);
-}
-
-extern int tegra_drm_register_client(struct tegra_drm *tegra,
-                                    struct tegra_drm_client *client);
-extern int tegra_drm_unregister_client(struct tegra_drm *tegra,
-                                      struct tegra_drm_client *client);
-
-extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
-extern int tegra_drm_exit(struct tegra_drm *tegra);
-
-struct tegra_output;
-
-struct tegra_dc {
-       struct host1x_client client;
-       struct device *dev;
-       spinlock_t lock;
-
-       struct drm_crtc base;
-       int pipe;
-
-       struct clk *clk;
-       void __iomem *regs;
-       int irq;
-
-       struct tegra_output *rgb;
-
-       struct list_head list;
-
-       struct drm_info_list *debugfs_files;
-       struct drm_minor *minor;
-       struct dentry *debugfs;
-
-       /* page-flip handling */
-       struct drm_pending_vblank_event *event;
-};
-
-static inline struct tegra_dc *
-host1x_client_to_dc(struct host1x_client *client)
-{
-       return container_of(client, struct tegra_dc, client);
-}
-
-static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
-{
-       return container_of(crtc, struct tegra_dc, base);
-}
-
-static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value,
-                                  unsigned long reg)
-{
-       writel(value, dc->regs + (reg << 2));
-}
-
-static inline unsigned long tegra_dc_readl(struct tegra_dc *dc,
-                                          unsigned long reg)
-{
-       return readl(dc->regs + (reg << 2));
-}
-
-struct tegra_dc_window {
-       struct {
-               unsigned int x;
-               unsigned int y;
-               unsigned int w;
-               unsigned int h;
-       } src;
-       struct {
-               unsigned int x;
-               unsigned int y;
-               unsigned int w;
-               unsigned int h;
-       } dst;
-       unsigned int bits_per_pixel;
-       unsigned int format;
-       unsigned int stride[2];
-       unsigned long base[3];
-};
-
-/* from dc.c */
-extern unsigned int tegra_dc_format(uint32_t format);
-extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
-                                const struct tegra_dc_window *window);
-extern void tegra_dc_enable_vblank(struct tegra_dc *dc);
-extern void tegra_dc_disable_vblank(struct tegra_dc *dc);
-extern void tegra_dc_cancel_page_flip(struct drm_crtc *crtc,
-                                     struct drm_file *file);
-
-struct tegra_output_ops {
-       int (*enable)(struct tegra_output *output);
-       int (*disable)(struct tegra_output *output);
-       int (*setup_clock)(struct tegra_output *output, struct clk *clk,
-                          unsigned long pclk);
-       int (*check_mode)(struct tegra_output *output,
-                         struct drm_display_mode *mode,
-                         enum drm_mode_status *status);
-};
-
-enum tegra_output_type {
-       TEGRA_OUTPUT_RGB,
-       TEGRA_OUTPUT_HDMI,
-};
-
-struct tegra_output {
-       struct device_node *of_node;
-       struct device *dev;
-
-       const struct tegra_output_ops *ops;
-       enum tegra_output_type type;
-
-       struct i2c_adapter *ddc;
-       const struct edid *edid;
-       unsigned int hpd_irq;
-       int hpd_gpio;
-
-       struct drm_encoder encoder;
-       struct drm_connector connector;
-};
-
-static inline struct tegra_output *encoder_to_output(struct drm_encoder *e)
-{
-       return container_of(e, struct tegra_output, encoder);
-}
-
-static inline struct tegra_output *connector_to_output(struct drm_connector *c)
-{
-       return container_of(c, struct tegra_output, connector);
-}
-
-static inline int tegra_output_enable(struct tegra_output *output)
-{
-       if (output && output->ops && output->ops->enable)
-               return output->ops->enable(output);
-
-       return output ? -ENOSYS : -EINVAL;
-}
-
-static inline int tegra_output_disable(struct tegra_output *output)
-{
-       if (output && output->ops && output->ops->disable)
-               return output->ops->disable(output);
-
-       return output ? -ENOSYS : -EINVAL;
-}
-
-static inline int tegra_output_setup_clock(struct tegra_output *output,
-                                          struct clk *clk, unsigned long pclk)
-{
-       if (output && output->ops && output->ops->setup_clock)
-               return output->ops->setup_clock(output, clk, pclk);
-
-       return output ? -ENOSYS : -EINVAL;
-}
-
-static inline int tegra_output_check_mode(struct tegra_output *output,
-                                         struct drm_display_mode *mode,
-                                         enum drm_mode_status *status)
-{
-       if (output && output->ops && output->ops->check_mode)
-               return output->ops->check_mode(output, mode, status);
-
-       return output ? -ENOSYS : -EINVAL;
-}
-
-/* from bus.c */
-int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device);
-void drm_host1x_exit(struct drm_driver *driver, struct host1x_device *device);
-
-/* from rgb.c */
-extern int tegra_dc_rgb_probe(struct tegra_dc *dc);
-extern int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc);
-extern int tegra_dc_rgb_exit(struct tegra_dc *dc);
-
-/* from output.c */
-extern int tegra_output_parse_dt(struct tegra_output *output);
-extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output);
-extern int tegra_output_exit(struct tegra_output *output);
-
-/* from fb.c */
-struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
-                                   unsigned int index);
-extern int tegra_drm_fb_init(struct drm_device *drm);
-extern void tegra_drm_fb_exit(struct drm_device *drm);
-extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
-
-extern struct platform_driver tegra_dc_driver;
-extern struct platform_driver tegra_hdmi_driver;
-extern struct platform_driver tegra_gr2d_driver;
-
-#endif /* HOST1X_DRM_H */
diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/host1x/drm/fb.c
deleted file mode 100644 (file)
index 1fd4e19..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Avionic Design GmbH
- * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * Based on the KMS/FB CMA helpers
- *   Copyright (C) 2012 Analog Device Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "drm.h"
-#include "gem.h"
-
-static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb)
-{
-       return container_of(fb, struct tegra_fb, base);
-}
-
-static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
-{
-       return container_of(helper, struct tegra_fbdev, base);
-}
-
-struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
-                                   unsigned int index)
-{
-       struct tegra_fb *fb = to_tegra_fb(framebuffer);
-
-       if (index >= drm_format_num_planes(framebuffer->pixel_format))
-               return NULL;
-
-       return fb->planes[index];
-}
-
-static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
-{
-       struct tegra_fb *fb = to_tegra_fb(framebuffer);
-       unsigned int i;
-
-       for (i = 0; i < fb->num_planes; i++) {
-               struct tegra_bo *bo = fb->planes[i];
-
-               if (bo)
-                       drm_gem_object_unreference_unlocked(&bo->gem);
-       }
-
-       drm_framebuffer_cleanup(framebuffer);
-       kfree(fb->planes);
-       kfree(fb);
-}
-
-static int tegra_fb_create_handle(struct drm_framebuffer *framebuffer,
-                                 struct drm_file *file, unsigned int *handle)
-{
-       struct tegra_fb *fb = to_tegra_fb(framebuffer);
-
-       return drm_gem_handle_create(file, &fb->planes[0]->gem, handle);
-}
-
-static struct drm_framebuffer_funcs tegra_fb_funcs = {
-       .destroy = tegra_fb_destroy,
-       .create_handle = tegra_fb_create_handle,
-};
-
-static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm,
-                                      struct drm_mode_fb_cmd2 *mode_cmd,
-                                      struct tegra_bo **planes,
-                                      unsigned int num_planes)
-{
-       struct tegra_fb *fb;
-       unsigned int i;
-       int err;
-
-       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-       if (!fb)
-               return ERR_PTR(-ENOMEM);
-
-       fb->planes = kzalloc(num_planes * sizeof(*planes), GFP_KERNEL);
-       if (!fb->planes)
-               return ERR_PTR(-ENOMEM);
-
-       fb->num_planes = num_planes;
-
-       drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
-
-       for (i = 0; i < fb->num_planes; i++)
-               fb->planes[i] = planes[i];
-
-       err = drm_framebuffer_init(drm, &fb->base, &tegra_fb_funcs);
-       if (err < 0) {
-               dev_err(drm->dev, "failed to initialize framebuffer: %d\n",
-                       err);
-               kfree(fb->planes);
-               kfree(fb);
-               return ERR_PTR(err);
-       }
-
-       return fb;
-}
-
-static struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
-                                              struct drm_file *file,
-                                              struct drm_mode_fb_cmd2 *cmd)
-{
-       unsigned int hsub, vsub, i;
-       struct tegra_bo *planes[4];
-       struct drm_gem_object *gem;
-       struct tegra_fb *fb;
-       int err;
-
-       hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format);
-       vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format);
-
-       for (i = 0; i < drm_format_num_planes(cmd->pixel_format); i++) {
-               unsigned int width = cmd->width / (i ? hsub : 1);
-               unsigned int height = cmd->height / (i ? vsub : 1);
-               unsigned int size, bpp;
-
-               gem = drm_gem_object_lookup(drm, file, cmd->handles[i]);
-               if (!gem) {
-                       err = -ENXIO;
-                       goto unreference;
-               }
-
-               bpp = drm_format_plane_cpp(cmd->pixel_format, i);
-
-               size = (height - 1) * cmd->pitches[i] +
-                      width * bpp + cmd->offsets[i];
-
-               if (gem->size < size) {
-                       err = -EINVAL;
-                       goto unreference;
-               }
-
-               planes[i] = to_tegra_bo(gem);
-       }
-
-       fb = tegra_fb_alloc(drm, cmd, planes, i);
-       if (IS_ERR(fb)) {
-               err = PTR_ERR(fb);
-               goto unreference;
-       }
-
-       return &fb->base;
-
-unreference:
-       while (i--)
-               drm_gem_object_unreference_unlocked(&planes[i]->gem);
-
-       return ERR_PTR(err);
-}
-
-static struct fb_ops tegra_fb_ops = {
-       .owner = THIS_MODULE,
-       .fb_fillrect = sys_fillrect,
-       .fb_copyarea = sys_copyarea,
-       .fb_imageblit = sys_imageblit,
-       .fb_check_var = drm_fb_helper_check_var,
-       .fb_set_par = drm_fb_helper_set_par,
-       .fb_blank = drm_fb_helper_blank,
-       .fb_pan_display = drm_fb_helper_pan_display,
-       .fb_setcmap = drm_fb_helper_setcmap,
-};
-
-static int tegra_fbdev_probe(struct drm_fb_helper *helper,
-                            struct drm_fb_helper_surface_size *sizes)
-{
-       struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
-       struct drm_device *drm = helper->dev;
-       struct drm_mode_fb_cmd2 cmd = { 0 };
-       unsigned int bytes_per_pixel;
-       struct drm_framebuffer *fb;
-       unsigned long offset;
-       struct fb_info *info;
-       struct tegra_bo *bo;
-       size_t size;
-       int err;
-
-       bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
-
-       cmd.width = sizes->surface_width;
-       cmd.height = sizes->surface_height;
-       cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
-       cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
-                                                    sizes->surface_depth);
-
-       size = cmd.pitches[0] * cmd.height;
-
-       bo = tegra_bo_create(drm, size);
-       if (IS_ERR(bo))
-               return PTR_ERR(bo);
-
-       info = framebuffer_alloc(0, drm->dev);
-       if (!info) {
-               dev_err(drm->dev, "failed to allocate framebuffer info\n");
-               tegra_bo_free_object(&bo->gem);
-               return -ENOMEM;
-       }
-
-       fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1);
-       if (IS_ERR(fbdev->fb)) {
-               dev_err(drm->dev, "failed to allocate DRM framebuffer\n");
-               err = PTR_ERR(fbdev->fb);
-               goto release;
-       }
-
-       fb = &fbdev->fb->base;
-       helper->fb = fb;
-       helper->fbdev = info;
-
-       info->par = helper;
-       info->flags = FBINFO_FLAG_DEFAULT;
-       info->fbops = &tegra_fb_ops;
-
-       err = fb_alloc_cmap(&info->cmap, 256, 0);
-       if (err < 0) {
-               dev_err(drm->dev, "failed to allocate color map: %d\n", err);
-               goto destroy;
-       }
-
-       drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
-       drm_fb_helper_fill_var(info, helper, fb->width, fb->height);
-
-       offset = info->var.xoffset * bytes_per_pixel +
-                info->var.yoffset * fb->pitches[0];
-
-       drm->mode_config.fb_base = (resource_size_t)bo->paddr;
-       info->screen_base = bo->vaddr + offset;
-       info->screen_size = size;
-       info->fix.smem_start = (unsigned long)(bo->paddr + offset);
-       info->fix.smem_len = size;
-
-       return 0;
-
-destroy:
-       drm_framebuffer_unregister_private(fb);
-       tegra_fb_destroy(fb);
-release:
-       framebuffer_release(info);
-       return err;
-}
-
-static struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
-       .fb_probe = tegra_fbdev_probe,
-};
-
-static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
-                                             unsigned int preferred_bpp,
-                                             unsigned int num_crtc,
-                                             unsigned int max_connectors)
-{
-       struct drm_fb_helper *helper;
-       struct tegra_fbdev *fbdev;
-       int err;
-
-       fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
-       if (!fbdev) {
-               dev_err(drm->dev, "failed to allocate DRM fbdev\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       fbdev->base.funcs = &tegra_fb_helper_funcs;
-       helper = &fbdev->base;
-
-       err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
-       if (err < 0) {
-               dev_err(drm->dev, "failed to initialize DRM FB helper\n");
-               goto free;
-       }
-
-       err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
-       if (err < 0) {
-               dev_err(drm->dev, "failed to add connectors\n");
-               goto fini;
-       }
-
-       drm_helper_disable_unused_functions(drm);
-
-       err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
-       if (err < 0) {
-               dev_err(drm->dev, "failed to set initial configuration\n");
-               goto fini;
-       }
-
-       return fbdev;
-
-fini:
-       drm_fb_helper_fini(&fbdev->base);
-free:
-       kfree(fbdev);
-       return ERR_PTR(err);
-}
-
-static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
-{
-       struct fb_info *info = fbdev->base.fbdev;
-
-       if (info) {
-               int err;
-
-               err = unregister_framebuffer(info);
-               if (err < 0)
-                       DRM_DEBUG_KMS("failed to unregister framebuffer\n");
-
-               if (info->cmap.len)
-                       fb_dealloc_cmap(&info->cmap);
-
-               framebuffer_release(info);
-       }
-
-       if (fbdev->fb) {
-               drm_framebuffer_unregister_private(&fbdev->fb->base);
-               tegra_fb_destroy(&fbdev->fb->base);
-       }
-
-       drm_fb_helper_fini(&fbdev->base);
-       kfree(fbdev);
-}
-
-static void tegra_fb_output_poll_changed(struct drm_device *drm)
-{
-       struct tegra_drm *tegra = drm->dev_private;
-
-       if (tegra->fbdev)
-               drm_fb_helper_hotplug_event(&tegra->fbdev->base);
-}
-
-static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
-       .fb_create = tegra_fb_create,
-       .output_poll_changed = tegra_fb_output_poll_changed,
-};
-
-int tegra_drm_fb_init(struct drm_device *drm)
-{
-       struct tegra_drm *tegra = drm->dev_private;
-       struct tegra_fbdev *fbdev;
-
-       drm->mode_config.min_width = 0;
-       drm->mode_config.min_height = 0;
-
-       drm->mode_config.max_width = 4096;
-       drm->mode_config.max_height = 4096;
-
-       drm->mode_config.funcs = &tegra_drm_mode_funcs;
-
-       fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
-                                  drm->mode_config.num_connector);
-       if (IS_ERR(fbdev))
-               return PTR_ERR(fbdev);
-
-       tegra->fbdev = fbdev;
-
-       return 0;
-}
-
-void tegra_drm_fb_exit(struct drm_device *drm)
-{
-       struct tegra_drm *tegra = drm->dev_private;
-
-       tegra_fbdev_free(tegra->fbdev);
-}
-
-void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
-{
-       if (fbdev) {
-               drm_modeset_lock_all(fbdev->base.dev);
-               drm_fb_helper_restore_fbdev_mode(&fbdev->base);
-               drm_modeset_unlock_all(fbdev->base.dev);
-       }
-}
diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/host1x/drm/gem.c
deleted file mode 100644 (file)
index 267c0c2..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * NVIDIA Tegra DRM GEM helper functions
- *
- * Copyright (C) 2012 Sascha Hauer, Pengutronix
- * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved.
- *
- * Based on the GEM/CMA helpers
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include "gem.h"
-
-static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
-{
-       return container_of(bo, struct tegra_bo, base);
-}
-
-static void tegra_bo_put(struct host1x_bo *bo)
-{
-       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
-       struct drm_device *drm = obj->gem.dev;
-
-       mutex_lock(&drm->struct_mutex);
-       drm_gem_object_unreference(&obj->gem);
-       mutex_unlock(&drm->struct_mutex);
-}
-
-static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt)
-{
-       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
-
-       return obj->paddr;
-}
-
-static void tegra_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt)
-{
-}
-
-static void *tegra_bo_mmap(struct host1x_bo *bo)
-{
-       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
-
-       return obj->vaddr;
-}
-
-static void tegra_bo_munmap(struct host1x_bo *bo, void *addr)
-{
-}
-
-static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page)
-{
-       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
-
-       return obj->vaddr + page * PAGE_SIZE;
-}
-
-static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page,
-                           void *addr)
-{
-}
-
-static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
-{
-       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
-       struct drm_device *drm = obj->gem.dev;
-
-       mutex_lock(&drm->struct_mutex);
-       drm_gem_object_reference(&obj->gem);
-       mutex_unlock(&drm->struct_mutex);
-
-       return bo;
-}
-
-const struct host1x_bo_ops tegra_bo_ops = {
-       .get = tegra_bo_get,
-       .put = tegra_bo_put,
-       .pin = tegra_bo_pin,
-       .unpin = tegra_bo_unpin,
-       .mmap = tegra_bo_mmap,
-       .munmap = tegra_bo_munmap,
-       .kmap = tegra_bo_kmap,
-       .kunmap = tegra_bo_kunmap,
-};
-
-static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo)
-{
-       dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr);
-}
-
-struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size)
-{
-       struct tegra_bo *bo;
-       int err;
-
-       bo = kzalloc(sizeof(*bo), GFP_KERNEL);
-       if (!bo)
-               return ERR_PTR(-ENOMEM);
-
-       host1x_bo_init(&bo->base, &tegra_bo_ops);
-       size = round_up(size, PAGE_SIZE);
-
-       bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr,
-                                          GFP_KERNEL | __GFP_NOWARN);
-       if (!bo->vaddr) {
-               dev_err(drm->dev, "failed to allocate buffer with size %u\n",
-                       size);
-               err = -ENOMEM;
-               goto err_dma;
-       }
-
-       err = drm_gem_object_init(drm, &bo->gem, size);
-       if (err)
-               goto err_init;
-
-       err = drm_gem_create_mmap_offset(&bo->gem);
-       if (err)
-               goto err_mmap;
-
-       return bo;
-
-err_mmap:
-       drm_gem_object_release(&bo->gem);
-err_init:
-       tegra_bo_destroy(drm, bo);
-err_dma:
-       kfree(bo);
-
-       return ERR_PTR(err);
-
-}
-
-struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
-                                            struct drm_device *drm,
-                                            unsigned int size,
-                                            unsigned int *handle)
-{
-       struct tegra_bo *bo;
-       int ret;
-
-       bo = tegra_bo_create(drm, size);
-       if (IS_ERR(bo))
-               return bo;
-
-       ret = drm_gem_handle_create(file, &bo->gem, handle);
-       if (ret)
-               goto err;
-
-       drm_gem_object_unreference_unlocked(&bo->gem);
-
-       return bo;
-
-err:
-       tegra_bo_free_object(&bo->gem);
-       return ERR_PTR(ret);
-}
-
-void tegra_bo_free_object(struct drm_gem_object *gem)
-{
-       struct tegra_bo *bo = to_tegra_bo(gem);
-
-       drm_gem_free_mmap_offset(gem);
-       drm_gem_object_release(gem);
-       tegra_bo_destroy(gem->dev, bo);
-
-       kfree(bo);
-}
-
-int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
-                        struct drm_mode_create_dumb *args)
-{
-       int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-       struct tegra_bo *bo;
-
-       if (args->pitch < min_pitch)
-               args->pitch = min_pitch;
-
-       if (args->size < args->pitch * args->height)
-               args->size = args->pitch * args->height;
-
-       bo = tegra_bo_create_with_handle(file, drm, args->size,
-                                        &args->handle);
-       if (IS_ERR(bo))
-               return PTR_ERR(bo);
-
-       return 0;
-}
-
-int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
-                            uint32_t handle, uint64_t *offset)
-{
-       struct drm_gem_object *gem;
-       struct tegra_bo *bo;
-
-       mutex_lock(&drm->struct_mutex);
-
-       gem = drm_gem_object_lookup(drm, file, handle);
-       if (!gem) {
-               dev_err(drm->dev, "failed to lookup GEM object\n");
-               mutex_unlock(&drm->struct_mutex);
-               return -EINVAL;
-       }
-
-       bo = to_tegra_bo(gem);
-
-       *offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
-
-       drm_gem_object_unreference(gem);
-
-       mutex_unlock(&drm->struct_mutex);
-
-       return 0;
-}
-
-const struct vm_operations_struct tegra_bo_vm_ops = {
-       .open = drm_gem_vm_open,
-       .close = drm_gem_vm_close,
-};
-
-int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct drm_gem_object *gem;
-       struct tegra_bo *bo;
-       int ret;
-
-       ret = drm_gem_mmap(file, vma);
-       if (ret)
-               return ret;
-
-       gem = vma->vm_private_data;
-       bo = to_tegra_bo(gem);
-
-       ret = remap_pfn_range(vma, vma->vm_start, bo->paddr >> PAGE_SHIFT,
-                             vma->vm_end - vma->vm_start, vma->vm_page_prot);
-       if (ret)
-               drm_gem_vm_close(vma);
-
-       return ret;
-}
diff --git a/drivers/gpu/host1x/drm/gem.h b/drivers/gpu/host1x/drm/gem.h
deleted file mode 100644 (file)
index 2b54f14..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Tegra host1x GEM implementation
- *
- * Copyright (c) 2012-2013, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __HOST1X_GEM_H
-#define __HOST1X_GEM_H
-
-#include <linux/host1x.h>
-
-#include <drm/drm.h>
-#include <drm/drmP.h>
-
-struct tegra_bo {
-       struct drm_gem_object gem;
-       struct host1x_bo base;
-       dma_addr_t paddr;
-       void *vaddr;
-};
-
-static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
-{
-       return container_of(gem, struct tegra_bo, gem);
-}
-
-extern const struct host1x_bo_ops tegra_bo_ops;
-
-struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size);
-struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
-                                           struct drm_device *drm,
-                                           unsigned int size,
-                                           unsigned int *handle);
-void tegra_bo_free_object(struct drm_gem_object *gem);
-int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
-                        struct drm_mode_create_dumb *args);
-int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
-                            uint32_t handle, uint64_t *offset);
-
-int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma);
-
-extern const struct vm_operations_struct tegra_bo_vm_ops;
-
-#endif
diff --git a/drivers/gpu/host1x/drm/gr2d.c b/drivers/gpu/host1x/drm/gr2d.c
deleted file mode 100644 (file)
index 4e407e3..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 2012-2013, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/clk.h>
-
-#include "drm.h"
-#include "gem.h"
-
-#define GR2D_NUM_REGS 0x4d
-
-struct gr2d {
-       struct tegra_drm_client client;
-       struct host1x_channel *channel;
-       struct clk *clk;
-
-       DECLARE_BITMAP(addr_regs, GR2D_NUM_REGS);
-};
-
-static inline struct gr2d *to_gr2d(struct tegra_drm_client *client)
-{
-       return container_of(client, struct gr2d, client);
-}
-
-static int gr2d_init(struct host1x_client *client)
-{
-       struct tegra_drm_client *drm = host1x_to_drm_client(client);
-       struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-       struct gr2d *gr2d = to_gr2d(drm);
-
-       gr2d->channel = host1x_channel_request(client->dev);
-       if (!gr2d->channel)
-               return -ENOMEM;
-
-       client->syncpts[0] = host1x_syncpt_request(client->dev, false);
-       if (!client->syncpts[0]) {
-               host1x_channel_free(gr2d->channel);
-               return -ENOMEM;
-       }
-
-       return tegra_drm_register_client(tegra, drm);
-}
-
-static int gr2d_exit(struct host1x_client *client)
-{
-       struct tegra_drm_client *drm = host1x_to_drm_client(client);
-       struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-       struct gr2d *gr2d = to_gr2d(drm);
-       int err;
-
-       err = tegra_drm_unregister_client(tegra, drm);
-       if (err < 0)
-               return err;
-
-       host1x_syncpt_free(client->syncpts[0]);
-       host1x_channel_free(gr2d->channel);
-
-       return 0;
-}
-
-static const struct host1x_client_ops gr2d_client_ops = {
-       .init = gr2d_init,
-       .exit = gr2d_exit,
-};
-
-static int gr2d_open_channel(struct tegra_drm_client *client,
-                            struct tegra_drm_context *context)
-{
-       struct gr2d *gr2d = to_gr2d(client);
-
-       context->channel = host1x_channel_get(gr2d->channel);
-       if (!context->channel)
-               return -ENOMEM;
-
-       return 0;
-}
-
-static void gr2d_close_channel(struct tegra_drm_context *context)
-{
-       host1x_channel_put(context->channel);
-}
-
-static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm,
-                                         struct drm_file *file,
-                                         u32 handle)
-{
-       struct drm_gem_object *gem;
-       struct tegra_bo *bo;
-
-       gem = drm_gem_object_lookup(drm, file, handle);
-       if (!gem)
-               return NULL;
-
-       mutex_lock(&drm->struct_mutex);
-       drm_gem_object_unreference(gem);
-       mutex_unlock(&drm->struct_mutex);
-
-       bo = to_tegra_bo(gem);
-       return &bo->base;
-}
-
-static int gr2d_is_addr_reg(struct device *dev, u32 class, u32 offset)
-{
-       struct gr2d *gr2d = dev_get_drvdata(dev);
-
-       switch (class) {
-       case HOST1X_CLASS_HOST1X:
-               if (offset == 0x2b)
-                       return 1;
-
-               break;
-
-       case HOST1X_CLASS_GR2D:
-       case HOST1X_CLASS_GR2D_SB:
-               if (offset >= GR2D_NUM_REGS)
-                       break;
-
-               if (test_bit(offset, gr2d->addr_regs))
-                       return 1;
-
-               break;
-       }
-
-       return 0;
-}
-
-static int gr2d_submit(struct tegra_drm_context *context,
-                      struct drm_tegra_submit *args, struct drm_device *drm,
-                      struct drm_file *file)
-{
-       unsigned int num_cmdbufs = args->num_cmdbufs;
-       unsigned int num_relocs = args->num_relocs;
-       unsigned int num_waitchks = args->num_waitchks;
-       struct drm_tegra_cmdbuf __user *cmdbufs =
-               (void * __user)(uintptr_t)args->cmdbufs;
-       struct drm_tegra_reloc __user *relocs =
-               (void * __user)(uintptr_t)args->relocs;
-       struct drm_tegra_waitchk __user *waitchks =
-               (void * __user)(uintptr_t)args->waitchks;
-       struct drm_tegra_syncpt syncpt;
-       struct host1x_job *job;
-       int err;
-
-       /* We don't yet support other than one syncpt_incr struct per submit */
-       if (args->num_syncpts != 1)
-               return -EINVAL;
-
-       job = host1x_job_alloc(context->channel, args->num_cmdbufs,
-                              args->num_relocs, args->num_waitchks);
-       if (!job)
-               return -ENOMEM;
-
-       job->num_relocs = args->num_relocs;
-       job->num_waitchk = args->num_waitchks;
-       job->client = (u32)args->context;
-       job->class = context->client->base.class;
-       job->serialize = true;
-
-       while (num_cmdbufs) {
-               struct drm_tegra_cmdbuf cmdbuf;
-               struct host1x_bo *bo;
-
-               err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf));
-               if (err)
-                       goto fail;
-
-               bo = host1x_bo_lookup(drm, file, cmdbuf.handle);
-               if (!bo) {
-                       err = -ENOENT;
-                       goto fail;
-               }
-
-               host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset);
-               num_cmdbufs--;
-               cmdbufs++;
-       }
-
-       err = copy_from_user(job->relocarray, relocs,
-                            sizeof(*relocs) * num_relocs);
-       if (err)
-               goto fail;
-
-       while (num_relocs--) {
-               struct host1x_reloc *reloc = &job->relocarray[num_relocs];
-               struct host1x_bo *cmdbuf, *target;
-
-               cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf);
-               target = host1x_bo_lookup(drm, file, (u32)reloc->target);
-
-               reloc->cmdbuf = cmdbuf;
-               reloc->target = target;
-
-               if (!reloc->target || !reloc->cmdbuf) {
-                       err = -ENOENT;
-                       goto fail;
-               }
-       }
-
-       err = copy_from_user(job->waitchk, waitchks,
-                            sizeof(*waitchks) * num_waitchks);
-       if (err)
-               goto fail;
-
-       err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts,
-                            sizeof(syncpt));
-       if (err)
-               goto fail;
-
-       job->syncpt_id = syncpt.id;
-       job->syncpt_incrs = syncpt.incrs;
-       job->timeout = 10000;
-       job->is_addr_reg = gr2d_is_addr_reg;
-
-       if (args->timeout && args->timeout < 10000)
-               job->timeout = args->timeout;
-
-       err = host1x_job_pin(job, context->client->base.dev);
-       if (err)
-               goto fail;
-
-       err = host1x_job_submit(job);
-       if (err)
-               goto fail_submit;
-
-       args->fence = job->syncpt_end;
-
-       host1x_job_put(job);
-       return 0;
-
-fail_submit:
-       host1x_job_unpin(job);
-fail:
-       host1x_job_put(job);
-       return err;
-}
-
-static const struct tegra_drm_client_ops gr2d_ops = {
-       .open_channel = gr2d_open_channel,
-       .close_channel = gr2d_close_channel,
-       .submit = gr2d_submit,
-};
-
-static const struct of_device_id gr2d_match[] = {
-       { .compatible = "nvidia,tegra30-gr2d" },
-       { .compatible = "nvidia,tegra20-gr2d" },
-       { },
-};
-
-static const u32 gr2d_addr_regs[] = {
-       0x1a, 0x1b, 0x26, 0x2b, 0x2c, 0x2d, 0x31, 0x32,
-       0x48, 0x49, 0x4a, 0x4b, 0x4c
-};
-
-static int gr2d_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct host1x_syncpt **syncpts;
-       struct gr2d *gr2d;
-       unsigned int i;
-       int err;
-
-       gr2d = devm_kzalloc(dev, sizeof(*gr2d), GFP_KERNEL);
-       if (!gr2d)
-               return -ENOMEM;
-
-       syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
-       if (!syncpts)
-               return -ENOMEM;
-
-       gr2d->clk = devm_clk_get(dev, NULL);
-       if (IS_ERR(gr2d->clk)) {
-               dev_err(dev, "cannot get clock\n");
-               return PTR_ERR(gr2d->clk);
-       }
-
-       err = clk_prepare_enable(gr2d->clk);
-       if (err) {
-               dev_err(dev, "cannot turn on clock\n");
-               return err;
-       }
-
-       INIT_LIST_HEAD(&gr2d->client.base.list);
-       gr2d->client.base.ops = &gr2d_client_ops;
-       gr2d->client.base.dev = dev;
-       gr2d->client.base.class = HOST1X_CLASS_GR2D;
-       gr2d->client.base.syncpts = syncpts;
-       gr2d->client.base.num_syncpts = 1;
-
-       INIT_LIST_HEAD(&gr2d->client.list);
-       gr2d->client.ops = &gr2d_ops;
-
-       err = host1x_client_register(&gr2d->client.base);
-       if (err < 0) {
-               dev_err(dev, "failed to register host1x client: %d\n", err);
-               return err;
-       }
-
-       /* initialize address register map */
-       for (i = 0; i < ARRAY_SIZE(gr2d_addr_regs); i++)
-               set_bit(gr2d_addr_regs[i], gr2d->addr_regs);
-
-       platform_set_drvdata(pdev, gr2d);
-
-       return 0;
-}
-
-static int gr2d_remove(struct platform_device *pdev)
-{
-       struct gr2d *gr2d = platform_get_drvdata(pdev);
-       int err;
-
-       err = host1x_client_unregister(&gr2d->client.base);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
-                       err);
-               return err;
-       }
-
-       clk_disable_unprepare(gr2d->clk);
-
-       return 0;
-}
-
-struct platform_driver tegra_gr2d_driver = {
-       .driver = {
-               .name = "tegra-gr2d",
-               .of_match_table = gr2d_match,
-       },
-       .probe = gr2d_probe,
-       .remove = gr2d_remove,
-};
diff --git a/drivers/gpu/host1x/drm/hdmi.c b/drivers/gpu/host1x/drm/hdmi.c
deleted file mode 100644 (file)
index f5663d1..0000000
+++ /dev/null
@@ -1,1295 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/clk/tegra.h>
-#include <linux/debugfs.h>
-#include <linux/hdmi.h>
-#include <linux/regulator/consumer.h>
-
-#include "hdmi.h"
-#include "drm.h"
-#include "dc.h"
-
-struct tegra_hdmi {
-       struct host1x_client client;
-       struct tegra_output output;
-       struct device *dev;
-
-       struct regulator *vdd;
-       struct regulator *pll;
-
-       void __iomem *regs;
-       unsigned int irq;
-
-       struct clk *clk_parent;
-       struct clk *clk;
-
-       unsigned int audio_source;
-       unsigned int audio_freq;
-       bool stereo;
-       bool dvi;
-
-       struct drm_info_list *debugfs_files;
-       struct drm_minor *minor;
-       struct dentry *debugfs;
-};
-
-static inline struct tegra_hdmi *
-host1x_client_to_hdmi(struct host1x_client *client)
-{
-       return container_of(client, struct tegra_hdmi, client);
-}
-
-static inline struct tegra_hdmi *to_hdmi(struct tegra_output *output)
-{
-       return container_of(output, struct tegra_hdmi, output);
-}
-
-#define HDMI_AUDIOCLK_FREQ 216000000
-#define HDMI_REKEY_DEFAULT 56
-
-enum {
-       AUTO = 0,
-       SPDIF,
-       HDA,
-};
-
-static inline unsigned long tegra_hdmi_readl(struct tegra_hdmi *hdmi,
-                                            unsigned long reg)
-{
-       return readl(hdmi->regs + (reg << 2));
-}
-
-static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, unsigned long val,
-                                    unsigned long reg)
-{
-       writel(val, hdmi->regs + (reg << 2));
-}
-
-struct tegra_hdmi_audio_config {
-       unsigned int pclk;
-       unsigned int n;
-       unsigned int cts;
-       unsigned int aval;
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
-       {  25200000, 4096,  25200, 24000 },
-       {  27000000, 4096,  27000, 24000 },
-       {  74250000, 4096,  74250, 24000 },
-       { 148500000, 4096, 148500, 24000 },
-       {         0,    0,      0,     0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
-       {  25200000, 5880,  26250, 25000 },
-       {  27000000, 5880,  28125, 25000 },
-       {  74250000, 4704,  61875, 20000 },
-       { 148500000, 4704, 123750, 20000 },
-       {         0,    0,      0,     0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
-       {  25200000, 6144,  25200, 24000 },
-       {  27000000, 6144,  27000, 24000 },
-       {  74250000, 6144,  74250, 24000 },
-       { 148500000, 6144, 148500, 24000 },
-       {         0,    0,      0,     0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
-       {  25200000, 11760,  26250, 25000 },
-       {  27000000, 11760,  28125, 25000 },
-       {  74250000,  9408,  61875, 20000 },
-       { 148500000,  9408, 123750, 20000 },
-       {         0,     0,      0,     0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
-       {  25200000, 12288,  25200, 24000 },
-       {  27000000, 12288,  27000, 24000 },
-       {  74250000, 12288,  74250, 24000 },
-       { 148500000, 12288, 148500, 24000 },
-       {         0,     0,      0,     0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
-       {  25200000, 23520,  26250, 25000 },
-       {  27000000, 23520,  28125, 25000 },
-       {  74250000, 18816,  61875, 20000 },
-       { 148500000, 18816, 123750, 20000 },
-       {         0,     0,      0,     0 },
-};
-
-static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
-       {  25200000, 24576,  25200, 24000 },
-       {  27000000, 24576,  27000, 24000 },
-       {  74250000, 24576,  74250, 24000 },
-       { 148500000, 24576, 148500, 24000 },
-       {         0,     0,      0,     0 },
-};
-
-struct tmds_config {
-       unsigned int pclk;
-       u32 pll0;
-       u32 pll1;
-       u32 pe_current;
-       u32 drive_current;
-};
-
-static const struct tmds_config tegra2_tmds_config[] = {
-       { /* slow pixel clock modes */
-               .pclk = 27000000,
-               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
-                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
-                       SOR_PLL_TX_REG_LOAD(3),
-               .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
-               .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
-                       PE_CURRENT1(PE_CURRENT_0_0_mA) |
-                       PE_CURRENT2(PE_CURRENT_0_0_mA) |
-                       PE_CURRENT3(PE_CURRENT_0_0_mA),
-               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
-                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
-                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
-                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
-       },
-       { /* high pixel clock modes */
-               .pclk = UINT_MAX,
-               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
-                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
-                       SOR_PLL_TX_REG_LOAD(3),
-               .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
-               .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
-                       PE_CURRENT1(PE_CURRENT_6_0_mA) |
-                       PE_CURRENT2(PE_CURRENT_6_0_mA) |
-                       PE_CURRENT3(PE_CURRENT_6_0_mA),
-               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
-                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
-                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
-                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
-       },
-};
-
-static const struct tmds_config tegra3_tmds_config[] = {
-       { /* 480p modes */
-               .pclk = 27000000,
-               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
-                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) |
-                       SOR_PLL_TX_REG_LOAD(0),
-               .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
-               .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
-                       PE_CURRENT1(PE_CURRENT_0_0_mA) |
-                       PE_CURRENT2(PE_CURRENT_0_0_mA) |
-                       PE_CURRENT3(PE_CURRENT_0_0_mA),
-               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
-                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
-                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
-                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
-       }, { /* 720p modes */
-               .pclk = 74250000,
-               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
-                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) |
-                       SOR_PLL_TX_REG_LOAD(0),
-               .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
-               .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
-                       PE_CURRENT1(PE_CURRENT_5_0_mA) |
-                       PE_CURRENT2(PE_CURRENT_5_0_mA) |
-                       PE_CURRENT3(PE_CURRENT_5_0_mA),
-               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
-                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
-                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
-                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
-       }, { /* 1080p modes */
-               .pclk = UINT_MAX,
-               .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) |
-                       SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(3) |
-                       SOR_PLL_TX_REG_LOAD(0),
-               .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
-               .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
-                       PE_CURRENT1(PE_CURRENT_5_0_mA) |
-                       PE_CURRENT2(PE_CURRENT_5_0_mA) |
-                       PE_CURRENT3(PE_CURRENT_5_0_mA),
-               .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
-                       DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
-                       DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
-                       DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
-       },
-};
-
-static const struct tegra_hdmi_audio_config *
-tegra_hdmi_get_audio_config(unsigned int audio_freq, unsigned int pclk)
-{
-       const struct tegra_hdmi_audio_config *table;
-
-       switch (audio_freq) {
-       case 32000:
-               table = tegra_hdmi_audio_32k;
-               break;
-
-       case 44100:
-               table = tegra_hdmi_audio_44_1k;
-               break;
-
-       case 48000:
-               table = tegra_hdmi_audio_48k;
-               break;
-
-       case 88200:
-               table = tegra_hdmi_audio_88_2k;
-               break;
-
-       case 96000:
-               table = tegra_hdmi_audio_96k;
-               break;
-
-       case 176400:
-               table = tegra_hdmi_audio_176_4k;
-               break;
-
-       case 192000:
-               table = tegra_hdmi_audio_192k;
-               break;
-
-       default:
-               return NULL;
-       }
-
-       while (table->pclk) {
-               if (table->pclk == pclk)
-                       return table;
-
-               table++;
-       }
-
-       return NULL;
-}
-
-static void tegra_hdmi_setup_audio_fs_tables(struct tegra_hdmi *hdmi)
-{
-       const unsigned int freqs[] = {
-               32000, 44100, 48000, 88200, 96000, 176400, 192000
-       };
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(freqs); i++) {
-               unsigned int f = freqs[i];
-               unsigned int eight_half;
-               unsigned long value;
-               unsigned int delta;
-
-               if (f > 96000)
-                       delta = 2;
-               else if (f > 480000)
-                       delta = 6;
-               else
-                       delta = 9;
-
-               eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
-               value = AUDIO_FS_LOW(eight_half - delta) |
-                       AUDIO_FS_HIGH(eight_half + delta);
-               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_FS(i));
-       }
-}
-
-static int tegra_hdmi_setup_audio(struct tegra_hdmi *hdmi, unsigned int pclk)
-{
-       struct device_node *node = hdmi->dev->of_node;
-       const struct tegra_hdmi_audio_config *config;
-       unsigned int offset = 0;
-       unsigned long value;
-
-       switch (hdmi->audio_source) {
-       case HDA:
-               value = AUDIO_CNTRL0_SOURCE_SELECT_HDAL;
-               break;
-
-       case SPDIF:
-               value = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF;
-               break;
-
-       default:
-               value = AUDIO_CNTRL0_SOURCE_SELECT_AUTO;
-               break;
-       }
-
-       if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
-               value |= AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
-                        AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
-               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
-       } else {
-               value |= AUDIO_CNTRL0_INJECT_NULLSMPL;
-               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
-
-               value = AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
-                       AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0);
-               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_CNTRL0);
-       }
-
-       config = tegra_hdmi_get_audio_config(hdmi->audio_freq, pclk);
-       if (!config) {
-               dev_err(hdmi->dev, "cannot set audio to %u at %u pclk\n",
-                       hdmi->audio_freq, pclk);
-               return -EINVAL;
-       }
-
-       tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
-
-       value = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNATE |
-               AUDIO_N_VALUE(config->n - 1);
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
-
-       tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
-                         HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
-
-       value = ACR_SUBPACK_CTS(config->cts);
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
-
-       value = SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1);
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_SPARE);
-
-       value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_AUDIO_N);
-       value &= ~AUDIO_N_RESETF;
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_AUDIO_N);
-
-       if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
-               switch (hdmi->audio_freq) {
-               case 32000:
-                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320;
-                       break;
-
-               case 44100:
-                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441;
-                       break;
-
-               case 48000:
-                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480;
-                       break;
-
-               case 88200:
-                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882;
-                       break;
-
-               case 96000:
-                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960;
-                       break;
-
-               case 176400:
-                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764;
-                       break;
-
-               case 192000:
-                       offset = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920;
-                       break;
-               }
-
-               tegra_hdmi_writel(hdmi, config->aval, offset);
-       }
-
-       tegra_hdmi_setup_audio_fs_tables(hdmi);
-
-       return 0;
-}
-
-static inline unsigned long tegra_hdmi_subpack(const u8 *ptr, size_t size)
-{
-       unsigned long value = 0;
-       size_t i;
-
-       for (i = size; i > 0; i--)
-               value = (value << 8) | ptr[i - 1];
-
-       return value;
-}
-
-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;
-
-       switch (ptr[0]) {
-       case HDMI_INFOFRAME_TYPE_AVI:
-               offset = HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER;
-               break;
-
-       case HDMI_INFOFRAME_TYPE_AUDIO:
-               offset = HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER;
-               break;
-
-       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;
-       }
-
-       value = INFOFRAME_HEADER_TYPE(ptr[0]) |
-               INFOFRAME_HEADER_VERSION(ptr[1]) |
-               INFOFRAME_HEADER_LEN(ptr[2]);
-       tegra_hdmi_writel(hdmi, value, offset);
-       offset++;
-
-       /*
-        * 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);
-
-               value = tegra_hdmi_subpack(&ptr[i], num);
-               tegra_hdmi_writel(hdmi, value, offset++);
-
-               num = min_t(size_t, rem - num, 3);
-
-               value = tegra_hdmi_subpack(&ptr[i + 4], num);
-               tegra_hdmi_writel(hdmi, value, offset++);
-       }
-}
-
-static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
-                                          struct drm_display_mode *mode)
-{
-       struct hdmi_avi_infoframe frame;
-       u8 buffer[17];
-       ssize_t err;
-
-       if (hdmi->dvi) {
-               tegra_hdmi_writel(hdmi, 0,
-                                 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
-               return;
-       }
-
-       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;
-       }
-
-       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, 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,
-                                 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
-               return;
-       }
-
-       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;
-       }
-
-       /*
-        * 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_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);
-               value &= ~GENERIC_CTRL_ENABLE;
-               tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
-               return;
-       }
-
-       hdmi_vendor_infoframe_init(&frame);
-       frame.s3d_struct = HDMI_3D_STRUCTURE_FRAME_PACKING;
-
-       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, buffer, err);
-
-       value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
-       value |= GENERIC_CTRL_ENABLE;
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
-}
-
-static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
-                                 const struct tmds_config *tmds)
-{
-       unsigned long value;
-
-       tegra_hdmi_writel(hdmi, tmds->pll0, HDMI_NV_PDISP_SOR_PLL0);
-       tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
-       tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
-
-       value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
-}
-
-static int tegra_output_hdmi_enable(struct tegra_output *output)
-{
-       unsigned int h_sync_width, h_front_porch, h_back_porch, i, rekey;
-       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
-       struct drm_display_mode *mode = &dc->base.mode;
-       struct tegra_hdmi *hdmi = to_hdmi(output);
-       struct device_node *node = hdmi->dev->of_node;
-       unsigned int pulse_start, div82, pclk;
-       const struct tmds_config *tmds;
-       unsigned int num_tmds;
-       unsigned long value;
-       int retries = 1000;
-       int err;
-
-       pclk = mode->clock * 1000;
-       h_sync_width = mode->hsync_end - mode->hsync_start;
-       h_back_porch = mode->htotal - mode->hsync_end;
-       h_front_porch = mode->hsync_start - mode->hdisplay;
-
-       err = regulator_enable(hdmi->vdd);
-       if (err < 0) {
-               dev_err(hdmi->dev, "failed to enable VDD regulator: %d\n", err);
-               return err;
-       }
-
-       err = regulator_enable(hdmi->pll);
-       if (err < 0) {
-               dev_err(hdmi->dev, "failed to enable PLL regulator: %d\n", err);
-               return err;
-       }
-
-       /*
-        * This assumes that the display controller will divide its parent
-        * clock by 2 to generate the pixel clock.
-        */
-       err = tegra_output_setup_clock(output, hdmi->clk, pclk * 2);
-       if (err < 0) {
-               dev_err(hdmi->dev, "failed to setup clock: %d\n", err);
-               return err;
-       }
-
-       err = clk_set_rate(hdmi->clk, pclk);
-       if (err < 0)
-               return err;
-
-       err = clk_enable(hdmi->clk);
-       if (err < 0) {
-               dev_err(hdmi->dev, "failed to enable clock: %d\n", err);
-               return err;
-       }
-
-       tegra_periph_reset_assert(hdmi->clk);
-       usleep_range(1000, 2000);
-       tegra_periph_reset_deassert(hdmi->clk);
-
-       tegra_dc_writel(dc, VSYNC_H_POSITION(1),
-                       DC_DISP_DISP_TIMING_OPTIONS);
-       tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
-                       DC_DISP_DISP_COLOR_CONTROL);
-
-       /* video_preamble uses h_pulse2 */
-       pulse_start = 1 + h_sync_width + h_back_porch - 10;
-
-       tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
-
-       value = PULSE_MODE_NORMAL | PULSE_POLARITY_HIGH | PULSE_QUAL_VACTIVE |
-               PULSE_LAST_END_A;
-       tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
-
-       value = PULSE_START(pulse_start) | PULSE_END(pulse_start + 8);
-       tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
-
-       value = VSYNC_WINDOW_END(0x210) | VSYNC_WINDOW_START(0x200) |
-               VSYNC_WINDOW_ENABLE;
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
-
-       if (dc->pipe)
-               value = HDMI_SRC_DISPLAYB;
-       else
-               value = HDMI_SRC_DISPLAYA;
-
-       if ((mode->hdisplay == 720) && ((mode->vdisplay == 480) ||
-                                       (mode->vdisplay == 576)))
-               tegra_hdmi_writel(hdmi,
-                                 value | ARM_VIDEO_RANGE_FULL,
-                                 HDMI_NV_PDISP_INPUT_CONTROL);
-       else
-               tegra_hdmi_writel(hdmi,
-                                 value | ARM_VIDEO_RANGE_LIMITED,
-                                 HDMI_NV_PDISP_INPUT_CONTROL);
-
-       div82 = clk_get_rate(hdmi->clk) / 1000000 * 4;
-       value = SOR_REFCLK_DIV_INT(div82 >> 2) | SOR_REFCLK_DIV_FRAC(div82);
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_REFCLK);
-
-       if (!hdmi->dvi) {
-               err = tegra_hdmi_setup_audio(hdmi, pclk);
-               if (err < 0)
-                       hdmi->dvi = true;
-       }
-
-       if (of_device_is_compatible(node, "nvidia,tegra20-hdmi")) {
-               /*
-                * TODO: add ELD support
-                */
-       }
-
-       rekey = HDMI_REKEY_DEFAULT;
-       value = HDMI_CTRL_REKEY(rekey);
-       value |= HDMI_CTRL_MAX_AC_PACKET((h_sync_width + h_back_porch +
-                                         h_front_porch - rekey - 18) / 32);
-
-       if (!hdmi->dvi)
-               value |= HDMI_CTRL_ENABLE;
-
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_CTRL);
-
-       if (hdmi->dvi)
-               tegra_hdmi_writel(hdmi, 0x0,
-                                 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
-       else
-               tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
-                                 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
-
-       tegra_hdmi_setup_avi_infoframe(hdmi, mode);
-       tegra_hdmi_setup_audio_infoframe(hdmi);
-       tegra_hdmi_setup_stereo_infoframe(hdmi);
-
-       /* TMDS CONFIG */
-       if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
-               num_tmds = ARRAY_SIZE(tegra3_tmds_config);
-               tmds = tegra3_tmds_config;
-       } else {
-               num_tmds = ARRAY_SIZE(tegra2_tmds_config);
-               tmds = tegra2_tmds_config;
-       }
-
-       for (i = 0; i < num_tmds; i++) {
-               if (pclk <= tmds[i].pclk) {
-                       tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
-                       break;
-               }
-       }
-
-       tegra_hdmi_writel(hdmi,
-                         SOR_SEQ_CTL_PU_PC(0) |
-                         SOR_SEQ_PU_PC_ALT(0) |
-                         SOR_SEQ_PD_PC(8) |
-                         SOR_SEQ_PD_PC_ALT(8),
-                         HDMI_NV_PDISP_SOR_SEQ_CTL);
-
-       value = SOR_SEQ_INST_WAIT_TIME(1) |
-               SOR_SEQ_INST_WAIT_UNITS_VSYNC |
-               SOR_SEQ_INST_HALT |
-               SOR_SEQ_INST_PIN_A_LOW |
-               SOR_SEQ_INST_PIN_B_LOW |
-               SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
-
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(0));
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_SEQ_INST(8));
-
-       value = 0x1c800;
-       value &= ~SOR_CSTM_ROTCLK(~0);
-       value |= SOR_CSTM_ROTCLK(2);
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM);
-
-       tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
-       tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
-       tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
-
-       /* start SOR */
-       tegra_hdmi_writel(hdmi,
-                         SOR_PWR_NORMAL_STATE_PU |
-                         SOR_PWR_NORMAL_START_NORMAL |
-                         SOR_PWR_SAFE_STATE_PD |
-                         SOR_PWR_SETTING_NEW_TRIGGER,
-                         HDMI_NV_PDISP_SOR_PWR);
-       tegra_hdmi_writel(hdmi,
-                         SOR_PWR_NORMAL_STATE_PU |
-                         SOR_PWR_NORMAL_START_NORMAL |
-                         SOR_PWR_SAFE_STATE_PD |
-                         SOR_PWR_SETTING_NEW_DONE,
-                         HDMI_NV_PDISP_SOR_PWR);
-
-       do {
-               BUG_ON(--retries < 0);
-               value = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR);
-       } while (value & SOR_PWR_SETTING_NEW_PENDING);
-
-       value = SOR_STATE_ASY_CRCMODE_COMPLETE |
-               SOR_STATE_ASY_OWNER_HEAD0 |
-               SOR_STATE_ASY_SUBOWNER_BOTH |
-               SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
-               SOR_STATE_ASY_DEPOL_POS;
-
-       /* setup sync polarities */
-       if (mode->flags & DRM_MODE_FLAG_PHSYNC)
-               value |= SOR_STATE_ASY_HSYNCPOL_POS;
-
-       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
-               value |= SOR_STATE_ASY_HSYNCPOL_NEG;
-
-       if (mode->flags & DRM_MODE_FLAG_PVSYNC)
-               value |= SOR_STATE_ASY_VSYNCPOL_POS;
-
-       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-               value |= SOR_STATE_ASY_VSYNCPOL_NEG;
-
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE2);
-
-       value = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_STATE1);
-
-       tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
-       tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0);
-       tegra_hdmi_writel(hdmi, value | SOR_STATE_ATTACHED,
-                         HDMI_NV_PDISP_SOR_STATE1);
-       tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
-
-       tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
-
-       value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
-               PW4_ENABLE | PM0_ENABLE | PM1_ENABLE;
-       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
-
-       value = DISP_CTRL_MODE_C_DISPLAY;
-       tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
-
-       tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
-       tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
-
-       /* TODO: add HDCP support */
-
-       return 0;
-}
-
-static int tegra_output_hdmi_disable(struct tegra_output *output)
-{
-       struct tegra_hdmi *hdmi = to_hdmi(output);
-
-       tegra_periph_reset_assert(hdmi->clk);
-       clk_disable(hdmi->clk);
-       regulator_disable(hdmi->pll);
-       regulator_disable(hdmi->vdd);
-
-       return 0;
-}
-
-static int tegra_output_hdmi_setup_clock(struct tegra_output *output,
-                                        struct clk *clk, unsigned long pclk)
-{
-       struct tegra_hdmi *hdmi = to_hdmi(output);
-       struct clk *base;
-       int err;
-
-       err = clk_set_parent(clk, hdmi->clk_parent);
-       if (err < 0) {
-               dev_err(output->dev, "failed to set parent: %d\n", err);
-               return err;
-       }
-
-       base = clk_get_parent(hdmi->clk_parent);
-
-       /*
-        * This assumes that the parent clock is pll_d_out0 or pll_d2_out
-        * respectively, each of which divides the base pll_d by 2.
-        */
-       err = clk_set_rate(base, pclk * 2);
-       if (err < 0)
-               dev_err(output->dev,
-                       "failed to set base clock rate to %lu Hz\n",
-                       pclk * 2);
-
-       return 0;
-}
-
-static int tegra_output_hdmi_check_mode(struct tegra_output *output,
-                                       struct drm_display_mode *mode,
-                                       enum drm_mode_status *status)
-{
-       struct tegra_hdmi *hdmi = to_hdmi(output);
-       unsigned long pclk = mode->clock * 1000;
-       struct clk *parent;
-       long err;
-
-       parent = clk_get_parent(hdmi->clk_parent);
-
-       err = clk_round_rate(parent, pclk * 4);
-       if (err < 0)
-               *status = MODE_NOCLOCK;
-       else
-               *status = MODE_OK;
-
-       return 0;
-}
-
-static const struct tegra_output_ops hdmi_ops = {
-       .enable = tegra_output_hdmi_enable,
-       .disable = tegra_output_hdmi_disable,
-       .setup_clock = tegra_output_hdmi_setup_clock,
-       .check_mode = tegra_output_hdmi_check_mode,
-};
-
-static int tegra_hdmi_show_regs(struct seq_file *s, void *data)
-{
-       struct drm_info_node *node = s->private;
-       struct tegra_hdmi *hdmi = node->info_ent->data;
-       int err;
-
-       err = clk_enable(hdmi->clk);
-       if (err)
-               return err;
-
-#define DUMP_REG(name)                                         \
-       seq_printf(s, "%-56s %#05x %08lx\n", #name, name,       \
-               tegra_hdmi_readl(hdmi, name))
-
-       DUMP_REG(HDMI_CTXSW);
-       DUMP_REG(HDMI_NV_PDISP_SOR_STATE0);
-       DUMP_REG(HDMI_NV_PDISP_SOR_STATE1);
-       DUMP_REG(HDMI_NV_PDISP_SOR_STATE2);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB);
-       DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2);
-       DUMP_REG(HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL);
-       DUMP_REG(HDMI_NV_PDISP_SOR_CAP);
-       DUMP_REG(HDMI_NV_PDISP_SOR_PWR);
-       DUMP_REG(HDMI_NV_PDISP_SOR_TEST);
-       DUMP_REG(HDMI_NV_PDISP_SOR_PLL0);
-       DUMP_REG(HDMI_NV_PDISP_SOR_PLL1);
-       DUMP_REG(HDMI_NV_PDISP_SOR_PLL2);
-       DUMP_REG(HDMI_NV_PDISP_SOR_CSTM);
-       DUMP_REG(HDMI_NV_PDISP_SOR_LVDS);
-       DUMP_REG(HDMI_NV_PDISP_SOR_CRCA);
-       DUMP_REG(HDMI_NV_PDISP_SOR_CRCB);
-       DUMP_REG(HDMI_NV_PDISP_SOR_BLANK);
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL);
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(0));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(1));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(2));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(3));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(4));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(5));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(6));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(7));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(8));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(9));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(10));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(11));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(12));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(13));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(14));
-       DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST(15));
-       DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0);
-       DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1);
-       DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0);
-       DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1);
-       DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0);
-       DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1);
-       DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0);
-       DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1);
-       DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0);
-       DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1);
-       DUMP_REG(HDMI_NV_PDISP_SOR_TRIG);
-       DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK);
-       DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
-       DUMP_REG(HDMI_NV_PDISP_AUDIO_N);
-       DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING);
-       DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK);
-       DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL);
-       DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL);
-       DUMP_REG(HDMI_NV_PDISP_SCRATCH);
-       DUMP_REG(HDMI_NV_PDISP_PE_CURRENT);
-       DUMP_REG(HDMI_NV_PDISP_KEY_CTRL);
-       DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0);
-       DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1);
-       DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2);
-       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0);
-       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1);
-       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2);
-       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3);
-       DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
-       DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX);
-       DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_CNTRL0);
-       DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
-       DUMP_REG(HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
-
-#undef DUMP_REG
-
-       clk_disable(hdmi->clk);
-
-       return 0;
-}
-
-static struct drm_info_list debugfs_files[] = {
-       { "regs", tegra_hdmi_show_regs, 0, NULL },
-};
-
-static int tegra_hdmi_debugfs_init(struct tegra_hdmi *hdmi,
-                                  struct drm_minor *minor)
-{
-       unsigned int i;
-       int err;
-
-       hdmi->debugfs = debugfs_create_dir("hdmi", minor->debugfs_root);
-       if (!hdmi->debugfs)
-               return -ENOMEM;
-
-       hdmi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
-                                     GFP_KERNEL);
-       if (!hdmi->debugfs_files) {
-               err = -ENOMEM;
-               goto remove;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
-               hdmi->debugfs_files[i].data = hdmi;
-
-       err = drm_debugfs_create_files(hdmi->debugfs_files,
-                                      ARRAY_SIZE(debugfs_files),
-                                      hdmi->debugfs, minor);
-       if (err < 0)
-               goto free;
-
-       hdmi->minor = minor;
-
-       return 0;
-
-free:
-       kfree(hdmi->debugfs_files);
-       hdmi->debugfs_files = NULL;
-remove:
-       debugfs_remove(hdmi->debugfs);
-       hdmi->debugfs = NULL;
-
-       return err;
-}
-
-static int tegra_hdmi_debugfs_exit(struct tegra_hdmi *hdmi)
-{
-       drm_debugfs_remove_files(hdmi->debugfs_files, ARRAY_SIZE(debugfs_files),
-                                hdmi->minor);
-       hdmi->minor = NULL;
-
-       kfree(hdmi->debugfs_files);
-       hdmi->debugfs_files = NULL;
-
-       debugfs_remove(hdmi->debugfs);
-       hdmi->debugfs = NULL;
-
-       return 0;
-}
-
-static int tegra_hdmi_init(struct host1x_client *client)
-{
-       struct tegra_drm *tegra = dev_get_drvdata(client->parent);
-       struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
-       int err;
-
-       hdmi->output.type = TEGRA_OUTPUT_HDMI;
-       hdmi->output.dev = client->dev;
-       hdmi->output.ops = &hdmi_ops;
-
-       err = tegra_output_init(tegra->drm, &hdmi->output);
-       if (err < 0) {
-               dev_err(client->dev, "output setup failed: %d\n", err);
-               return err;
-       }
-
-       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-               err = tegra_hdmi_debugfs_init(hdmi, tegra->drm->primary);
-               if (err < 0)
-                       dev_err(client->dev, "debugfs setup failed: %d\n", err);
-       }
-
-       return 0;
-}
-
-static int tegra_hdmi_exit(struct host1x_client *client)
-{
-       struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
-       int err;
-
-       if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-               err = tegra_hdmi_debugfs_exit(hdmi);
-               if (err < 0)
-                       dev_err(client->dev, "debugfs cleanup failed: %d\n",
-                               err);
-       }
-
-       err = tegra_output_disable(&hdmi->output);
-       if (err < 0) {
-               dev_err(client->dev, "output failed to disable: %d\n", err);
-               return err;
-       }
-
-       err = tegra_output_exit(&hdmi->output);
-       if (err < 0) {
-               dev_err(client->dev, "output cleanup failed: %d\n", err);
-               return err;
-       }
-
-       return 0;
-}
-
-static const struct host1x_client_ops hdmi_client_ops = {
-       .init = tegra_hdmi_init,
-       .exit = tegra_hdmi_exit,
-};
-
-static int tegra_hdmi_probe(struct platform_device *pdev)
-{
-       struct tegra_hdmi *hdmi;
-       struct resource *regs;
-       int err;
-
-       hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
-       if (!hdmi)
-               return -ENOMEM;
-
-       hdmi->dev = &pdev->dev;
-       hdmi->audio_source = AUTO;
-       hdmi->audio_freq = 44100;
-       hdmi->stereo = false;
-       hdmi->dvi = false;
-
-       hdmi->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(hdmi->clk)) {
-               dev_err(&pdev->dev, "failed to get clock\n");
-               return PTR_ERR(hdmi->clk);
-       }
-
-       err = clk_prepare(hdmi->clk);
-       if (err < 0)
-               return err;
-
-       hdmi->clk_parent = devm_clk_get(&pdev->dev, "parent");
-       if (IS_ERR(hdmi->clk_parent))
-               return PTR_ERR(hdmi->clk_parent);
-
-       err = clk_prepare(hdmi->clk_parent);
-       if (err < 0)
-               return err;
-
-       err = clk_set_parent(hdmi->clk, hdmi->clk_parent);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to setup clocks: %d\n", err);
-               return err;
-       }
-
-       hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
-       if (IS_ERR(hdmi->vdd)) {
-               dev_err(&pdev->dev, "failed to get VDD regulator\n");
-               return PTR_ERR(hdmi->vdd);
-       }
-
-       hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
-       if (IS_ERR(hdmi->pll)) {
-               dev_err(&pdev->dev, "failed to get PLL regulator\n");
-               return PTR_ERR(hdmi->pll);
-       }
-
-       hdmi->output.dev = &pdev->dev;
-
-       err = tegra_output_parse_dt(&hdmi->output);
-       if (err < 0)
-               return err;
-
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!regs)
-               return -ENXIO;
-
-       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)
-               return err;
-
-       hdmi->irq = err;
-
-       INIT_LIST_HEAD(&hdmi->client.list);
-       hdmi->client.ops = &hdmi_client_ops;
-       hdmi->client.dev = &pdev->dev;
-
-       err = host1x_client_register(&hdmi->client);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to register host1x client: %d\n",
-                       err);
-               return err;
-       }
-
-       platform_set_drvdata(pdev, hdmi);
-
-       return 0;
-}
-
-static int tegra_hdmi_remove(struct platform_device *pdev)
-{
-       struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
-       int err;
-
-       err = host1x_client_unregister(&hdmi->client);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
-                       err);
-               return err;
-       }
-
-       clk_unprepare(hdmi->clk_parent);
-       clk_unprepare(hdmi->clk);
-
-       return 0;
-}
-
-static struct of_device_id tegra_hdmi_of_match[] = {
-       { .compatible = "nvidia,tegra30-hdmi", },
-       { .compatible = "nvidia,tegra20-hdmi", },
-       { },
-};
-
-struct platform_driver tegra_hdmi_driver = {
-       .driver = {
-               .name = "tegra-hdmi",
-               .owner = THIS_MODULE,
-               .of_match_table = tegra_hdmi_of_match,
-       },
-       .probe = tegra_hdmi_probe,
-       .remove = tegra_hdmi_remove,
-};
diff --git a/drivers/gpu/host1x/drm/hdmi.h b/drivers/gpu/host1x/drm/hdmi.h
deleted file mode 100644 (file)
index 52ac36e..0000000
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef TEGRA_HDMI_H
-#define TEGRA_HDMI_H 1
-
-/* register definitions */
-#define HDMI_CTXSW                                             0x00
-
-#define HDMI_NV_PDISP_SOR_STATE0                               0x01
-#define SOR_STATE_UPDATE (1 << 0)
-
-#define HDMI_NV_PDISP_SOR_STATE1                               0x02
-#define SOR_STATE_ASY_HEAD_OPMODE_AWAKE (2 << 0)
-#define SOR_STATE_ASY_ORMODE_NORMAL     (1 << 2)
-#define SOR_STATE_ATTACHED              (1 << 3)
-
-#define HDMI_NV_PDISP_SOR_STATE2                               0x03
-#define SOR_STATE_ASY_OWNER_NONE         (0 <<  0)
-#define SOR_STATE_ASY_OWNER_HEAD0        (1 <<  0)
-#define SOR_STATE_ASY_SUBOWNER_NONE      (0 <<  4)
-#define SOR_STATE_ASY_SUBOWNER_SUBHEAD0  (1 <<  4)
-#define SOR_STATE_ASY_SUBOWNER_SUBHEAD1  (2 <<  4)
-#define SOR_STATE_ASY_SUBOWNER_BOTH      (3 <<  4)
-#define SOR_STATE_ASY_CRCMODE_ACTIVE     (0 <<  6)
-#define SOR_STATE_ASY_CRCMODE_COMPLETE   (1 <<  6)
-#define SOR_STATE_ASY_CRCMODE_NON_ACTIVE (2 <<  6)
-#define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (1 << 8)
-#define SOR_STATE_ASY_PROTOCOL_CUSTOM        (15 << 8)
-#define SOR_STATE_ASY_HSYNCPOL_POS       (0 << 12)
-#define SOR_STATE_ASY_HSYNCPOL_NEG       (1 << 12)
-#define SOR_STATE_ASY_VSYNCPOL_POS       (0 << 13)
-#define SOR_STATE_ASY_VSYNCPOL_NEG       (1 << 13)
-#define SOR_STATE_ASY_DEPOL_POS          (0 << 14)
-#define SOR_STATE_ASY_DEPOL_NEG          (1 << 14)
-
-#define HDMI_NV_PDISP_RG_HDCP_AN_MSB                           0x04
-#define HDMI_NV_PDISP_RG_HDCP_AN_LSB                           0x05
-#define HDMI_NV_PDISP_RG_HDCP_CN_MSB                           0x06
-#define HDMI_NV_PDISP_RG_HDCP_CN_LSB                           0x07
-#define HDMI_NV_PDISP_RG_HDCP_AKSV_MSB                         0x08
-#define HDMI_NV_PDISP_RG_HDCP_AKSV_LSB                         0x09
-#define HDMI_NV_PDISP_RG_HDCP_BKSV_MSB                         0x0a
-#define HDMI_NV_PDISP_RG_HDCP_BKSV_LSB                         0x0b
-#define HDMI_NV_PDISP_RG_HDCP_CKSV_MSB                         0x0c
-#define HDMI_NV_PDISP_RG_HDCP_CKSV_LSB                         0x0d
-#define HDMI_NV_PDISP_RG_HDCP_DKSV_MSB                         0x0e
-#define HDMI_NV_PDISP_RG_HDCP_DKSV_LSB                         0x0f
-#define HDMI_NV_PDISP_RG_HDCP_CTRL                             0x10
-#define HDMI_NV_PDISP_RG_HDCP_CMODE                            0x11
-#define HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB                       0x12
-#define HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB                       0x13
-#define HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB                       0x14
-#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2                      0x15
-#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1                      0x16
-#define HDMI_NV_PDISP_RG_HDCP_RI                               0x17
-#define HDMI_NV_PDISP_RG_HDCP_CS_MSB                           0x18
-#define HDMI_NV_PDISP_RG_HDCP_CS_LSB                           0x19
-#define HDMI_NV_PDISP_HDMI_AUDIO_EMU0                          0x1a
-#define HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0                    0x1b
-#define HDMI_NV_PDISP_HDMI_AUDIO_EMU1                          0x1c
-#define HDMI_NV_PDISP_HDMI_AUDIO_EMU2                          0x1d
-
-#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL                        0x1e
-#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS              0x1f
-#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER              0x20
-#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW                0x21
-#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH       0x22
-#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL                  0x23
-#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS                        0x24
-#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER                        0x25
-#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW          0x26
-#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH         0x27
-#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW          0x28
-#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH         0x29
-
-#define INFOFRAME_CTRL_ENABLE (1 << 0)
-
-#define INFOFRAME_HEADER_TYPE(x)    (((x) & 0xff) <<  0)
-#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
-#define INFOFRAME_HEADER_LEN(x)     (((x) & 0x0f) << 16)
-
-#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL                                0x2a
-#define GENERIC_CTRL_ENABLE (1 <<  0)
-#define GENERIC_CTRL_OTHER  (1 <<  4)
-#define GENERIC_CTRL_SINGLE (1 <<  8)
-#define GENERIC_CTRL_HBLANK (1 << 12)
-#define GENERIC_CTRL_AUDIO  (1 << 16)
-
-#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS                      0x2b
-#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER                      0x2c
-#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW                        0x2d
-#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH               0x2e
-#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW                        0x2f
-#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH               0x30
-#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW                        0x31
-#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH               0x32
-#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW                        0x33
-#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH               0x34
-
-#define HDMI_NV_PDISP_HDMI_ACR_CTRL                            0x35
-#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW                        0x36
-#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH               0x37
-#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW                        0x38
-#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH               0x39
-#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW                        0x3a
-#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH               0x3b
-#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW                        0x3c
-#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH               0x3d
-#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW                        0x3e
-#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH               0x3f
-#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW                        0x40
-#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH               0x41
-#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW                        0x42
-#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH               0x43
-
-#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8)
-#define ACR_SUBPACK_N(x)   (((x) & 0xffffff) << 0)
-#define ACR_ENABLE         (1 << 31)
-
-#define HDMI_NV_PDISP_HDMI_CTRL                                        0x44
-#define HDMI_CTRL_REKEY(x)         (((x) & 0x7f) <<  0)
-#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16)
-#define HDMI_CTRL_ENABLE           (1 << 30)
-
-#define HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT                       0x45
-#define HDMI_NV_PDISP_HDMI_VSYNC_WINDOW                                0x46
-#define VSYNC_WINDOW_END(x)   (((x) & 0x3ff) <<  0)
-#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16)
-#define VSYNC_WINDOW_ENABLE   (1 << 31)
-
-#define HDMI_NV_PDISP_HDMI_GCP_CTRL                            0x47
-#define HDMI_NV_PDISP_HDMI_GCP_STATUS                          0x48
-#define HDMI_NV_PDISP_HDMI_GCP_SUBPACK                         0x49
-#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1                     0x4a
-#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2                     0x4b
-#define HDMI_NV_PDISP_HDMI_EMU0                                        0x4c
-#define HDMI_NV_PDISP_HDMI_EMU1                                        0x4d
-#define HDMI_NV_PDISP_HDMI_EMU1_RDATA                          0x4e
-
-#define HDMI_NV_PDISP_HDMI_SPARE                               0x4f
-#define SPARE_HW_CTS           (1 << 0)
-#define SPARE_FORCE_SW_CTS     (1 << 1)
-#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16)
-
-#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1                   0x50
-#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2                   0x51
-#define HDMI_NV_PDISP_HDMI_HDCPRIF_ROM_CTRL                    0x53
-#define HDMI_NV_PDISP_SOR_CAP                                  0x54
-#define HDMI_NV_PDISP_SOR_PWR                                  0x55
-#define SOR_PWR_NORMAL_STATE_PD     (0 <<  0)
-#define SOR_PWR_NORMAL_STATE_PU     (1 <<  0)
-#define SOR_PWR_NORMAL_START_NORMAL (0 <<  1)
-#define SOR_PWR_NORMAL_START_ALT    (1 <<  1)
-#define SOR_PWR_SAFE_STATE_PD       (0 << 16)
-#define SOR_PWR_SAFE_STATE_PU       (1 << 16)
-#define SOR_PWR_SETTING_NEW_DONE    (0 << 31)
-#define SOR_PWR_SETTING_NEW_PENDING (1 << 31)
-#define SOR_PWR_SETTING_NEW_TRIGGER (1 << 31)
-
-#define HDMI_NV_PDISP_SOR_TEST                                 0x56
-#define HDMI_NV_PDISP_SOR_PLL0                                 0x57
-#define SOR_PLL_PWR            (1 << 0)
-#define SOR_PLL_PDBG           (1 << 1)
-#define SOR_PLL_VCAPD          (1 << 2)
-#define SOR_PLL_PDPORT         (1 << 3)
-#define SOR_PLL_RESISTORSEL    (1 << 4)
-#define SOR_PLL_PULLDOWN       (1 << 5)
-#define SOR_PLL_VCOCAP(x)      (((x) & 0xf) <<  8)
-#define SOR_PLL_BG_V17_S(x)    (((x) & 0xf) << 12)
-#define SOR_PLL_FILTER(x)      (((x) & 0xf) << 16)
-#define SOR_PLL_ICHPMP(x)      (((x) & 0xf) << 24)
-#define SOR_PLL_TX_REG_LOAD(x) (((x) & 0xf) << 28)
-
-#define HDMI_NV_PDISP_SOR_PLL1                                 0x58
-#define SOR_PLL_TMDS_TERM_ENABLE (1 << 8)
-#define SOR_PLL_TMDS_TERMADJ(x)  (((x) & 0xf) <<  9)
-#define SOR_PLL_LOADADJ(x)       (((x) & 0xf) << 20)
-#define SOR_PLL_PE_EN            (1 << 28)
-#define SOR_PLL_HALF_FULL_PE     (1 << 29)
-#define SOR_PLL_S_D_PIN_PE       (1 << 30)
-
-#define HDMI_NV_PDISP_SOR_PLL2                                 0x59
-
-#define HDMI_NV_PDISP_SOR_CSTM                                 0x5a
-#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24)
-
-#define HDMI_NV_PDISP_SOR_LVDS                                 0x5b
-#define HDMI_NV_PDISP_SOR_CRCA                                 0x5c
-#define HDMI_NV_PDISP_SOR_CRCB                                 0x5d
-#define HDMI_NV_PDISP_SOR_BLANK                                        0x5e
-#define HDMI_NV_PDISP_SOR_SEQ_CTL                              0x5f
-#define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) <<  0)
-#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) <<  4)
-#define SOR_SEQ_PD_PC(x)     (((x) & 0xf) <<  8)
-#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12)
-#define SOR_SEQ_PC(x)        (((x) & 0xf) << 16)
-#define SOR_SEQ_STATUS       (1 << 28)
-#define SOR_SEQ_SWITCH       (1 << 30)
-
-#define HDMI_NV_PDISP_SOR_SEQ_INST(x)                          (0x60 + (x))
-
-#define SOR_SEQ_INST_WAIT_TIME(x)     (((x) & 0x3ff) << 0)
-#define SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12)
-#define SOR_SEQ_INST_HALT             (1 << 15)
-#define SOR_SEQ_INST_PIN_A_LOW        (0 << 21)
-#define SOR_SEQ_INST_PIN_A_HIGH       (1 << 21)
-#define SOR_SEQ_INST_PIN_B_LOW        (0 << 22)
-#define SOR_SEQ_INST_PIN_B_HIGH       (1 << 22)
-#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23)
-
-#define HDMI_NV_PDISP_SOR_VCRCA0                               0x72
-#define HDMI_NV_PDISP_SOR_VCRCA1                               0x73
-#define HDMI_NV_PDISP_SOR_CCRCA0                               0x74
-#define HDMI_NV_PDISP_SOR_CCRCA1                               0x75
-#define HDMI_NV_PDISP_SOR_EDATAA0                              0x76
-#define HDMI_NV_PDISP_SOR_EDATAA1                              0x77
-#define HDMI_NV_PDISP_SOR_COUNTA0                              0x78
-#define HDMI_NV_PDISP_SOR_COUNTA1                              0x79
-#define HDMI_NV_PDISP_SOR_DEBUGA0                              0x7a
-#define HDMI_NV_PDISP_SOR_DEBUGA1                              0x7b
-#define HDMI_NV_PDISP_SOR_TRIG                                 0x7c
-#define HDMI_NV_PDISP_SOR_MSCHECK                              0x7d
-
-#define HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT                   0x7e
-#define DRIVE_CURRENT_LANE0(x)      (((x) & 0x3f) <<  0)
-#define DRIVE_CURRENT_LANE1(x)      (((x) & 0x3f) <<  8)
-#define DRIVE_CURRENT_LANE2(x)      (((x) & 0x3f) << 16)
-#define DRIVE_CURRENT_LANE3(x)      (((x) & 0x3f) << 24)
-#define DRIVE_CURRENT_FUSE_OVERRIDE (1 << 31)
-
-#define DRIVE_CURRENT_1_500_mA  0x00
-#define DRIVE_CURRENT_1_875_mA  0x01
-#define DRIVE_CURRENT_2_250_mA  0x02
-#define DRIVE_CURRENT_2_625_mA  0x03
-#define DRIVE_CURRENT_3_000_mA  0x04
-#define DRIVE_CURRENT_3_375_mA  0x05
-#define DRIVE_CURRENT_3_750_mA  0x06
-#define DRIVE_CURRENT_4_125_mA  0x07
-#define DRIVE_CURRENT_4_500_mA  0x08
-#define DRIVE_CURRENT_4_875_mA  0x09
-#define DRIVE_CURRENT_5_250_mA  0x0a
-#define DRIVE_CURRENT_5_625_mA  0x0b
-#define DRIVE_CURRENT_6_000_mA  0x0c
-#define DRIVE_CURRENT_6_375_mA  0x0d
-#define DRIVE_CURRENT_6_750_mA  0x0e
-#define DRIVE_CURRENT_7_125_mA  0x0f
-#define DRIVE_CURRENT_7_500_mA  0x10
-#define DRIVE_CURRENT_7_875_mA  0x11
-#define DRIVE_CURRENT_8_250_mA  0x12
-#define DRIVE_CURRENT_8_625_mA  0x13
-#define DRIVE_CURRENT_9_000_mA  0x14
-#define DRIVE_CURRENT_9_375_mA  0x15
-#define DRIVE_CURRENT_9_750_mA  0x16
-#define DRIVE_CURRENT_10_125_mA 0x17
-#define DRIVE_CURRENT_10_500_mA 0x18
-#define DRIVE_CURRENT_10_875_mA 0x19
-#define DRIVE_CURRENT_11_250_mA 0x1a
-#define DRIVE_CURRENT_11_625_mA 0x1b
-#define DRIVE_CURRENT_12_000_mA 0x1c
-#define DRIVE_CURRENT_12_375_mA 0x1d
-#define DRIVE_CURRENT_12_750_mA 0x1e
-#define DRIVE_CURRENT_13_125_mA 0x1f
-#define DRIVE_CURRENT_13_500_mA 0x20
-#define DRIVE_CURRENT_13_875_mA 0x21
-#define DRIVE_CURRENT_14_250_mA 0x22
-#define DRIVE_CURRENT_14_625_mA 0x23
-#define DRIVE_CURRENT_15_000_mA 0x24
-#define DRIVE_CURRENT_15_375_mA 0x25
-#define DRIVE_CURRENT_15_750_mA 0x26
-#define DRIVE_CURRENT_16_125_mA 0x27
-#define DRIVE_CURRENT_16_500_mA 0x28
-#define DRIVE_CURRENT_16_875_mA 0x29
-#define DRIVE_CURRENT_17_250_mA 0x2a
-#define DRIVE_CURRENT_17_625_mA 0x2b
-#define DRIVE_CURRENT_18_000_mA 0x2c
-#define DRIVE_CURRENT_18_375_mA 0x2d
-#define DRIVE_CURRENT_18_750_mA 0x2e
-#define DRIVE_CURRENT_19_125_mA 0x2f
-#define DRIVE_CURRENT_19_500_mA 0x30
-#define DRIVE_CURRENT_19_875_mA 0x31
-#define DRIVE_CURRENT_20_250_mA 0x32
-#define DRIVE_CURRENT_20_625_mA 0x33
-#define DRIVE_CURRENT_21_000_mA 0x34
-#define DRIVE_CURRENT_21_375_mA 0x35
-#define DRIVE_CURRENT_21_750_mA 0x36
-#define DRIVE_CURRENT_22_125_mA 0x37
-#define DRIVE_CURRENT_22_500_mA 0x38
-#define DRIVE_CURRENT_22_875_mA 0x39
-#define DRIVE_CURRENT_23_250_mA 0x3a
-#define DRIVE_CURRENT_23_625_mA 0x3b
-#define DRIVE_CURRENT_24_000_mA 0x3c
-#define DRIVE_CURRENT_24_375_mA 0x3d
-#define DRIVE_CURRENT_24_750_mA 0x3e
-
-#define HDMI_NV_PDISP_AUDIO_DEBUG0                             0x7f
-#define HDMI_NV_PDISP_AUDIO_DEBUG1                             0x80
-#define HDMI_NV_PDISP_AUDIO_DEBUG2                             0x81
-
-#define HDMI_NV_PDISP_AUDIO_FS(x)                              (0x82 + (x))
-#define AUDIO_FS_LOW(x)  (((x) & 0xfff) <<  0)
-#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16)
-
-#define HDMI_NV_PDISP_AUDIO_PULSE_WIDTH                                0x89
-#define HDMI_NV_PDISP_AUDIO_THRESHOLD                          0x8a
-#define HDMI_NV_PDISP_AUDIO_CNTRL0                             0x8b
-#define AUDIO_CNTRL0_ERROR_TOLERANCE(x)  (((x) & 0xff) << 0)
-#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO  (0 << 20)
-#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20)
-#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL  (2 << 20)
-#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24)
-
-#define HDMI_NV_PDISP_AUDIO_N                                  0x8c
-#define AUDIO_N_VALUE(x)           (((x) & 0xfffff) << 0)
-#define AUDIO_N_RESETF             (1 << 20)
-#define AUDIO_N_GENERATE_NORMAL    (0 << 24)
-#define AUDIO_N_GENERATE_ALTERNATE (1 << 24)
-
-#define HDMI_NV_PDISP_HDCPRIF_ROM_TIMING                       0x94
-#define HDMI_NV_PDISP_SOR_REFCLK                               0x95
-#define SOR_REFCLK_DIV_INT(x)  (((x) & 0xff) << 8)
-#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x03) << 6)
-
-#define HDMI_NV_PDISP_CRC_CONTROL                              0x96
-#define HDMI_NV_PDISP_INPUT_CONTROL                            0x97
-#define HDMI_SRC_DISPLAYA       (0 << 0)
-#define HDMI_SRC_DISPLAYB       (1 << 0)
-#define ARM_VIDEO_RANGE_FULL    (0 << 1)
-#define ARM_VIDEO_RANGE_LIMITED (1 << 1)
-
-#define HDMI_NV_PDISP_SCRATCH                                  0x98
-#define HDMI_NV_PDISP_PE_CURRENT                               0x99
-#define PE_CURRENT0(x) (((x) & 0xf) << 0)
-#define PE_CURRENT1(x) (((x) & 0xf) << 8)
-#define PE_CURRENT2(x) (((x) & 0xf) << 16)
-#define PE_CURRENT3(x) (((x) & 0xf) << 24)
-
-#define PE_CURRENT_0_0_mA 0x0
-#define PE_CURRENT_0_5_mA 0x1
-#define PE_CURRENT_1_0_mA 0x2
-#define PE_CURRENT_1_5_mA 0x3
-#define PE_CURRENT_2_0_mA 0x4
-#define PE_CURRENT_2_5_mA 0x5
-#define PE_CURRENT_3_0_mA 0x6
-#define PE_CURRENT_3_5_mA 0x7
-#define PE_CURRENT_4_0_mA 0x8
-#define PE_CURRENT_4_5_mA 0x9
-#define PE_CURRENT_5_0_mA 0xa
-#define PE_CURRENT_5_5_mA 0xb
-#define PE_CURRENT_6_0_mA 0xc
-#define PE_CURRENT_6_5_mA 0xd
-#define PE_CURRENT_7_0_mA 0xe
-#define PE_CURRENT_7_5_mA 0xf
-
-#define HDMI_NV_PDISP_KEY_CTRL                                 0x9a
-#define HDMI_NV_PDISP_KEY_DEBUG0                               0x9b
-#define HDMI_NV_PDISP_KEY_DEBUG1                               0x9c
-#define HDMI_NV_PDISP_KEY_DEBUG2                               0x9d
-#define HDMI_NV_PDISP_KEY_HDCP_KEY_0                           0x9e
-#define HDMI_NV_PDISP_KEY_HDCP_KEY_1                           0x9f
-#define HDMI_NV_PDISP_KEY_HDCP_KEY_2                           0xa0
-#define HDMI_NV_PDISP_KEY_HDCP_KEY_3                           0xa1
-#define HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG                                0xa2
-#define HDMI_NV_PDISP_KEY_SKEY_INDEX                           0xa3
-
-#define HDMI_NV_PDISP_SOR_AUDIO_CNTRL0                         0xac
-#define AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29)
-#define HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR                  0xbc
-#define HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE                   0xbd
-
-#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320    0xbf
-#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441    0xc0
-#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882    0xc1
-#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764    0xc2
-#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480    0xc3
-#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960    0xc4
-#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920    0xc5
-#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT 0xc5
-
-#endif /* TEGRA_HDMI_H */
diff --git a/drivers/gpu/host1x/drm/output.c b/drivers/gpu/host1x/drm/output.c
deleted file mode 100644 (file)
index 8f40fa6..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/of_gpio.h>
-
-#include "drm.h"
-
-static int tegra_connector_get_modes(struct drm_connector *connector)
-{
-       struct tegra_output *output = connector_to_output(connector);
-       struct edid *edid = NULL;
-       int err = 0;
-
-       if (output->edid)
-               edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL);
-       else if (output->ddc)
-               edid = drm_get_edid(connector, output->ddc);
-
-       drm_mode_connector_update_edid_property(connector, edid);
-
-       if (edid) {
-               err = drm_add_edid_modes(connector, edid);
-               kfree(edid);
-       }
-
-       return err;
-}
-
-static int tegra_connector_mode_valid(struct drm_connector *connector,
-                                     struct drm_display_mode *mode)
-{
-       struct tegra_output *output = connector_to_output(connector);
-       enum drm_mode_status status = MODE_OK;
-       int err;
-
-       err = tegra_output_check_mode(output, mode, &status);
-       if (err < 0)
-               return MODE_ERROR;
-
-       return status;
-}
-
-static struct drm_encoder *
-tegra_connector_best_encoder(struct drm_connector *connector)
-{
-       struct tegra_output *output = connector_to_output(connector);
-
-       return &output->encoder;
-}
-
-static const struct drm_connector_helper_funcs connector_helper_funcs = {
-       .get_modes = tegra_connector_get_modes,
-       .mode_valid = tegra_connector_mode_valid,
-       .best_encoder = tegra_connector_best_encoder,
-};
-
-static enum drm_connector_status
-tegra_connector_detect(struct drm_connector *connector, bool force)
-{
-       struct tegra_output *output = connector_to_output(connector);
-       enum drm_connector_status status = connector_status_unknown;
-
-       if (gpio_is_valid(output->hpd_gpio)) {
-               if (gpio_get_value(output->hpd_gpio) == 0)
-                       status = connector_status_disconnected;
-               else
-                       status = connector_status_connected;
-       } else {
-               if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
-                       status = connector_status_connected;
-       }
-
-       return status;
-}
-
-static void tegra_connector_destroy(struct drm_connector *connector)
-{
-       drm_sysfs_connector_remove(connector);
-       drm_connector_cleanup(connector);
-}
-
-static const struct drm_connector_funcs connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .detect = tegra_connector_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = tegra_connector_destroy,
-};
-
-static void tegra_encoder_destroy(struct drm_encoder *encoder)
-{
-       drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs encoder_funcs = {
-       .destroy = tegra_encoder_destroy,
-};
-
-static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-}
-
-static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder,
-                                    const struct drm_display_mode *mode,
-                                    struct drm_display_mode *adjusted)
-{
-       return true;
-}
-
-static void tegra_encoder_prepare(struct drm_encoder *encoder)
-{
-}
-
-static void tegra_encoder_commit(struct drm_encoder *encoder)
-{
-}
-
-static void tegra_encoder_mode_set(struct drm_encoder *encoder,
-                                  struct drm_display_mode *mode,
-                                  struct drm_display_mode *adjusted)
-{
-       struct tegra_output *output = encoder_to_output(encoder);
-       int err;
-
-       err = tegra_output_enable(output);
-       if (err < 0)
-               dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err);
-}
-
-static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-       .dpms = tegra_encoder_dpms,
-       .mode_fixup = tegra_encoder_mode_fixup,
-       .prepare = tegra_encoder_prepare,
-       .commit = tegra_encoder_commit,
-       .mode_set = tegra_encoder_mode_set,
-};
-
-static irqreturn_t hpd_irq(int irq, void *data)
-{
-       struct tegra_output *output = data;
-
-       drm_helper_hpd_irq_event(output->connector.dev);
-
-       return IRQ_HANDLED;
-}
-
-int tegra_output_parse_dt(struct tegra_output *output)
-{
-       enum of_gpio_flags flags;
-       struct device_node *ddc;
-       size_t size;
-       int err;
-
-       if (!output->of_node)
-               output->of_node = output->dev->of_node;
-
-       output->edid = of_get_property(output->of_node, "nvidia,edid", &size);
-
-       ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0);
-       if (ddc) {
-               output->ddc = of_find_i2c_adapter_by_node(ddc);
-               if (!output->ddc) {
-                       err = -EPROBE_DEFER;
-                       of_node_put(ddc);
-                       return err;
-               }
-
-               of_node_put(ddc);
-       }
-
-       if (!output->edid && !output->ddc)
-               return -ENODEV;
-
-       output->hpd_gpio = of_get_named_gpio_flags(output->of_node,
-                                                  "nvidia,hpd-gpio", 0,
-                                                  &flags);
-
-       return 0;
-}
-
-int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
-{
-       int connector, encoder, err;
-
-       if (gpio_is_valid(output->hpd_gpio)) {
-               unsigned long flags;
-
-               err = gpio_request_one(output->hpd_gpio, GPIOF_DIR_IN,
-                                      "HDMI hotplug detect");
-               if (err < 0) {
-                       dev_err(output->dev, "gpio_request_one(): %d\n", err);
-                       return err;
-               }
-
-               err = gpio_to_irq(output->hpd_gpio);
-               if (err < 0) {
-                       dev_err(output->dev, "gpio_to_irq(): %d\n", err);
-                       goto free_hpd;
-               }
-
-               output->hpd_irq = err;
-
-               flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
-                       IRQF_ONESHOT;
-
-               err = request_threaded_irq(output->hpd_irq, NULL, hpd_irq,
-                                          flags, "hpd", output);
-               if (err < 0) {
-                       dev_err(output->dev, "failed to request IRQ#%u: %d\n",
-                               output->hpd_irq, err);
-                       goto free_hpd;
-               }
-
-               output->connector.polled = DRM_CONNECTOR_POLL_HPD;
-       }
-
-       switch (output->type) {
-       case TEGRA_OUTPUT_RGB:
-               connector = DRM_MODE_CONNECTOR_LVDS;
-               encoder = DRM_MODE_ENCODER_LVDS;
-               break;
-
-       case TEGRA_OUTPUT_HDMI:
-               connector = DRM_MODE_CONNECTOR_HDMIA;
-               encoder = DRM_MODE_ENCODER_TMDS;
-               break;
-
-       default:
-               connector = DRM_MODE_CONNECTOR_Unknown;
-               encoder = DRM_MODE_ENCODER_NONE;
-               break;
-       }
-
-       drm_connector_init(drm, &output->connector, &connector_funcs,
-                          connector);
-       drm_connector_helper_add(&output->connector, &connector_helper_funcs);
-
-       drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder);
-       drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
-
-       drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
-       drm_sysfs_connector_add(&output->connector);
-
-       output->encoder.possible_crtcs = 0x3;
-
-       return 0;
-
-free_hpd:
-       gpio_free(output->hpd_gpio);
-
-       return err;
-}
-
-int tegra_output_exit(struct tegra_output *output)
-{
-       if (gpio_is_valid(output->hpd_gpio)) {
-               free_irq(output->hpd_irq, output);
-               gpio_free(output->hpd_gpio);
-       }
-
-       if (output->ddc)
-               put_device(&output->ddc->dev);
-
-       return 0;
-}
diff --git a/drivers/gpu/host1x/drm/rgb.c b/drivers/gpu/host1x/drm/rgb.c
deleted file mode 100644 (file)
index e4d2841..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2012 Avionic Design GmbH
- * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-
-#include "drm.h"
-#include "dc.h"
-
-struct tegra_rgb {
-       struct tegra_output output;
-       struct clk *clk_parent;
-       struct clk *clk;
-};
-
-static inline struct tegra_rgb *to_rgb(struct tegra_output *output)
-{
-       return container_of(output, struct tegra_rgb, output);
-}
-
-struct reg_entry {
-       unsigned long offset;
-       unsigned long value;
-};
-
-static const struct reg_entry rgb_enable[] = {
-       { DC_COM_PIN_OUTPUT_ENABLE(0),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_ENABLE(1),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_ENABLE(2),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_ENABLE(3),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
-       { DC_COM_PIN_OUTPUT_POLARITY(1), 0x01000000 },
-       { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
-       { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
-       { DC_COM_PIN_OUTPUT_DATA(0),     0x00000000 },
-       { DC_COM_PIN_OUTPUT_DATA(1),     0x00000000 },
-       { DC_COM_PIN_OUTPUT_DATA(2),     0x00000000 },
-       { DC_COM_PIN_OUTPUT_DATA(3),     0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(0),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(1),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(2),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(3),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(4),   0x00210222 },
-       { DC_COM_PIN_OUTPUT_SELECT(5),   0x00002200 },
-       { DC_COM_PIN_OUTPUT_SELECT(6),   0x00020000 },
-};
-
-static const struct reg_entry rgb_disable[] = {
-       { DC_COM_PIN_OUTPUT_SELECT(6),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(5),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(4),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(3),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(2),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(1),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_SELECT(0),   0x00000000 },
-       { DC_COM_PIN_OUTPUT_DATA(3),     0xaaaaaaaa },
-       { DC_COM_PIN_OUTPUT_DATA(2),     0xaaaaaaaa },
-       { DC_COM_PIN_OUTPUT_DATA(1),     0xaaaaaaaa },
-       { DC_COM_PIN_OUTPUT_DATA(0),     0xaaaaaaaa },
-       { DC_COM_PIN_OUTPUT_POLARITY(3), 0x00000000 },
-       { DC_COM_PIN_OUTPUT_POLARITY(2), 0x00000000 },
-       { DC_COM_PIN_OUTPUT_POLARITY(1), 0x00000000 },
-       { DC_COM_PIN_OUTPUT_POLARITY(0), 0x00000000 },
-       { DC_COM_PIN_OUTPUT_ENABLE(3),   0x55555555 },
-       { DC_COM_PIN_OUTPUT_ENABLE(2),   0x55555555 },
-       { DC_COM_PIN_OUTPUT_ENABLE(1),   0x55150005 },
-       { DC_COM_PIN_OUTPUT_ENABLE(0),   0x55555555 },
-};
-
-static void tegra_dc_write_regs(struct tegra_dc *dc,
-                               const struct reg_entry *table,
-                               unsigned int num)
-{
-       unsigned int i;
-
-       for (i = 0; i < num; i++)
-               tegra_dc_writel(dc, table[i].value, table[i].offset);
-}
-
-static int tegra_output_rgb_enable(struct tegra_output *output)
-{
-       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
-
-       tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable));
-
-       return 0;
-}
-
-static int tegra_output_rgb_disable(struct tegra_output *output)
-{
-       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
-
-       tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable));
-
-       return 0;
-}
-
-static int tegra_output_rgb_setup_clock(struct tegra_output *output,
-                                       struct clk *clk, unsigned long pclk)
-{
-       struct tegra_rgb *rgb = to_rgb(output);
-
-       return clk_set_parent(clk, rgb->clk_parent);
-}
-
-static int tegra_output_rgb_check_mode(struct tegra_output *output,
-                                      struct drm_display_mode *mode,
-                                      enum drm_mode_status *status)
-{
-       /*
-        * FIXME: For now, always assume that the mode is okay. There are
-        * unresolved issues with clk_round_rate(), which doesn't always
-        * reliably report whether a frequency can be set or not.
-        */
-
-       *status = MODE_OK;
-
-       return 0;
-}
-
-static const struct tegra_output_ops rgb_ops = {
-       .enable = tegra_output_rgb_enable,
-       .disable = tegra_output_rgb_disable,
-       .setup_clock = tegra_output_rgb_setup_clock,
-       .check_mode = tegra_output_rgb_check_mode,
-};
-
-int tegra_dc_rgb_probe(struct tegra_dc *dc)
-{
-       struct device_node *np;
-       struct tegra_rgb *rgb;
-       int err;
-
-       np = of_get_child_by_name(dc->dev->of_node, "rgb");
-       if (!np || !of_device_is_available(np))
-               return -ENODEV;
-
-       rgb = devm_kzalloc(dc->dev, sizeof(*rgb), GFP_KERNEL);
-       if (!rgb)
-               return -ENOMEM;
-
-       rgb->output.dev = dc->dev;
-       rgb->output.of_node = np;
-
-       err = tegra_output_parse_dt(&rgb->output);
-       if (err < 0)
-               return err;
-
-       rgb->clk = devm_clk_get(dc->dev, NULL);
-       if (IS_ERR(rgb->clk)) {
-               dev_err(dc->dev, "failed to get clock\n");
-               return PTR_ERR(rgb->clk);
-       }
-
-       rgb->clk_parent = devm_clk_get(dc->dev, "parent");
-       if (IS_ERR(rgb->clk_parent)) {
-               dev_err(dc->dev, "failed to get parent clock\n");
-               return PTR_ERR(rgb->clk_parent);
-       }
-
-       err = clk_set_parent(rgb->clk, rgb->clk_parent);
-       if (err < 0) {
-               dev_err(dc->dev, "failed to set parent clock: %d\n", err);
-               return err;
-       }
-
-       dc->rgb = &rgb->output;
-
-       return 0;
-}
-
-int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
-{
-       struct tegra_rgb *rgb = to_rgb(dc->rgb);
-       int err;
-
-       if (!dc->rgb)
-               return -ENODEV;
-
-       rgb->output.type = TEGRA_OUTPUT_RGB;
-       rgb->output.ops = &rgb_ops;
-
-       err = tegra_output_init(dc->base.dev, &rgb->output);
-       if (err < 0) {
-               dev_err(dc->dev, "output setup failed: %d\n", err);
-               return err;
-       }
-
-       /*
-        * By default, outputs can be associated with each display controller.
-        * RGB outputs are an exception, so we make sure they can be attached
-        * to only their parent display controller.
-        */
-       rgb->output.encoder.possible_crtcs = 1 << dc->pipe;
-
-       return 0;
-}
-
-int tegra_dc_rgb_exit(struct tegra_dc *dc)
-{
-       if (dc->rgb) {
-               int err;
-
-               err = tegra_output_disable(dc->rgb);
-               if (err < 0) {
-                       dev_err(dc->dev, "output failed to disable: %d\n", err);
-                       return err;
-               }
-
-               err = tegra_output_exit(dc->rgb);
-               if (err < 0) {
-                       dev_err(dc->dev, "output cleanup failed: %d\n", err);
-                       return err;
-               }
-
-               dc->rgb = NULL;
-       }
-
-       return 0;
-}
index 84b685f7ab6e0a3389c534b56e8f8187619e1e84..a312f048656f76f017c2a730836762cadd1e8553 100644 (file)
@@ -19,10 +19,10 @@ source "drivers/char/agp/Kconfig"
 
 source "drivers/gpu/vga/Kconfig"
 
-source "drivers/gpu/drm/Kconfig"
-
 source "drivers/gpu/host1x/Kconfig"
 
+source "drivers/gpu/drm/Kconfig"
+
 config VGASTATE
        tristate
        default n