tristate "Cirrus driver for QEMU emulated device"
        depends on DRM && PCI && MMU
        select DRM_KMS_HELPER
-       select DRM_TTM
+       select DRM_GEM_SHMEM_HELPER
        help
         This is a KMS driver for emulated cirrus device in qemu.
         It is *NOT* intended for real cirrus devices. This requires
 
-cirrus-y  := cirrus_main.o cirrus_mode.o \
-       cirrus_drv.o cirrus_fbdev.o cirrus_ttm.o
-
 obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o
 
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2012-2019 Red Hat
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License version 2. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Authors: Matthew Garrett
+ *         Dave Airlie
+ *         Gerd Hoffmann
+ *
+ * Portions of this code derived from cirrusfb.c:
+ * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
+ *
+ * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
+ */
+
+#include <linux/console.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <video/cirrus.h>
+#include <video/vga.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_file.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_vblank.h>
+
+#define DRIVER_NAME "cirrus"
+#define DRIVER_DESC "qemu cirrus vga"
+#define DRIVER_DATE "2019"
+#define DRIVER_MAJOR 2
+#define DRIVER_MINOR 0
+
+#define CIRRUS_MAX_PITCH (0x1FF << 3)      /* (4096 - 1) & ~111b bytes */
+#define CIRRUS_VRAM_SIZE (4 * 1024 * 1024) /* 4 MB */
+
+struct cirrus_device {
+       struct drm_device              dev;
+       struct drm_simple_display_pipe pipe;
+       struct drm_connector           conn;
+       unsigned int                   cpp;
+       unsigned int                   pitch;
+       void __iomem                   *vram;
+       void __iomem                   *mmio;
+};
+
+/* ------------------------------------------------------------------ */
+/*
+ * The meat of this driver. The core passes us a mode and we have to program
+ * it. The modesetting here is the bare minimum required to satisfy the qemu
+ * emulation of this hardware, and running this against a real device is
+ * likely to result in an inadequately programmed mode. We've already had
+ * the opportunity to modify the mode, so whatever we receive here should
+ * be something that can be correctly programmed and displayed
+ */
+
+#define SEQ_INDEX 4
+#define SEQ_DATA 5
+
+static u8 rreg_seq(struct cirrus_device *cirrus, u8 reg)
+{
+       iowrite8(reg, cirrus->mmio + SEQ_INDEX);
+       return ioread8(cirrus->mmio + SEQ_DATA);
+}
+
+static void wreg_seq(struct cirrus_device *cirrus, u8 reg, u8 val)
+{
+       iowrite8(reg, cirrus->mmio + SEQ_INDEX);
+       iowrite8(val, cirrus->mmio + SEQ_DATA);
+}
+
+#define CRT_INDEX 0x14
+#define CRT_DATA 0x15
+
+static u8 rreg_crt(struct cirrus_device *cirrus, u8 reg)
+{
+       iowrite8(reg, cirrus->mmio + CRT_INDEX);
+       return ioread8(cirrus->mmio + CRT_DATA);
+}
+
+static void wreg_crt(struct cirrus_device *cirrus, u8 reg, u8 val)
+{
+       iowrite8(reg, cirrus->mmio + CRT_INDEX);
+       iowrite8(val, cirrus->mmio + CRT_DATA);
+}
+
+#define GFX_INDEX 0xe
+#define GFX_DATA 0xf
+
+static void wreg_gfx(struct cirrus_device *cirrus, u8 reg, u8 val)
+{
+       iowrite8(reg, cirrus->mmio + GFX_INDEX);
+       iowrite8(val, cirrus->mmio + GFX_DATA);
+}
+
+#define VGA_DAC_MASK  0x06
+
+static void wreg_hdr(struct cirrus_device *cirrus, u8 val)
+{
+       ioread8(cirrus->mmio + VGA_DAC_MASK);
+       ioread8(cirrus->mmio + VGA_DAC_MASK);
+       ioread8(cirrus->mmio + VGA_DAC_MASK);
+       ioread8(cirrus->mmio + VGA_DAC_MASK);
+       iowrite8(val, cirrus->mmio + VGA_DAC_MASK);
+}
+
+static int cirrus_convert_to(struct drm_framebuffer *fb)
+{
+       if (fb->format->cpp[0] == 4 && fb->pitches[0] > CIRRUS_MAX_PITCH) {
+               if (fb->width * 3 <= CIRRUS_MAX_PITCH)
+                       /* convert from XR24 to RG24 */
+                       return 3;
+               else
+                       /* convert from XR24 to RG16 */
+                       return 2;
+       }
+       return 0;
+}
+
+static int cirrus_cpp(struct drm_framebuffer *fb)
+{
+       int convert_cpp = cirrus_convert_to(fb);
+
+       if (convert_cpp)
+               return convert_cpp;
+       return fb->format->cpp[0];
+}
+
+static int cirrus_pitch(struct drm_framebuffer *fb)
+{
+       int convert_cpp = cirrus_convert_to(fb);
+
+       if (convert_cpp)
+               return convert_cpp * fb->width;
+       return fb->pitches[0];
+}
+
+static void cirrus_set_start_address(struct cirrus_device *cirrus, u32 offset)
+{
+       u32 addr;
+       u8 tmp;
+
+       addr = offset >> 2;
+       wreg_crt(cirrus, 0x0c, (u8)((addr >> 8) & 0xff));
+       wreg_crt(cirrus, 0x0d, (u8)(addr & 0xff));
+
+       tmp = rreg_crt(cirrus, 0x1b);
+       tmp &= 0xf2;
+       tmp |= (addr >> 16) & 0x01;
+       tmp |= (addr >> 15) & 0x0c;
+       wreg_crt(cirrus, 0x1b, tmp);
+
+       tmp = rreg_crt(cirrus, 0x1d);
+       tmp &= 0x7f;
+       tmp |= (addr >> 12) & 0x80;
+       wreg_crt(cirrus, 0x1d, tmp);
+}
+
+static int cirrus_mode_set(struct cirrus_device *cirrus,
+                          struct drm_display_mode *mode,
+                          struct drm_framebuffer *fb)
+{
+       int hsyncstart, hsyncend, htotal, hdispend;
+       int vtotal, vdispend;
+       int tmp;
+       int sr07 = 0, hdr = 0;
+
+       htotal = mode->htotal / 8;
+       hsyncend = mode->hsync_end / 8;
+       hsyncstart = mode->hsync_start / 8;
+       hdispend = mode->hdisplay / 8;
+
+       vtotal = mode->vtotal;
+       vdispend = mode->vdisplay;
+
+       vdispend -= 1;
+       vtotal -= 2;
+
+       htotal -= 5;
+       hdispend -= 1;
+       hsyncstart += 1;
+       hsyncend += 1;
+
+       wreg_crt(cirrus, VGA_CRTC_V_SYNC_END, 0x20);
+       wreg_crt(cirrus, VGA_CRTC_H_TOTAL, htotal);
+       wreg_crt(cirrus, VGA_CRTC_H_DISP, hdispend);
+       wreg_crt(cirrus, VGA_CRTC_H_SYNC_START, hsyncstart);
+       wreg_crt(cirrus, VGA_CRTC_H_SYNC_END, hsyncend);
+       wreg_crt(cirrus, VGA_CRTC_V_TOTAL, vtotal & 0xff);
+       wreg_crt(cirrus, VGA_CRTC_V_DISP_END, vdispend & 0xff);
+
+       tmp = 0x40;
+       if ((vdispend + 1) & 512)
+               tmp |= 0x20;
+       wreg_crt(cirrus, VGA_CRTC_MAX_SCAN, tmp);
+
+       /*
+        * Overflow bits for values that don't fit in the standard registers
+        */
+       tmp = 0x10;
+       if (vtotal & 0x100)
+               tmp |= 0x01;
+       if (vdispend & 0x100)
+               tmp |= 0x02;
+       if ((vdispend + 1) & 0x100)
+               tmp |= 0x08;
+       if (vtotal & 0x200)
+               tmp |= 0x20;
+       if (vdispend & 0x200)
+               tmp |= 0x40;
+       wreg_crt(cirrus, VGA_CRTC_OVERFLOW, tmp);
+
+       tmp = 0;
+
+       /* More overflow bits */
+
+       if ((htotal + 5) & 0x40)
+               tmp |= 0x10;
+       if ((htotal + 5) & 0x80)
+               tmp |= 0x20;
+       if (vtotal & 0x100)
+               tmp |= 0x40;
+       if (vtotal & 0x200)
+               tmp |= 0x80;
+
+       wreg_crt(cirrus, CL_CRT1A, tmp);
+
+       /* Disable Hercules/CGA compatibility */
+       wreg_crt(cirrus, VGA_CRTC_MODE, 0x03);
+
+       sr07 = rreg_seq(cirrus, 0x07);
+       sr07 &= 0xe0;
+       hdr = 0;
+
+       cirrus->cpp = cirrus_cpp(fb);
+       switch (cirrus->cpp * 8) {
+       case 8:
+               sr07 |= 0x11;
+               break;
+       case 16:
+               sr07 |= 0x17;
+               hdr = 0xc1;
+               break;
+       case 24:
+               sr07 |= 0x15;
+               hdr = 0xc5;
+               break;
+       case 32:
+               sr07 |= 0x19;
+               hdr = 0xc5;
+               break;
+       default:
+               return -1;
+       }
+
+       wreg_seq(cirrus, 0x7, sr07);
+
+       /* Program the pitch */
+       cirrus->pitch = cirrus_pitch(fb);
+       tmp = cirrus->pitch / 8;
+       wreg_crt(cirrus, VGA_CRTC_OFFSET, tmp);
+
+       /* Enable extended blanking and pitch bits, and enable full memory */
+       tmp = 0x22;
+       tmp |= (cirrus->pitch >> 7) & 0x10;
+       tmp |= (cirrus->pitch >> 6) & 0x40;
+       wreg_crt(cirrus, 0x1b, tmp);
+
+       /* Enable high-colour modes */
+       wreg_gfx(cirrus, VGA_GFX_MODE, 0x40);
+
+       /* And set graphics mode */
+       wreg_gfx(cirrus, VGA_GFX_MISC, 0x01);
+
+       wreg_hdr(cirrus, hdr);
+
+       cirrus_set_start_address(cirrus, 0);
+
+       /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
+       outb(0x20, 0x3c0);
+       return 0;
+}
+
+static int cirrus_fb_blit_rect(struct drm_framebuffer *fb,
+                              struct drm_rect *rect)
+{
+       struct cirrus_device *cirrus = fb->dev->dev_private;
+       void *vmap;
+
+       vmap = drm_gem_shmem_vmap(fb->obj[0]);
+       if (!vmap)
+               return -ENOMEM;
+
+       if (cirrus->cpp == fb->format->cpp[0])
+               drm_fb_memcpy_dstclip(__io_virt(cirrus->vram),
+                                     vmap, fb, rect);
+
+       else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2)
+               drm_fb_xrgb8888_to_rgb565_dstclip(__io_virt(cirrus->vram),
+                                                 cirrus->pitch,
+                                                 vmap, fb, rect, false);
+
+       else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3)
+               drm_fb_xrgb8888_to_rgb888_dstclip(__io_virt(cirrus->vram),
+                                                 cirrus->pitch,
+                                                 vmap, fb, rect);
+
+       else
+               WARN_ON_ONCE("cpp mismatch");
+
+       drm_gem_shmem_vunmap(fb->obj[0], vmap);
+       return 0;
+}
+
+static int cirrus_fb_blit_fullscreen(struct drm_framebuffer *fb)
+{
+       struct drm_rect fullscreen = {
+               .x1 = 0,
+               .x2 = fb->width,
+               .y1 = 0,
+               .y2 = fb->height,
+       };
+       return cirrus_fb_blit_rect(fb, &fullscreen);
+}
+
+static int cirrus_check_size(int width, int height,
+                            struct drm_framebuffer *fb)
+{
+       int pitch = width * 2;
+
+       if (fb)
+               pitch = cirrus_pitch(fb);
+
+       if (pitch > CIRRUS_MAX_PITCH)
+               return -EINVAL;
+       if (pitch * height > CIRRUS_VRAM_SIZE)
+               return -EINVAL;
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* cirrus connector                                                  */
+
+static int cirrus_conn_get_modes(struct drm_connector *conn)
+{
+       int count;
+
+       count = drm_add_modes_noedid(conn,
+                                    conn->dev->mode_config.max_width,
+                                    conn->dev->mode_config.max_height);
+       drm_set_preferred_mode(conn, 1024, 768);
+       return count;
+}
+
+static const struct drm_connector_helper_funcs cirrus_conn_helper_funcs = {
+       .get_modes = cirrus_conn_get_modes,
+};
+
+static const struct drm_connector_funcs cirrus_conn_funcs = {
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = drm_connector_cleanup,
+       .reset = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int cirrus_conn_init(struct cirrus_device *cirrus)
+{
+       drm_connector_helper_add(&cirrus->conn, &cirrus_conn_helper_funcs);
+       return drm_connector_init(&cirrus->dev, &cirrus->conn,
+                                 &cirrus_conn_funcs, DRM_MODE_CONNECTOR_VGA);
+
+}
+
+/* ------------------------------------------------------------------ */
+/* cirrus (simple) display pipe                                              */
+
+static enum drm_mode_status cirrus_pipe_mode_valid(struct drm_crtc *crtc,
+                                                  const struct drm_display_mode *mode)
+{
+       if (cirrus_check_size(mode->hdisplay, mode->vdisplay, NULL) < 0)
+               return MODE_BAD;
+       return MODE_OK;
+}
+
+static int cirrus_pipe_check(struct drm_simple_display_pipe *pipe,
+                            struct drm_plane_state *plane_state,
+                            struct drm_crtc_state *crtc_state)
+{
+       struct drm_framebuffer *fb = plane_state->fb;
+
+       if (!fb)
+               return 0;
+       return cirrus_check_size(fb->width, fb->height, fb);
+}
+
+static void cirrus_pipe_enable(struct drm_simple_display_pipe *pipe,
+                              struct drm_crtc_state *crtc_state,
+                              struct drm_plane_state *plane_state)
+{
+       struct cirrus_device *cirrus = pipe->crtc.dev->dev_private;
+
+       cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb);
+       cirrus_fb_blit_fullscreen(plane_state->fb);
+}
+
+static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
+                              struct drm_plane_state *old_state)
+{
+       struct cirrus_device *cirrus = pipe->crtc.dev->dev_private;
+       struct drm_plane_state *state = pipe->plane.state;
+       struct drm_crtc *crtc = &pipe->crtc;
+       struct drm_rect rect;
+
+       if (pipe->plane.state->fb &&
+           cirrus->cpp != cirrus_cpp(pipe->plane.state->fb))
+               cirrus_mode_set(cirrus, &crtc->mode,
+                               pipe->plane.state->fb);
+
+       if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+               cirrus_fb_blit_rect(pipe->plane.state->fb, &rect);
+
+       if (crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               crtc->state->event = NULL;
+               spin_unlock_irq(&crtc->dev->event_lock);
+       }
+}
+
+static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = {
+       .mode_valid = cirrus_pipe_mode_valid,
+       .check      = cirrus_pipe_check,
+       .enable     = cirrus_pipe_enable,
+       .update     = cirrus_pipe_update,
+};
+
+static const uint32_t cirrus_formats[] = {
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_RGB888,
+       DRM_FORMAT_XRGB8888,
+};
+
+static const uint64_t cirrus_modifiers[] = {
+       DRM_FORMAT_MOD_LINEAR,
+       DRM_FORMAT_MOD_INVALID
+};
+
+static int cirrus_pipe_init(struct cirrus_device *cirrus)
+{
+       return drm_simple_display_pipe_init(&cirrus->dev,
+                                           &cirrus->pipe,
+                                           &cirrus_pipe_funcs,
+                                           cirrus_formats,
+                                           ARRAY_SIZE(cirrus_formats),
+                                           cirrus_modifiers,
+                                           &cirrus->conn);
+}
+
+/* ------------------------------------------------------------------ */
+/* cirrus framebuffers & mode config                                 */
+
+static struct drm_framebuffer*
+cirrus_fb_create(struct drm_device *dev, struct drm_file *file_priv,
+                const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+       if (mode_cmd->pixel_format != DRM_FORMAT_RGB565 &&
+           mode_cmd->pixel_format != DRM_FORMAT_RGB888 &&
+           mode_cmd->pixel_format != DRM_FORMAT_XRGB8888)
+               return ERR_PTR(-EINVAL);
+       if (cirrus_check_size(mode_cmd->width, mode_cmd->height, NULL) < 0)
+               return ERR_PTR(-EINVAL);
+       return drm_gem_fb_create_with_dirty(dev, file_priv, mode_cmd);
+}
+
+static const struct drm_mode_config_funcs cirrus_mode_config_funcs = {
+       .fb_create = cirrus_fb_create,
+       .atomic_check = drm_atomic_helper_check,
+       .atomic_commit = drm_atomic_helper_commit,
+};
+
+static void cirrus_mode_config_init(struct cirrus_device *cirrus)
+{
+       struct drm_device *dev = &cirrus->dev;
+
+       drm_mode_config_init(dev);
+       dev->mode_config.min_width = 0;
+       dev->mode_config.min_height = 0;
+       dev->mode_config.max_width = CIRRUS_MAX_PITCH / 2;
+       dev->mode_config.max_height = 1024;
+       dev->mode_config.preferred_depth = 16;
+       dev->mode_config.prefer_shadow = 0;
+       dev->mode_config.funcs = &cirrus_mode_config_funcs;
+}
+
+/* ------------------------------------------------------------------ */
+
+DEFINE_DRM_GEM_SHMEM_FOPS(cirrus_fops);
+
+static struct drm_driver cirrus_driver = {
+       .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_PRIME,
+
+       .name            = DRIVER_NAME,
+       .desc            = DRIVER_DESC,
+       .date            = DRIVER_DATE,
+       .major           = DRIVER_MAJOR,
+       .minor           = DRIVER_MINOR,
+
+       .fops            = &cirrus_fops,
+       DRM_GEM_SHMEM_DRIVER_OPS,
+};
+
+static int cirrus_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
+{
+       struct drm_device *dev;
+       struct cirrus_device *cirrus;
+       int ret;
+
+       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "cirrusdrmfb");
+       if (ret)
+               return ret;
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       ret = pci_request_regions(pdev, DRIVER_NAME);
+       if (ret)
+               return ret;
+
+       ret = -ENOMEM;
+       cirrus = kzalloc(sizeof(*cirrus), GFP_KERNEL);
+       if (cirrus == NULL)
+               goto err_pci_release;
+
+       dev = &cirrus->dev;
+       ret = drm_dev_init(dev, &cirrus_driver, &pdev->dev);
+       if (ret)
+               goto err_free_cirrus;
+       dev->dev_private = cirrus;
+
+       ret = -ENOMEM;
+       cirrus->vram = ioremap(pci_resource_start(pdev, 0),
+                              pci_resource_len(pdev, 0));
+       if (cirrus->vram == NULL)
+               goto err_dev_put;
+
+       cirrus->mmio = ioremap(pci_resource_start(pdev, 1),
+                              pci_resource_len(pdev, 1));
+       if (cirrus->mmio == NULL)
+               goto err_unmap_vram;
+
+       cirrus_mode_config_init(cirrus);
+
+       ret = cirrus_conn_init(cirrus);
+       if (ret < 0)
+               goto err_cleanup;
+
+       ret = cirrus_pipe_init(cirrus);
+       if (ret < 0)
+               goto err_cleanup;
+
+       drm_mode_config_reset(dev);
+
+       dev->pdev = pdev;
+       pci_set_drvdata(pdev, dev);
+       ret = drm_dev_register(dev, 0);
+       if (ret)
+               goto err_cleanup;
+
+       drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
+       return 0;
+
+err_cleanup:
+       drm_mode_config_cleanup(dev);
+       iounmap(cirrus->mmio);
+err_unmap_vram:
+       iounmap(cirrus->vram);
+err_dev_put:
+       drm_dev_put(dev);
+err_free_cirrus:
+       kfree(cirrus);
+err_pci_release:
+       pci_release_regions(pdev);
+       return ret;
+}
+
+static void cirrus_pci_remove(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct cirrus_device *cirrus = dev->dev_private;
+
+       drm_dev_unregister(dev);
+       drm_mode_config_cleanup(dev);
+       iounmap(cirrus->mmio);
+       iounmap(cirrus->vram);
+       drm_dev_put(dev);
+       kfree(cirrus);
+       pci_release_regions(pdev);
+}
+
+static const struct pci_device_id pciidlist[] = {
+       {
+               .vendor    = PCI_VENDOR_ID_CIRRUS,
+               .device    = PCI_DEVICE_ID_CIRRUS_5446,
+               /* only bind to the cirrus chip in qemu */
+               .subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
+               .subdevice = PCI_SUBDEVICE_ID_QEMU,
+       }, {
+               .vendor    = PCI_VENDOR_ID_CIRRUS,
+               .device    = PCI_DEVICE_ID_CIRRUS_5446,
+               .subvendor = PCI_VENDOR_ID_XEN,
+               .subdevice = 0x0001,
+       },
+       { /* end if list */ }
+};
+
+static struct pci_driver cirrus_pci_driver = {
+       .name = DRIVER_NAME,
+       .id_table = pciidlist,
+       .probe = cirrus_pci_probe,
+       .remove = cirrus_pci_remove,
+};
+
+static int __init cirrus_init(void)
+{
+       if (vgacon_text_force())
+               return -EINVAL;
+       return pci_register_driver(&cirrus_pci_driver);
+}
+
+static void __exit cirrus_exit(void)
+{
+       pci_unregister_driver(&cirrus_pci_driver);
+}
+
+module_init(cirrus_init);
+module_exit(cirrus_exit);
+
+MODULE_DEVICE_TABLE(pci, pciidlist);
+MODULE_LICENSE("GPL");
 
+++ /dev/null
-/*
- * Copyright 2012 Red Hat <mjg@redhat.com>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License version 2. See the file COPYING in the main
- * directory of this archive for more details.
- *
- * Authors: Matthew Garrett
- *          Dave Airlie
- */
-#include <linux/module.h>
-#include <linux/console.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_probe_helper.h>
-
-#include "cirrus_drv.h"
-
-int cirrus_modeset = -1;
-int cirrus_bpp = 16;
-
-MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
-module_param_named(modeset, cirrus_modeset, int, 0400);
-MODULE_PARM_DESC(bpp, "Max bits-per-pixel (default:16)");
-module_param_named(bpp, cirrus_bpp, int, 0400);
-
-/*
- * This is the generic driver code. This binds the driver to the drm core,
- * which then performs further device association and calls our graphics init
- * functions
- */
-
-static struct drm_driver driver;
-
-/* only bind to the cirrus chip in qemu */
-static const struct pci_device_id pciidlist[] = {
-       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446,
-         PCI_SUBVENDOR_ID_REDHAT_QUMRANET, PCI_SUBDEVICE_ID_QEMU,
-         0, 0, 0 },
-       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, PCI_VENDOR_ID_XEN,
-         0x0001, 0, 0, 0 },
-       {0,}
-};
-
-
-static int cirrus_pci_probe(struct pci_dev *pdev,
-                           const struct pci_device_id *ent)
-{
-       int ret;
-
-       ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "cirrusdrmfb");
-       if (ret)
-               return ret;
-
-       return drm_get_pci_dev(pdev, ent, &driver);
-}
-
-static void cirrus_pci_remove(struct pci_dev *pdev)
-{
-       struct drm_device *dev = pci_get_drvdata(pdev);
-
-       drm_put_dev(dev);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int cirrus_pm_suspend(struct device *dev)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct drm_device *drm_dev = pci_get_drvdata(pdev);
-       struct cirrus_device *cdev = drm_dev->dev_private;
-
-       drm_kms_helper_poll_disable(drm_dev);
-
-       if (cdev->mode_info.gfbdev) {
-               console_lock();
-               drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 1);
-               console_unlock();
-       }
-
-       return 0;
-}
-
-static int cirrus_pm_resume(struct device *dev)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct drm_device *drm_dev = pci_get_drvdata(pdev);
-       struct cirrus_device *cdev = drm_dev->dev_private;
-
-       drm_helper_resume_force_mode(drm_dev);
-
-       if (cdev->mode_info.gfbdev) {
-               console_lock();
-               drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 0);
-               console_unlock();
-       }
-
-       drm_kms_helper_poll_enable(drm_dev);
-       return 0;
-}
-#endif
-
-static const struct file_operations cirrus_driver_fops = {
-       .owner = THIS_MODULE,
-       .open = drm_open,
-       .release = drm_release,
-       .unlocked_ioctl = drm_ioctl,
-       .mmap = cirrus_mmap,
-       .poll = drm_poll,
-       .compat_ioctl = drm_compat_ioctl,
-};
-static struct drm_driver driver = {
-       .driver_features = DRIVER_MODESET | DRIVER_GEM,
-       .load = cirrus_driver_load,
-       .unload = cirrus_driver_unload,
-       .fops = &cirrus_driver_fops,
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-       .gem_free_object_unlocked = cirrus_gem_free_object,
-       .dumb_create = cirrus_dumb_create,
-       .dumb_map_offset = cirrus_dumb_mmap_offset,
-};
-
-static const struct dev_pm_ops cirrus_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend,
-                               cirrus_pm_resume)
-};
-
-static struct pci_driver cirrus_pci_driver = {
-       .name = DRIVER_NAME,
-       .id_table = pciidlist,
-       .probe = cirrus_pci_probe,
-       .remove = cirrus_pci_remove,
-       .driver.pm = &cirrus_pm_ops,
-};
-
-static int __init cirrus_init(void)
-{
-       if (vgacon_text_force() && cirrus_modeset == -1)
-               return -EINVAL;
-
-       if (cirrus_modeset == 0)
-               return -EINVAL;
-       return pci_register_driver(&cirrus_pci_driver);
-}
-
-static void __exit cirrus_exit(void)
-{
-       pci_unregister_driver(&cirrus_pci_driver);
-}
-
-module_init(cirrus_init);
-module_exit(cirrus_exit);
-
-MODULE_DEVICE_TABLE(pci, pciidlist);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
 
+++ /dev/null
-/*
- * Copyright 2012 Red Hat
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License version 2. See the file COPYING in the main
- * directory of this archive for more details.
- *
- * Authors: Matthew Garrett
- *          Dave Airlie
- */
-#ifndef __CIRRUS_DRV_H__
-#define __CIRRUS_DRV_H__
-
-#include <video/vga.h>
-
-#include <drm/drm_encoder.h>
-#include <drm/drm_fb_helper.h>
-
-#include <drm/ttm/ttm_bo_api.h>
-#include <drm/ttm/ttm_bo_driver.h>
-#include <drm/ttm/ttm_placement.h>
-#include <drm/ttm/ttm_memory.h>
-#include <drm/ttm/ttm_module.h>
-
-#include <drm/drm_gem.h>
-
-#define DRIVER_AUTHOR          "Matthew Garrett"
-
-#define DRIVER_NAME            "cirrus"
-#define DRIVER_DESC            "qemu Cirrus emulation"
-#define DRIVER_DATE            "20110418"
-
-#define DRIVER_MAJOR           1
-#define DRIVER_MINOR           0
-#define DRIVER_PATCHLEVEL      0
-
-#define CIRRUSFB_CONN_LIMIT 1
-
-#define RREG8(reg) ioread8(((void __iomem *)cdev->rmmio) + (reg))
-#define WREG8(reg, v) iowrite8(v, ((void __iomem *)cdev->rmmio) + (reg))
-#define RREG32(reg) ioread32(((void __iomem *)cdev->rmmio) + (reg))
-#define WREG32(reg, v) iowrite32(v, ((void __iomem *)cdev->rmmio) + (reg))
-
-#define SEQ_INDEX 4
-#define SEQ_DATA 5
-
-#define WREG_SEQ(reg, v)                                       \
-       do {                                                    \
-               WREG8(SEQ_INDEX, reg);                          \
-               WREG8(SEQ_DATA, v);                             \
-       } while (0)                                             \
-
-#define CRT_INDEX 0x14
-#define CRT_DATA 0x15
-
-#define WREG_CRT(reg, v)                                       \
-       do {                                                    \
-               WREG8(CRT_INDEX, reg);                          \
-               WREG8(CRT_DATA, v);                             \
-       } while (0)                                             \
-
-#define GFX_INDEX 0xe
-#define GFX_DATA 0xf
-
-#define WREG_GFX(reg, v)                                       \
-       do {                                                    \
-               WREG8(GFX_INDEX, reg);                          \
-               WREG8(GFX_DATA, v);                             \
-       } while (0)                                             \
-
-/*
- * Cirrus has a "hidden" DAC register that can be accessed by writing to
- * the pixel mask register to reset the state, then reading from the register
- * four times. The next write will then pass to the DAC
- */
-#define VGA_DAC_MASK 0x6
-
-#define WREG_HDR(v)                                            \
-       do {                                                    \
-               RREG8(VGA_DAC_MASK);                                    \
-               RREG8(VGA_DAC_MASK);                                    \
-               RREG8(VGA_DAC_MASK);                                    \
-               RREG8(VGA_DAC_MASK);                                    \
-               WREG8(VGA_DAC_MASK, v);                                 \
-       } while (0)                                             \
-
-
-#define CIRRUS_MAX_FB_HEIGHT 4096
-#define CIRRUS_MAX_FB_WIDTH 4096
-
-#define CIRRUS_DPMS_CLEARED (-1)
-
-#define to_cirrus_crtc(x) container_of(x, struct cirrus_crtc, base)
-#define to_cirrus_encoder(x) container_of(x, struct cirrus_encoder, base)
-
-struct cirrus_crtc {
-       struct drm_crtc                 base;
-       int                             last_dpms;
-       bool                            enabled;
-};
-
-struct cirrus_fbdev;
-struct cirrus_mode_info {
-       struct cirrus_crtc              *crtc;
-       /* pointer to fbdev info structure */
-       struct cirrus_fbdev             *gfbdev;
-};
-
-struct cirrus_encoder {
-       struct drm_encoder              base;
-       int                             last_dpms;
-};
-
-struct cirrus_connector {
-       struct drm_connector            base;
-};
-
-struct cirrus_mc {
-       resource_size_t                 vram_size;
-       resource_size_t                 vram_base;
-};
-
-struct cirrus_device {
-       struct drm_device               *dev;
-       unsigned long                   flags;
-
-       resource_size_t                 rmmio_base;
-       resource_size_t                 rmmio_size;
-       void __iomem                    *rmmio;
-
-       struct cirrus_mc                        mc;
-       struct cirrus_mode_info         mode_info;
-
-       int                             num_crtc;
-       int fb_mtrr;
-
-       struct {
-               struct ttm_bo_device bdev;
-       } ttm;
-       bool mm_inited;
-};
-
-
-struct cirrus_fbdev {
-       struct drm_fb_helper helper; /* must be first */
-       struct drm_framebuffer *gfb;
-       void *sysram;
-       int size;
-       int x1, y1, x2, y2; /* dirty rect */
-       spinlock_t dirty_lock;
-};
-
-struct cirrus_bo {
-       struct ttm_buffer_object bo;
-       struct ttm_placement placement;
-       struct ttm_bo_kmap_obj kmap;
-       struct drm_gem_object gem;
-       struct ttm_place placements[3];
-       int pin_count;
-};
-#define gem_to_cirrus_bo(gobj) container_of((gobj), struct cirrus_bo, gem)
-
-static inline struct cirrus_bo *
-cirrus_bo(struct ttm_buffer_object *bo)
-{
-       return container_of(bo, struct cirrus_bo, bo);
-}
-
-
-#define to_cirrus_obj(x) container_of(x, struct cirrus_gem_object, base)
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
-                               /* cirrus_main.c */
-int cirrus_device_init(struct cirrus_device *cdev,
-                     struct drm_device *ddev,
-                     struct pci_dev *pdev,
-                     uint32_t flags);
-void cirrus_device_fini(struct cirrus_device *cdev);
-void cirrus_gem_free_object(struct drm_gem_object *obj);
-int cirrus_dumb_mmap_offset(struct drm_file *file,
-                           struct drm_device *dev,
-                           uint32_t handle,
-                           uint64_t *offset);
-int cirrus_gem_create(struct drm_device *dev,
-                  u32 size, bool iskernel,
-                     struct drm_gem_object **obj);
-int cirrus_dumb_create(struct drm_file *file,
-                   struct drm_device *dev,
-                      struct drm_mode_create_dumb *args);
-
-int cirrus_framebuffer_init(struct drm_device *dev,
-                           struct drm_framebuffer *gfb,
-                           const struct drm_mode_fb_cmd2 *mode_cmd,
-                           struct drm_gem_object *obj);
-
-bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
-                             int bpp, int pitch);
-
-                               /* cirrus_display.c */
-int cirrus_modeset_init(struct cirrus_device *cdev);
-void cirrus_modeset_fini(struct cirrus_device *cdev);
-
-                               /* cirrus_fbdev.c */
-int cirrus_fbdev_init(struct cirrus_device *cdev);
-void cirrus_fbdev_fini(struct cirrus_device *cdev);
-
-
-
-                               /* cirrus_irq.c */
-void cirrus_driver_irq_preinstall(struct drm_device *dev);
-int cirrus_driver_irq_postinstall(struct drm_device *dev);
-void cirrus_driver_irq_uninstall(struct drm_device *dev);
-irqreturn_t cirrus_driver_irq_handler(int irq, void *arg);
-
-                               /* cirrus_kms.c */
-int cirrus_driver_load(struct drm_device *dev, unsigned long flags);
-void cirrus_driver_unload(struct drm_device *dev);
-extern struct drm_ioctl_desc cirrus_ioctls[];
-extern int cirrus_max_ioctl;
-
-int cirrus_mm_init(struct cirrus_device *cirrus);
-void cirrus_mm_fini(struct cirrus_device *cirrus);
-void cirrus_ttm_placement(struct cirrus_bo *bo, int domain);
-int cirrus_bo_create(struct drm_device *dev, int size, int align,
-                    uint32_t flags, struct cirrus_bo **pcirrusbo);
-int cirrus_mmap(struct file *filp, struct vm_area_struct *vma);
-
-static inline int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
-{
-       int ret;
-
-       ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL);
-       if (ret) {
-               if (ret != -ERESTARTSYS && ret != -EBUSY)
-                       DRM_ERROR("reserve failed %p\n", bo);
-               return ret;
-       }
-       return 0;
-}
-
-static inline void cirrus_bo_unreserve(struct cirrus_bo *bo)
-{
-       ttm_bo_unreserve(&bo->bo);
-}
-
-int cirrus_bo_push_sysram(struct cirrus_bo *bo);
-int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr);
-
-extern int cirrus_bpp;
-
-#endif                         /* __CIRRUS_DRV_H__ */
 
+++ /dev/null
-/*
- * Copyright 2012 Red Hat
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License version 2. See the file COPYING in the main
- * directory of this archive for more details.
- *
- * Authors: Matthew Garrett
- *          Dave Airlie
- */
-#include <linux/module.h>
-#include <drm/drmP.h>
-#include <drm/drm_util.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "cirrus_drv.h"
-
-static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
-                            int x, int y, int width, int height)
-{
-       int i;
-       struct drm_gem_object *obj;
-       struct cirrus_bo *bo;
-       int src_offset, dst_offset;
-       int bpp = afbdev->gfb->format->cpp[0];
-       int ret = -EBUSY;
-       bool unmap = false;
-       bool store_for_later = false;
-       int x2, y2;
-       unsigned long flags;
-
-       obj = afbdev->gfb->obj[0];
-       bo = gem_to_cirrus_bo(obj);
-
-       /*
-        * try and reserve the BO, if we fail with busy
-        * then the BO is being moved and we should
-        * store up the damage until later.
-        */
-       if (drm_can_sleep())
-               ret = cirrus_bo_reserve(bo, true);
-       if (ret) {
-               if (ret != -EBUSY)
-                       return;
-               store_for_later = true;
-       }
-
-       x2 = x + width - 1;
-       y2 = y + height - 1;
-       spin_lock_irqsave(&afbdev->dirty_lock, flags);
-
-       if (afbdev->y1 < y)
-               y = afbdev->y1;
-       if (afbdev->y2 > y2)
-               y2 = afbdev->y2;
-       if (afbdev->x1 < x)
-               x = afbdev->x1;
-       if (afbdev->x2 > x2)
-               x2 = afbdev->x2;
-
-       if (store_for_later) {
-               afbdev->x1 = x;
-               afbdev->x2 = x2;
-               afbdev->y1 = y;
-               afbdev->y2 = y2;
-               spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
-               return;
-       }
-
-       afbdev->x1 = afbdev->y1 = INT_MAX;
-       afbdev->x2 = afbdev->y2 = 0;
-       spin_unlock_irqrestore(&afbdev->dirty_lock, flags);
-
-       if (!bo->kmap.virtual) {
-               ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
-               if (ret) {
-                       DRM_ERROR("failed to kmap fb updates\n");
-                       cirrus_bo_unreserve(bo);
-                       return;
-               }
-               unmap = true;
-       }
-       for (i = y; i < y + height; i++) {
-               /* assume equal stride for now */
-               src_offset = dst_offset = i * afbdev->gfb->pitches[0] + (x * bpp);
-               memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, width * bpp);
-
-       }
-       if (unmap)
-               ttm_bo_kunmap(&bo->kmap);
-
-       cirrus_bo_unreserve(bo);
-}
-
-static void cirrus_fillrect(struct fb_info *info,
-                        const struct fb_fillrect *rect)
-{
-       struct cirrus_fbdev *afbdev = info->par;
-       drm_fb_helper_sys_fillrect(info, rect);
-       cirrus_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
-                        rect->height);
-}
-
-static void cirrus_copyarea(struct fb_info *info,
-                        const struct fb_copyarea *area)
-{
-       struct cirrus_fbdev *afbdev = info->par;
-       drm_fb_helper_sys_copyarea(info, area);
-       cirrus_dirty_update(afbdev, area->dx, area->dy, area->width,
-                        area->height);
-}
-
-static void cirrus_imageblit(struct fb_info *info,
-                         const struct fb_image *image)
-{
-       struct cirrus_fbdev *afbdev = info->par;
-       drm_fb_helper_sys_imageblit(info, image);
-       cirrus_dirty_update(afbdev, image->dx, image->dy, image->width,
-                        image->height);
-}
-
-
-static struct fb_ops cirrusfb_ops = {
-       .owner = THIS_MODULE,
-       .fb_check_var = drm_fb_helper_check_var,
-       .fb_set_par = drm_fb_helper_set_par,
-       .fb_fillrect = cirrus_fillrect,
-       .fb_copyarea = cirrus_copyarea,
-       .fb_imageblit = cirrus_imageblit,
-       .fb_pan_display = drm_fb_helper_pan_display,
-       .fb_blank = drm_fb_helper_blank,
-       .fb_setcmap = drm_fb_helper_setcmap,
-};
-
-static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
-                              const struct drm_mode_fb_cmd2 *mode_cmd,
-                              struct drm_gem_object **gobj_p)
-{
-       struct drm_device *dev = afbdev->helper.dev;
-       struct cirrus_device *cdev = dev->dev_private;
-       u32 bpp;
-       u32 size;
-       struct drm_gem_object *gobj;
-       int ret = 0;
-
-       bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
-
-       if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
-                                     bpp, mode_cmd->pitches[0]))
-               return -EINVAL;
-
-       size = mode_cmd->pitches[0] * mode_cmd->height;
-       ret = cirrus_gem_create(dev, size, true, &gobj);
-       if (ret)
-               return ret;
-
-       *gobj_p = gobj;
-       return ret;
-}
-
-static int cirrusfb_create(struct drm_fb_helper *helper,
-                          struct drm_fb_helper_surface_size *sizes)
-{
-       struct cirrus_fbdev *gfbdev =
-               container_of(helper, struct cirrus_fbdev, helper);
-       struct cirrus_device *cdev = gfbdev->helper.dev->dev_private;
-       struct fb_info *info;
-       struct drm_framebuffer *fb;
-       struct drm_mode_fb_cmd2 mode_cmd;
-       void *sysram;
-       struct drm_gem_object *gobj = NULL;
-       int size, ret;
-
-       mode_cmd.width = sizes->surface_width;
-       mode_cmd.height = sizes->surface_height;
-       mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
-                                                         sizes->surface_depth);
-       size = mode_cmd.pitches[0] * mode_cmd.height;
-
-       ret = cirrusfb_create_object(gfbdev, &mode_cmd, &gobj);
-       if (ret) {
-               DRM_ERROR("failed to create fbcon backing object %d\n", ret);
-               return ret;
-       }
-
-       sysram = vmalloc(size);
-       if (!sysram)
-               return -ENOMEM;
-
-       info = drm_fb_helper_alloc_fbi(helper);
-       if (IS_ERR(info)) {
-               ret = PTR_ERR(info);
-               goto err_vfree;
-       }
-
-       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-       if (!fb) {
-               ret = -ENOMEM;
-               goto err_drm_gem_object_put_unlocked;
-       }
-
-       ret = cirrus_framebuffer_init(cdev->dev, fb, &mode_cmd, gobj);
-       if (ret)
-               goto err_kfree;
-
-       gfbdev->sysram = sysram;
-       gfbdev->size = size;
-       gfbdev->gfb = fb;
-
-       /* setup helper */
-       gfbdev->helper.fb = fb;
-
-       info->fbops = &cirrusfb_ops;
-
-       drm_fb_helper_fill_info(info, &gfbdev->helper, sizes);
-
-       /* setup aperture base/size for vesafb takeover */
-       info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
-       info->apertures->ranges[0].size = cdev->mc.vram_size;
-
-       info->fix.smem_start = cdev->dev->mode_config.fb_base;
-       info->fix.smem_len = cdev->mc.vram_size;
-
-       info->screen_base = sysram;
-       info->screen_size = size;
-
-       info->fix.mmio_start = 0;
-       info->fix.mmio_len = 0;
-
-       DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
-       DRM_INFO("vram aper at 0x%lX\n", (unsigned long)info->fix.smem_start);
-       DRM_INFO("size %lu\n", (unsigned long)info->fix.smem_len);
-       DRM_INFO("fb depth is %d\n", fb->format->depth);
-       DRM_INFO("   pitch is %d\n", fb->pitches[0]);
-
-       return 0;
-
-err_kfree:
-       kfree(fb);
-err_drm_gem_object_put_unlocked:
-       drm_gem_object_put_unlocked(gobj);
-err_vfree:
-       vfree(sysram);
-       return ret;
-}
-
-static int cirrus_fbdev_destroy(struct drm_device *dev,
-                               struct cirrus_fbdev *gfbdev)
-{
-       struct drm_framebuffer *gfb = gfbdev->gfb;
-
-       drm_helper_force_disable_all(dev);
-
-       drm_fb_helper_unregister_fbi(&gfbdev->helper);
-
-       vfree(gfbdev->sysram);
-       drm_fb_helper_fini(&gfbdev->helper);
-       if (gfb)
-               drm_framebuffer_put(gfb);
-
-       return 0;
-}
-
-static const struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
-       .fb_probe = cirrusfb_create,
-};
-
-int cirrus_fbdev_init(struct cirrus_device *cdev)
-{
-       struct cirrus_fbdev *gfbdev;
-       int ret;
-
-       /*bpp_sel = 8;*/
-       gfbdev = kzalloc(sizeof(struct cirrus_fbdev), GFP_KERNEL);
-       if (!gfbdev)
-               return -ENOMEM;
-
-       cdev->mode_info.gfbdev = gfbdev;
-       spin_lock_init(&gfbdev->dirty_lock);
-
-       drm_fb_helper_prepare(cdev->dev, &gfbdev->helper,
-                             &cirrus_fb_helper_funcs);
-
-       ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
-                                CIRRUSFB_CONN_LIMIT);
-       if (ret)
-               return ret;
-
-       ret = drm_fb_helper_single_add_all_connectors(&gfbdev->helper);
-       if (ret)
-               return ret;
-
-       /* disable all the possible outputs/crtcs before entering KMS mode */
-       drm_helper_disable_unused_functions(cdev->dev);
-
-       return drm_fb_helper_initial_config(&gfbdev->helper, cirrus_bpp);
-}
-
-void cirrus_fbdev_fini(struct cirrus_device *cdev)
-{
-       if (!cdev->mode_info.gfbdev)
-               return;
-
-       cirrus_fbdev_destroy(cdev->dev, cdev->mode_info.gfbdev);
-       kfree(cdev->mode_info.gfbdev);
-       cdev->mode_info.gfbdev = NULL;
-}
 
+++ /dev/null
-/*
- * Copyright 2012 Red Hat
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License version 2. See the file COPYING in the main
- * directory of this archive for more details.
- *
- * Authors: Matthew Garrett
- *          Dave Airlie
- */
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-
-#include "cirrus_drv.h"
-
-static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
-       .create_handle = drm_gem_fb_create_handle,
-       .destroy = drm_gem_fb_destroy,
-};
-
-int cirrus_framebuffer_init(struct drm_device *dev,
-                           struct drm_framebuffer *gfb,
-                           const struct drm_mode_fb_cmd2 *mode_cmd,
-                           struct drm_gem_object *obj)
-{
-       int ret;
-
-       drm_helper_mode_fill_fb_struct(dev, gfb, mode_cmd);
-       gfb->obj[0] = obj;
-       ret = drm_framebuffer_init(dev, gfb, &cirrus_fb_funcs);
-       if (ret) {
-               DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
-               return ret;
-       }
-       return 0;
-}
-
-static struct drm_framebuffer *
-cirrus_user_framebuffer_create(struct drm_device *dev,
-                              struct drm_file *filp,
-                              const struct drm_mode_fb_cmd2 *mode_cmd)
-{
-       struct cirrus_device *cdev = dev->dev_private;
-       struct drm_gem_object *obj;
-       struct drm_framebuffer *fb;
-       u32 bpp;
-       int ret;
-
-       bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
-
-       if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
-                                     bpp, mode_cmd->pitches[0]))
-               return ERR_PTR(-EINVAL);
-
-       obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
-       if (obj == NULL)
-               return ERR_PTR(-ENOENT);
-
-       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-       if (!fb) {
-               drm_gem_object_put_unlocked(obj);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       ret = cirrus_framebuffer_init(dev, fb, mode_cmd, obj);
-       if (ret) {
-               drm_gem_object_put_unlocked(obj);
-               kfree(fb);
-               return ERR_PTR(ret);
-       }
-       return fb;
-}
-
-static const struct drm_mode_config_funcs cirrus_mode_funcs = {
-       .fb_create = cirrus_user_framebuffer_create,
-};
-
-/* Unmap the framebuffer from the core and release the memory */
-static void cirrus_vram_fini(struct cirrus_device *cdev)
-{
-       iounmap(cdev->rmmio);
-       cdev->rmmio = NULL;
-       if (cdev->mc.vram_base)
-               release_mem_region(cdev->mc.vram_base, cdev->mc.vram_size);
-}
-
-/* Map the framebuffer from the card and configure the core */
-static int cirrus_vram_init(struct cirrus_device *cdev)
-{
-       /* BAR 0 is VRAM */
-       cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0);
-       cdev->mc.vram_size = pci_resource_len(cdev->dev->pdev, 0);
-
-       if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size,
-                               "cirrusdrmfb_vram")) {
-               DRM_ERROR("can't reserve VRAM\n");
-               return -ENXIO;
-       }
-
-       return 0;
-}
-
-/*
- * Our emulated hardware has two sets of memory. One is video RAM and can
- * simply be used as a linear framebuffer - the other provides mmio access
- * to the display registers. The latter can also be accessed via IO port
- * access, but we map the range and use mmio to program them instead
- */
-
-int cirrus_device_init(struct cirrus_device *cdev,
-                      struct drm_device *ddev,
-                      struct pci_dev *pdev, uint32_t flags)
-{
-       int ret;
-
-       cdev->dev = ddev;
-       cdev->flags = flags;
-
-       /* Hardcode the number of CRTCs to 1 */
-       cdev->num_crtc = 1;
-
-       /* BAR 0 is the framebuffer, BAR 1 contains registers */
-       cdev->rmmio_base = pci_resource_start(cdev->dev->pdev, 1);
-       cdev->rmmio_size = pci_resource_len(cdev->dev->pdev, 1);
-
-       if (!request_mem_region(cdev->rmmio_base, cdev->rmmio_size,
-                               "cirrusdrmfb_mmio")) {
-               DRM_ERROR("can't reserve mmio registers\n");
-               return -ENOMEM;
-       }
-
-       cdev->rmmio = ioremap(cdev->rmmio_base, cdev->rmmio_size);
-
-       if (cdev->rmmio == NULL)
-               return -ENOMEM;
-
-       ret = cirrus_vram_init(cdev);
-       if (ret) {
-               release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
-               return ret;
-       }
-
-       return 0;
-}
-
-void cirrus_device_fini(struct cirrus_device *cdev)
-{
-       release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
-       cirrus_vram_fini(cdev);
-}
-
-/*
- * Functions here will be called by the core once it's bound the driver to
- * a PCI device
- */
-
-int cirrus_driver_load(struct drm_device *dev, unsigned long flags)
-{
-       struct cirrus_device *cdev;
-       int r;
-
-       cdev = kzalloc(sizeof(struct cirrus_device), GFP_KERNEL);
-       if (cdev == NULL)
-               return -ENOMEM;
-       dev->dev_private = (void *)cdev;
-
-       r = cirrus_device_init(cdev, dev, dev->pdev, flags);
-       if (r) {
-               dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r);
-               goto out;
-       }
-
-       r = cirrus_mm_init(cdev);
-       if (r) {
-               dev_err(&dev->pdev->dev, "fatal err on mm init\n");
-               goto out;
-       }
-
-       /*
-        * cirrus_modeset_init() is initializing/registering the emulated fbdev
-        * and DRM internals can access/test some of the fields in
-        * mode_config->funcs as part of the fbdev registration process.
-        * Make sure dev->mode_config.funcs is properly set to avoid
-        * dereferencing a NULL pointer.
-        * FIXME: mode_config.funcs assignment should probably be done in
-        * cirrus_modeset_init() (that's a common pattern seen in other DRM
-        * drivers).
-        */
-       dev->mode_config.funcs = &cirrus_mode_funcs;
-       r = cirrus_modeset_init(cdev);
-       if (r) {
-               dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
-               goto out;
-       }
-
-       return 0;
-out:
-       cirrus_driver_unload(dev);
-       return r;
-}
-
-void cirrus_driver_unload(struct drm_device *dev)
-{
-       struct cirrus_device *cdev = dev->dev_private;
-
-       if (cdev == NULL)
-               return;
-       cirrus_modeset_fini(cdev);
-       cirrus_mm_fini(cdev);
-       cirrus_device_fini(cdev);
-       kfree(cdev);
-       dev->dev_private = NULL;
-}
-
-int cirrus_gem_create(struct drm_device *dev,
-                  u32 size, bool iskernel,
-                  struct drm_gem_object **obj)
-{
-       struct cirrus_bo *cirrusbo;
-       int ret;
-
-       *obj = NULL;
-
-       size = roundup(size, PAGE_SIZE);
-       if (size == 0)
-               return -EINVAL;
-
-       ret = cirrus_bo_create(dev, size, 0, 0, &cirrusbo);
-       if (ret) {
-               if (ret != -ERESTARTSYS)
-                       DRM_ERROR("failed to allocate GEM object\n");
-               return ret;
-       }
-       *obj = &cirrusbo->gem;
-       return 0;
-}
-
-int cirrus_dumb_create(struct drm_file *file,
-                   struct drm_device *dev,
-                   struct drm_mode_create_dumb *args)
-{
-       int ret;
-       struct drm_gem_object *gobj;
-       u32 handle;
-
-       args->pitch = args->width * ((args->bpp + 7) / 8);
-       args->size = args->pitch * args->height;
-
-       ret = cirrus_gem_create(dev, args->size, false,
-                            &gobj);
-       if (ret)
-               return ret;
-
-       ret = drm_gem_handle_create(file, gobj, &handle);
-       drm_gem_object_put_unlocked(gobj);
-       if (ret)
-               return ret;
-
-       args->handle = handle;
-       return 0;
-}
-
-static void cirrus_bo_unref(struct cirrus_bo **bo)
-{
-       struct ttm_buffer_object *tbo;
-
-       if ((*bo) == NULL)
-               return;
-
-       tbo = &((*bo)->bo);
-       ttm_bo_put(tbo);
-       *bo = NULL;
-}
-
-void cirrus_gem_free_object(struct drm_gem_object *obj)
-{
-       struct cirrus_bo *cirrus_bo = gem_to_cirrus_bo(obj);
-
-       cirrus_bo_unref(&cirrus_bo);
-}
-
-
-static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo)
-{
-       return drm_vma_node_offset_addr(&bo->bo.vma_node);
-}
-
-int
-cirrus_dumb_mmap_offset(struct drm_file *file,
-                    struct drm_device *dev,
-                    uint32_t handle,
-                    uint64_t *offset)
-{
-       struct drm_gem_object *obj;
-       struct cirrus_bo *bo;
-
-       obj = drm_gem_object_lookup(file, handle);
-       if (obj == NULL)
-               return -ENOENT;
-
-       bo = gem_to_cirrus_bo(obj);
-       *offset = cirrus_bo_mmap_offset(bo);
-
-       drm_gem_object_put_unlocked(obj);
-
-       return 0;
-}
-
-bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
-                             int bpp, int pitch)
-{
-       const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */
-       const int max_size = cdev->mc.vram_size;
-
-       if (bpp > cirrus_bpp)
-               return false;
-       if (bpp > 32)
-               return false;
-
-       if (pitch > max_pitch)
-               return false;
-
-       if (pitch * height > max_size)
-               return false;
-
-       return true;
-}
 
+++ /dev/null
-
-/*
- * Copyright 2012 Red Hat
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License version 2. See the file COPYING in the main
- * directory of this archive for more details.
- *
- * Authors: Matthew Garrett
- *          Dave Airlie
- *
- * Portions of this code derived from cirrusfb.c:
- * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
- *
- * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
- */
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drm_probe_helper.h>
-
-#include <video/cirrus.h>
-
-#include "cirrus_drv.h"
-
-#define CIRRUS_LUT_SIZE 256
-
-#define PALETTE_INDEX 0x8
-#define PALETTE_DATA 0x9
-
-/*
- * This file contains setup code for the CRTC.
- */
-
-/*
- * The DRM core requires DPMS functions, but they make little sense in our
- * case and so are just stubs
- */
-
-static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-       struct drm_device *dev = crtc->dev;
-       struct cirrus_device *cdev = dev->dev_private;
-       u8 sr01, gr0e;
-
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-               sr01 = 0x00;
-               gr0e = 0x00;
-               break;
-       case DRM_MODE_DPMS_STANDBY:
-               sr01 = 0x20;
-               gr0e = 0x02;
-               break;
-       case DRM_MODE_DPMS_SUSPEND:
-               sr01 = 0x20;
-               gr0e = 0x04;
-               break;
-       case DRM_MODE_DPMS_OFF:
-               sr01 = 0x20;
-               gr0e = 0x06;
-               break;
-       default:
-               return;
-       }
-
-       WREG8(SEQ_INDEX, 0x1);
-       sr01 |= RREG8(SEQ_DATA) & ~0x20;
-       WREG_SEQ(0x1, sr01);
-
-       WREG8(GFX_INDEX, 0xe);
-       gr0e |= RREG8(GFX_DATA) & ~0x06;
-       WREG_GFX(0xe, gr0e);
-}
-
-static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
-{
-       struct cirrus_device *cdev = crtc->dev->dev_private;
-       u32 addr;
-       u8 tmp;
-
-       addr = offset >> 2;
-       WREG_CRT(0x0c, (u8)((addr >> 8) & 0xff));
-       WREG_CRT(0x0d, (u8)(addr & 0xff));
-
-       WREG8(CRT_INDEX, 0x1b);
-       tmp = RREG8(CRT_DATA);
-       tmp &= 0xf2;
-       tmp |= (addr >> 16) & 0x01;
-       tmp |= (addr >> 15) & 0x0c;
-       WREG_CRT(0x1b, tmp);
-       WREG8(CRT_INDEX, 0x1d);
-       tmp = RREG8(CRT_DATA);
-       tmp &= 0x7f;
-       tmp |= (addr >> 12) & 0x80;
-       WREG_CRT(0x1d, tmp);
-}
-
-/* cirrus is different - we will force move buffers out of VRAM */
-static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
-                               struct drm_framebuffer *fb,
-                               int x, int y, int atomic)
-{
-       struct cirrus_device *cdev = crtc->dev->dev_private;
-       struct cirrus_bo *bo;
-       int ret;
-       u64 gpu_addr;
-
-       /* push the previous fb to system ram */
-       if (!atomic && fb) {
-               bo = gem_to_cirrus_bo(fb->obj[0]);
-               ret = cirrus_bo_reserve(bo, false);
-               if (ret)
-                       return ret;
-               cirrus_bo_push_sysram(bo);
-               cirrus_bo_unreserve(bo);
-       }
-
-       bo = gem_to_cirrus_bo(crtc->primary->fb->obj[0]);
-
-       ret = cirrus_bo_reserve(bo, false);
-       if (ret)
-               return ret;
-
-       ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
-       if (ret) {
-               cirrus_bo_unreserve(bo);
-               return ret;
-       }
-
-       if (cdev->mode_info.gfbdev->gfb == crtc->primary->fb) {
-               /* if pushing console in kmap it */
-               ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
-               if (ret)
-                       DRM_ERROR("failed to kmap fbcon\n");
-       }
-       cirrus_bo_unreserve(bo);
-
-       cirrus_set_start_address(crtc, (u32)gpu_addr);
-       return 0;
-}
-
-static int cirrus_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-                            struct drm_framebuffer *old_fb)
-{
-       return cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
-}
-
-/*
- * The meat of this driver. The core passes us a mode and we have to program
- * it. The modesetting here is the bare minimum required to satisfy the qemu
- * emulation of this hardware, and running this against a real device is
- * likely to result in an inadequately programmed mode. We've already had
- * the opportunity to modify the mode, so whatever we receive here should
- * be something that can be correctly programmed and displayed
- */
-static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
-                               struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode,
-                               int x, int y, struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct cirrus_device *cdev = dev->dev_private;
-       const struct drm_framebuffer *fb = crtc->primary->fb;
-       int hsyncstart, hsyncend, htotal, hdispend;
-       int vtotal, vdispend;
-       int tmp;
-       int sr07 = 0, hdr = 0;
-
-       htotal = mode->htotal / 8;
-       hsyncend = mode->hsync_end / 8;
-       hsyncstart = mode->hsync_start / 8;
-       hdispend = mode->hdisplay / 8;
-
-       vtotal = mode->vtotal;
-       vdispend = mode->vdisplay;
-
-       vdispend -= 1;
-       vtotal -= 2;
-
-       htotal -= 5;
-       hdispend -= 1;
-       hsyncstart += 1;
-       hsyncend += 1;
-
-       WREG_CRT(VGA_CRTC_V_SYNC_END, 0x20);
-       WREG_CRT(VGA_CRTC_H_TOTAL, htotal);
-       WREG_CRT(VGA_CRTC_H_DISP, hdispend);
-       WREG_CRT(VGA_CRTC_H_SYNC_START, hsyncstart);
-       WREG_CRT(VGA_CRTC_H_SYNC_END, hsyncend);
-       WREG_CRT(VGA_CRTC_V_TOTAL, vtotal & 0xff);
-       WREG_CRT(VGA_CRTC_V_DISP_END, vdispend & 0xff);
-
-       tmp = 0x40;
-       if ((vdispend + 1) & 512)
-               tmp |= 0x20;
-       WREG_CRT(VGA_CRTC_MAX_SCAN, tmp);
-
-       /*
-        * Overflow bits for values that don't fit in the standard registers
-        */
-       tmp = 16;
-       if (vtotal & 256)
-               tmp |= 1;
-       if (vdispend & 256)
-               tmp |= 2;
-       if ((vdispend + 1) & 256)
-               tmp |= 8;
-       if (vtotal & 512)
-               tmp |= 32;
-       if (vdispend & 512)
-               tmp |= 64;
-       WREG_CRT(VGA_CRTC_OVERFLOW, tmp);
-
-       tmp = 0;
-
-       /* More overflow bits */
-
-       if ((htotal + 5) & 64)
-               tmp |= 16;
-       if ((htotal + 5) & 128)
-               tmp |= 32;
-       if (vtotal & 256)
-               tmp |= 64;
-       if (vtotal & 512)
-               tmp |= 128;
-
-       WREG_CRT(CL_CRT1A, tmp);
-
-       /* Disable Hercules/CGA compatibility */
-       WREG_CRT(VGA_CRTC_MODE, 0x03);
-
-       WREG8(SEQ_INDEX, 0x7);
-       sr07 = RREG8(SEQ_DATA);
-       sr07 &= 0xe0;
-       hdr = 0;
-       switch (fb->format->cpp[0] * 8) {
-       case 8:
-               sr07 |= 0x11;
-               break;
-       case 16:
-               sr07 |= 0x17;
-               hdr = 0xc1;
-               break;
-       case 24:
-               sr07 |= 0x15;
-               hdr = 0xc5;
-               break;
-       case 32:
-               sr07 |= 0x19;
-               hdr = 0xc5;
-               break;
-       default:
-               return -1;
-       }
-
-       WREG_SEQ(0x7, sr07);
-
-       /* Program the pitch */
-       tmp = fb->pitches[0] / 8;
-       WREG_CRT(VGA_CRTC_OFFSET, tmp);
-
-       /* Enable extended blanking and pitch bits, and enable full memory */
-       tmp = 0x22;
-       tmp |= (fb->pitches[0] >> 7) & 0x10;
-       tmp |= (fb->pitches[0] >> 6) & 0x40;
-       WREG_CRT(0x1b, tmp);
-
-       /* Enable high-colour modes */
-       WREG_GFX(VGA_GFX_MODE, 0x40);
-
-       /* And set graphics mode */
-       WREG_GFX(VGA_GFX_MISC, 0x01);
-
-       WREG_HDR(hdr);
-       cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
-
-       /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
-       outb(0x20, 0x3c0);
-       return 0;
-}
-
-/*
- * This is called before a mode is programmed. A typical use might be to
- * enable DPMS during the programming to avoid seeing intermediate stages,
- * but that's not relevant to us
- */
-static void cirrus_crtc_prepare(struct drm_crtc *crtc)
-{
-}
-
-static void cirrus_crtc_load_lut(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct cirrus_device *cdev = dev->dev_private;
-       u16 *r, *g, *b;
-       int i;
-
-       if (!crtc->enabled)
-               return;
-
-       r = crtc->gamma_store;
-       g = r + crtc->gamma_size;
-       b = g + crtc->gamma_size;
-
-       for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
-               /* VGA registers */
-               WREG8(PALETTE_INDEX, i);
-               WREG8(PALETTE_DATA, *r++ >> 8);
-               WREG8(PALETTE_DATA, *g++ >> 8);
-               WREG8(PALETTE_DATA, *b++ >> 8);
-       }
-}
-
-/*
- * This is called after a mode is programmed. It should reverse anything done
- * by the prepare function
- */
-static void cirrus_crtc_commit(struct drm_crtc *crtc)
-{
-       cirrus_crtc_load_lut(crtc);
-}
-
-/*
- * The core can pass us a set of gamma values to program. We actually only
- * use this for 8-bit mode so can't perform smooth fades on deeper modes,
- * but it's a requirement that we provide the function
- */
-static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-                                u16 *blue, uint32_t size,
-                                struct drm_modeset_acquire_ctx *ctx)
-{
-       cirrus_crtc_load_lut(crtc);
-
-       return 0;
-}
-
-/* Simple cleanup function */
-static void cirrus_crtc_destroy(struct drm_crtc *crtc)
-{
-       struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
-
-       drm_crtc_cleanup(crtc);
-       kfree(cirrus_crtc);
-}
-
-/* These provide the minimum set of functions required to handle a CRTC */
-static const struct drm_crtc_funcs cirrus_crtc_funcs = {
-       .gamma_set = cirrus_crtc_gamma_set,
-       .set_config = drm_crtc_helper_set_config,
-       .destroy = cirrus_crtc_destroy,
-};
-
-static const struct drm_crtc_helper_funcs cirrus_helper_funcs = {
-       .dpms = cirrus_crtc_dpms,
-       .mode_set = cirrus_crtc_mode_set,
-       .mode_set_base = cirrus_crtc_mode_set_base,
-       .prepare = cirrus_crtc_prepare,
-       .commit = cirrus_crtc_commit,
-};
-
-/* CRTC setup */
-static const uint32_t cirrus_formats_16[] = {
-       DRM_FORMAT_RGB565,
-};
-
-static const uint32_t cirrus_formats_24[] = {
-       DRM_FORMAT_RGB888,
-       DRM_FORMAT_RGB565,
-};
-
-static const uint32_t cirrus_formats_32[] = {
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_ARGB8888,
-       DRM_FORMAT_RGB888,
-       DRM_FORMAT_RGB565,
-};
-
-static struct drm_plane *cirrus_primary_plane(struct drm_device *dev)
-{
-       const uint32_t *formats;
-       uint32_t nformats;
-       struct drm_plane *primary;
-       int ret;
-
-       switch (cirrus_bpp) {
-       case 16:
-               formats = cirrus_formats_16;
-               nformats = ARRAY_SIZE(cirrus_formats_16);
-               break;
-       case 24:
-               formats = cirrus_formats_24;
-               nformats = ARRAY_SIZE(cirrus_formats_24);
-               break;
-       case 32:
-               formats = cirrus_formats_32;
-               nformats = ARRAY_SIZE(cirrus_formats_32);
-               break;
-       default:
-               return NULL;
-       }
-
-       primary = kzalloc(sizeof(*primary), GFP_KERNEL);
-       if (primary == NULL) {
-               DRM_DEBUG_KMS("Failed to allocate primary plane\n");
-               return NULL;
-       }
-
-       ret = drm_universal_plane_init(dev, primary, 0,
-                                      &drm_primary_helper_funcs,
-                                      formats, nformats,
-                                      NULL,
-                                      DRM_PLANE_TYPE_PRIMARY, NULL);
-       if (ret) {
-               kfree(primary);
-               primary = NULL;
-       }
-
-       return primary;
-}
-
-static void cirrus_crtc_init(struct drm_device *dev)
-{
-       struct cirrus_device *cdev = dev->dev_private;
-       struct cirrus_crtc *cirrus_crtc;
-       struct drm_plane *primary;
-
-       cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) +
-                             (CIRRUSFB_CONN_LIMIT * sizeof(struct drm_connector *)),
-                             GFP_KERNEL);
-
-       if (cirrus_crtc == NULL)
-               return;
-
-       primary = cirrus_primary_plane(dev);
-       if (primary == NULL) {
-               kfree(cirrus_crtc);
-               return;
-       }
-
-       drm_crtc_init_with_planes(dev, &cirrus_crtc->base,
-                                 primary, NULL,
-                                 &cirrus_crtc_funcs, NULL);
-
-       drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE);
-       cdev->mode_info.crtc = cirrus_crtc;
-
-       drm_crtc_helper_add(&cirrus_crtc->base, &cirrus_helper_funcs);
-}
-
-static void cirrus_encoder_mode_set(struct drm_encoder *encoder,
-                               struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode)
-{
-}
-
-static void cirrus_encoder_dpms(struct drm_encoder *encoder, int state)
-{
-       return;
-}
-
-static void cirrus_encoder_prepare(struct drm_encoder *encoder)
-{
-}
-
-static void cirrus_encoder_commit(struct drm_encoder *encoder)
-{
-}
-
-static void cirrus_encoder_destroy(struct drm_encoder *encoder)
-{
-       struct cirrus_encoder *cirrus_encoder = to_cirrus_encoder(encoder);
-       drm_encoder_cleanup(encoder);
-       kfree(cirrus_encoder);
-}
-
-static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs = {
-       .dpms = cirrus_encoder_dpms,
-       .mode_set = cirrus_encoder_mode_set,
-       .prepare = cirrus_encoder_prepare,
-       .commit = cirrus_encoder_commit,
-};
-
-static const struct drm_encoder_funcs cirrus_encoder_encoder_funcs = {
-       .destroy = cirrus_encoder_destroy,
-};
-
-static struct drm_encoder *cirrus_encoder_init(struct drm_device *dev)
-{
-       struct drm_encoder *encoder;
-       struct cirrus_encoder *cirrus_encoder;
-
-       cirrus_encoder = kzalloc(sizeof(struct cirrus_encoder), GFP_KERNEL);
-       if (!cirrus_encoder)
-               return NULL;
-
-       encoder = &cirrus_encoder->base;
-       encoder->possible_crtcs = 0x1;
-
-       drm_encoder_init(dev, encoder, &cirrus_encoder_encoder_funcs,
-                        DRM_MODE_ENCODER_DAC, NULL);
-       drm_encoder_helper_add(encoder, &cirrus_encoder_helper_funcs);
-
-       return encoder;
-}
-
-
-static int cirrus_vga_get_modes(struct drm_connector *connector)
-{
-       int count;
-
-       /* Just add a static list of modes */
-       if (cirrus_bpp <= 24) {
-               count = drm_add_modes_noedid(connector, 1280, 1024);
-               drm_set_preferred_mode(connector, 1024, 768);
-       } else {
-               count = drm_add_modes_noedid(connector, 800, 600);
-               drm_set_preferred_mode(connector, 800, 600);
-       }
-       return count;
-}
-
-static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
-                                                 *connector)
-{
-       int enc_id = connector->encoder_ids[0];
-       /* pick the encoder ids */
-       if (enc_id)
-               return drm_encoder_find(connector->dev, NULL, enc_id);
-       return NULL;
-}
-
-static void cirrus_connector_destroy(struct drm_connector *connector)
-{
-       drm_connector_cleanup(connector);
-       kfree(connector);
-}
-
-static const struct drm_connector_helper_funcs cirrus_vga_connector_helper_funcs = {
-       .get_modes = cirrus_vga_get_modes,
-       .best_encoder = cirrus_connector_best_encoder,
-};
-
-static const struct drm_connector_funcs cirrus_vga_connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = cirrus_connector_destroy,
-};
-
-static struct drm_connector *cirrus_vga_init(struct drm_device *dev)
-{
-       struct drm_connector *connector;
-       struct cirrus_connector *cirrus_connector;
-
-       cirrus_connector = kzalloc(sizeof(struct cirrus_connector), GFP_KERNEL);
-       if (!cirrus_connector)
-               return NULL;
-
-       connector = &cirrus_connector->base;
-
-       drm_connector_init(dev, connector,
-                          &cirrus_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA);
-
-       drm_connector_helper_add(connector, &cirrus_vga_connector_helper_funcs);
-
-       drm_connector_register(connector);
-       return connector;
-}
-
-
-int cirrus_modeset_init(struct cirrus_device *cdev)
-{
-       struct drm_encoder *encoder;
-       struct drm_connector *connector;
-       int ret;
-
-       drm_mode_config_init(cdev->dev);
-
-       cdev->dev->mode_config.max_width = CIRRUS_MAX_FB_WIDTH;
-       cdev->dev->mode_config.max_height = CIRRUS_MAX_FB_HEIGHT;
-
-       cdev->dev->mode_config.fb_base = cdev->mc.vram_base;
-       cdev->dev->mode_config.preferred_depth = cirrus_bpp;
-       /* don't prefer a shadow on virt GPU */
-       cdev->dev->mode_config.prefer_shadow = 0;
-
-       cirrus_crtc_init(cdev->dev);
-
-       encoder = cirrus_encoder_init(cdev->dev);
-       if (!encoder) {
-               DRM_ERROR("cirrus_encoder_init failed\n");
-               return -1;
-       }
-
-       connector = cirrus_vga_init(cdev->dev);
-       if (!connector) {
-               DRM_ERROR("cirrus_vga_init failed\n");
-               return -1;
-       }
-
-       drm_connector_attach_encoder(connector, encoder);
-
-       ret = cirrus_fbdev_init(cdev);
-       if (ret) {
-               DRM_ERROR("cirrus_fbdev_init failed\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-void cirrus_modeset_fini(struct cirrus_device *cdev)
-{
-       cirrus_fbdev_fini(cdev);
-       drm_helper_force_disable_all(cdev->dev);
-       drm_mode_config_cleanup(cdev->dev);
-}
 
+++ /dev/null
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- */
-/*
- * Authors: Dave Airlie <airlied@redhat.com>
- */
-#include <drm/drmP.h>
-#include <drm/ttm/ttm_page_alloc.h>
-
-#include "cirrus_drv.h"
-
-static inline struct cirrus_device *
-cirrus_bdev(struct ttm_bo_device *bd)
-{
-       return container_of(bd, struct cirrus_device, ttm.bdev);
-}
-
-static void cirrus_bo_ttm_destroy(struct ttm_buffer_object *tbo)
-{
-       struct cirrus_bo *bo;
-
-       bo = container_of(tbo, struct cirrus_bo, bo);
-
-       drm_gem_object_release(&bo->gem);
-       kfree(bo);
-}
-
-static bool cirrus_ttm_bo_is_cirrus_bo(struct ttm_buffer_object *bo)
-{
-       if (bo->destroy == &cirrus_bo_ttm_destroy)
-               return true;
-       return false;
-}
-
-static int
-cirrus_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
-                    struct ttm_mem_type_manager *man)
-{
-       switch (type) {
-       case TTM_PL_SYSTEM:
-               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
-               man->available_caching = TTM_PL_MASK_CACHING;
-               man->default_caching = TTM_PL_FLAG_CACHED;
-               break;
-       case TTM_PL_VRAM:
-               man->func = &ttm_bo_manager_func;
-               man->flags = TTM_MEMTYPE_FLAG_FIXED |
-                       TTM_MEMTYPE_FLAG_MAPPABLE;
-               man->available_caching = TTM_PL_FLAG_UNCACHED |
-                       TTM_PL_FLAG_WC;
-               man->default_caching = TTM_PL_FLAG_WC;
-               break;
-       default:
-               DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void
-cirrus_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
-{
-       struct cirrus_bo *cirrusbo = cirrus_bo(bo);
-
-       if (!cirrus_ttm_bo_is_cirrus_bo(bo))
-               return;
-
-       cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_SYSTEM);
-       *pl = cirrusbo->placement;
-}
-
-static int cirrus_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
-{
-       struct cirrus_bo *cirrusbo = cirrus_bo(bo);
-
-       return drm_vma_node_verify_access(&cirrusbo->gem.vma_node,
-                                         filp->private_data);
-}
-
-static int cirrus_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
-                                 struct ttm_mem_reg *mem)
-{
-       struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
-       struct cirrus_device *cirrus = cirrus_bdev(bdev);
-
-       mem->bus.addr = NULL;
-       mem->bus.offset = 0;
-       mem->bus.size = mem->num_pages << PAGE_SHIFT;
-       mem->bus.base = 0;
-       mem->bus.is_iomem = false;
-       if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
-               return -EINVAL;
-       switch (mem->mem_type) {
-       case TTM_PL_SYSTEM:
-               /* system memory */
-               return 0;
-       case TTM_PL_VRAM:
-               mem->bus.offset = mem->start << PAGE_SHIFT;
-               mem->bus.base = pci_resource_start(cirrus->dev->pdev, 0);
-               mem->bus.is_iomem = true;
-               break;
-       default:
-               return -EINVAL;
-               break;
-       }
-       return 0;
-}
-
-static void cirrus_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
-{
-}
-
-static void cirrus_ttm_backend_destroy(struct ttm_tt *tt)
-{
-       ttm_tt_fini(tt);
-       kfree(tt);
-}
-
-static struct ttm_backend_func cirrus_tt_backend_func = {
-       .destroy = &cirrus_ttm_backend_destroy,
-};
-
-
-static struct ttm_tt *cirrus_ttm_tt_create(struct ttm_buffer_object *bo,
-                                          uint32_t page_flags)
-{
-       struct ttm_tt *tt;
-
-       tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
-       if (tt == NULL)
-               return NULL;
-       tt->func = &cirrus_tt_backend_func;
-       if (ttm_tt_init(tt, bo, page_flags)) {
-               kfree(tt);
-               return NULL;
-       }
-       return tt;
-}
-
-struct ttm_bo_driver cirrus_bo_driver = {
-       .ttm_tt_create = cirrus_ttm_tt_create,
-       .init_mem_type = cirrus_bo_init_mem_type,
-       .eviction_valuable = ttm_bo_eviction_valuable,
-       .evict_flags = cirrus_bo_evict_flags,
-       .move = NULL,
-       .verify_access = cirrus_bo_verify_access,
-       .io_mem_reserve = &cirrus_ttm_io_mem_reserve,
-       .io_mem_free = &cirrus_ttm_io_mem_free,
-};
-
-int cirrus_mm_init(struct cirrus_device *cirrus)
-{
-       int ret;
-       struct drm_device *dev = cirrus->dev;
-       struct ttm_bo_device *bdev = &cirrus->ttm.bdev;
-
-       ret = ttm_bo_device_init(&cirrus->ttm.bdev,
-                                &cirrus_bo_driver,
-                                dev->anon_inode->i_mapping,
-                                DRM_FILE_PAGE_OFFSET,
-                                true);
-       if (ret) {
-               DRM_ERROR("Error initialising bo driver; %d\n", ret);
-               return ret;
-       }
-
-       ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
-                            cirrus->mc.vram_size >> PAGE_SHIFT);
-       if (ret) {
-               DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
-               return ret;
-       }
-
-       arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0),
-                                  pci_resource_len(dev->pdev, 0));
-
-       cirrus->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
-                                          pci_resource_len(dev->pdev, 0));
-
-       cirrus->mm_inited = true;
-       return 0;
-}
-
-void cirrus_mm_fini(struct cirrus_device *cirrus)
-{
-       struct drm_device *dev = cirrus->dev;
-
-       if (!cirrus->mm_inited)
-               return;
-
-       ttm_bo_device_release(&cirrus->ttm.bdev);
-
-       arch_phys_wc_del(cirrus->fb_mtrr);
-       cirrus->fb_mtrr = 0;
-       arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
-                               pci_resource_len(dev->pdev, 0));
-}
-
-void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
-{
-       u32 c = 0;
-       unsigned i;
-       bo->placement.placement = bo->placements;
-       bo->placement.busy_placement = bo->placements;
-       if (domain & TTM_PL_FLAG_VRAM)
-               bo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
-       if (domain & TTM_PL_FLAG_SYSTEM)
-               bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
-       if (!c)
-               bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
-       bo->placement.num_placement = c;
-       bo->placement.num_busy_placement = c;
-       for (i = 0; i < c; ++i) {
-               bo->placements[i].fpfn = 0;
-               bo->placements[i].lpfn = 0;
-       }
-}
-
-int cirrus_bo_create(struct drm_device *dev, int size, int align,
-                 uint32_t flags, struct cirrus_bo **pcirrusbo)
-{
-       struct cirrus_device *cirrus = dev->dev_private;
-       struct cirrus_bo *cirrusbo;
-       size_t acc_size;
-       int ret;
-
-       cirrusbo = kzalloc(sizeof(struct cirrus_bo), GFP_KERNEL);
-       if (!cirrusbo)
-               return -ENOMEM;
-
-       ret = drm_gem_object_init(dev, &cirrusbo->gem, size);
-       if (ret) {
-               kfree(cirrusbo);
-               return ret;
-       }
-
-       cirrusbo->bo.bdev = &cirrus->ttm.bdev;
-
-       cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
-
-       acc_size = ttm_bo_dma_acc_size(&cirrus->ttm.bdev, size,
-                                      sizeof(struct cirrus_bo));
-
-       ret = ttm_bo_init(&cirrus->ttm.bdev, &cirrusbo->bo, size,
-                         ttm_bo_type_device, &cirrusbo->placement,
-                         align >> PAGE_SHIFT, false, acc_size,
-                         NULL, NULL, cirrus_bo_ttm_destroy);
-       if (ret)
-               return ret;
-
-       *pcirrusbo = cirrusbo;
-       return 0;
-}
-
-static inline u64 cirrus_bo_gpu_offset(struct cirrus_bo *bo)
-{
-       return bo->bo.offset;
-}
-
-int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr)
-{
-       struct ttm_operation_ctx ctx = { false, false };
-       int i, ret;
-
-       if (bo->pin_count) {
-               bo->pin_count++;
-               if (gpu_addr)
-                       *gpu_addr = cirrus_bo_gpu_offset(bo);
-       }
-
-       cirrus_ttm_placement(bo, pl_flag);
-       for (i = 0; i < bo->placement.num_placement; i++)
-               bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
-       ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
-       if (ret)
-               return ret;
-
-       bo->pin_count = 1;
-       if (gpu_addr)
-               *gpu_addr = cirrus_bo_gpu_offset(bo);
-       return 0;
-}
-
-int cirrus_bo_push_sysram(struct cirrus_bo *bo)
-{
-       struct ttm_operation_ctx ctx = { false, false };
-       int i, ret;
-       if (!bo->pin_count) {
-               DRM_ERROR("unpin bad %p\n", bo);
-               return 0;
-       }
-       bo->pin_count--;
-       if (bo->pin_count)
-               return 0;
-
-       if (bo->kmap.virtual)
-               ttm_bo_kunmap(&bo->kmap);
-
-       cirrus_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
-       for (i = 0; i < bo->placement.num_placement ; i++)
-               bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
-
-       ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
-       if (ret) {
-               DRM_ERROR("pushing to VRAM failed\n");
-               return ret;
-       }
-       return 0;
-}
-
-int cirrus_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       struct drm_file *file_priv;
-       struct cirrus_device *cirrus;
-
-       if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
-               return -EINVAL;
-
-       file_priv = filp->private_data;
-       cirrus = file_priv->minor->dev->dev_private;
-       return ttm_bo_mmap(filp, vma, &cirrus->ttm.bdev);
-}