diff options
-rw-r--r-- | drivers/gpu/drm/cirrus/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/cirrus/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/cirrus/cirrus.c | 657 | ||||
-rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_drv.c | 161 | ||||
-rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_drv.h | 251 | ||||
-rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_fbdev.c | 309 | ||||
-rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_main.c | 328 | ||||
-rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_mode.c | 617 | ||||
-rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_ttm.c | 343 |
9 files changed, 658 insertions, 2013 deletions
diff --git a/drivers/gpu/drm/cirrus/Kconfig b/drivers/gpu/drm/cirrus/Kconfig index fc78c90ee931..dd4f52a0bc1c 100644 --- a/drivers/gpu/drm/cirrus/Kconfig +++ b/drivers/gpu/drm/cirrus/Kconfig @@ -2,7 +2,7 @@ config DRM_CIRRUS_QEMU 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 diff --git a/drivers/gpu/drm/cirrus/Makefile b/drivers/gpu/drm/cirrus/Makefile index 919c0a336c97..acf8971d37a1 100644 --- a/drivers/gpu/drm/cirrus/Makefile +++ b/drivers/gpu/drm/cirrus/Makefile @@ -1,4 +1 @@ -cirrus-y := cirrus_main.o cirrus_mode.o \ - cirrus_drv.o cirrus_fbdev.o cirrus_ttm.o - obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o diff --git a/drivers/gpu/drm/cirrus/cirrus.c b/drivers/gpu/drm/cirrus/cirrus.c new file mode 100644 index 000000000000..5095b8ce52c2 --- /dev/null +++ b/drivers/gpu/drm/cirrus/cirrus.c @@ -0,0 +1,657 @@ +/* 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"); diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c deleted file mode 100644 index 8ec880f3a322..000000000000 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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"); diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h deleted file mode 100644 index 828b150cdb20..000000000000 --- a/drivers/gpu/drm/cirrus/cirrus_drv.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * 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__ */ diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c deleted file mode 100644 index 2e6128069fc3..000000000000 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright 2012 Red Hat - * - * This file is subject to the |