diff options
Diffstat (limited to 'drivers/gpu/drm/tiny/cirrus.c')
-rw-r--r-- | drivers/gpu/drm/tiny/cirrus.c | 763 |
1 files changed, 0 insertions, 763 deletions
diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c deleted file mode 100644 index 4e3a152f897a..000000000000 --- a/drivers/gpu/drm/tiny/cirrus.c +++ /dev/null @@ -1,763 +0,0 @@ -/* 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/iosys-map.h> -#include <linux/module.h> -#include <linux/pci.h> - -#include <video/cirrus.h> -#include <video/vga.h> - -#include <drm/drm_aperture.h> -#include <drm/drm_atomic.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_edid.h> -#include <drm/drm_fbdev_generic.h> -#include <drm/drm_file.h> -#include <drm/drm_format_helper.h> -#include <drm/drm_fourcc.h> -#include <drm/drm_framebuffer.h> -#include <drm/drm_gem_atomic_helper.h> -#include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_gem_shmem_helper.h> -#include <drm/drm_ioctl.h> -#include <drm/drm_managed.h> -#include <drm/drm_modeset_helper_vtables.h> -#include <drm/drm_module.h> -#include <drm/drm_probe_helper.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; - - /* modesetting pipeline */ - struct drm_plane primary_plane; - struct drm_crtc crtc; - struct drm_encoder encoder; - struct drm_connector connector; - - /* HW resources */ - void __iomem *vram; - void __iomem *mmio; -}; - -#define to_cirrus(_dev) container_of(_dev, struct cirrus_device, dev) - -struct cirrus_primary_plane_state { - struct drm_shadow_plane_state base; - - /* HW scanout buffer */ - const struct drm_format_info *format; - unsigned int pitch; -}; - -static inline struct cirrus_primary_plane_state * -to_cirrus_primary_plane_state(struct drm_plane_state *plane_state) -{ - return container_of(plane_state, struct cirrus_primary_plane_state, base.base); -}; - -/* ------------------------------------------------------------------ */ -/* - * 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 const struct drm_format_info *cirrus_convert_to(struct drm_framebuffer *fb) -{ - if (fb->format->format == DRM_FORMAT_XRGB8888 && fb->pitches[0] > CIRRUS_MAX_PITCH) { - if (fb->width * 3 <= CIRRUS_MAX_PITCH) - /* convert from XR24 to RG24 */ - return drm_format_info(DRM_FORMAT_RGB888); - else - /* convert from XR24 to RG16 */ - return drm_format_info(DRM_FORMAT_RGB565); - } - return NULL; -} - -static const struct drm_format_info *cirrus_format(struct drm_framebuffer *fb) -{ - const struct drm_format_info *format = cirrus_convert_to(fb); - - if (format) - return format; - return fb->format; -} - -static int cirrus_pitch(struct drm_framebuffer *fb) -{ - const struct drm_format_info *format = cirrus_convert_to(fb); - - if (format) - return drm_format_info_min_pitch(format, 0, 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 void cirrus_mode_set(struct cirrus_device *cirrus, - struct drm_display_mode *mode) -{ - int hsyncstart, hsyncend, htotal, hdispend; - int vtotal, vdispend; - int tmp; - - 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); -} - -static void cirrus_format_set(struct cirrus_device *cirrus, - const struct drm_format_info *format) -{ - u8 sr07, hdr; - - sr07 = rreg_seq(cirrus, 0x07); - sr07 &= 0xe0; - - switch (format->format) { - case DRM_FORMAT_C8: - sr07 |= 0x11; - hdr = 0x00; - break; - case DRM_FORMAT_RGB565: - sr07 |= 0x17; - hdr = 0xc1; - break; - case DRM_FORMAT_RGB888: - sr07 |= 0x15; - hdr = 0xc5; - break; - case DRM_FORMAT_XRGB8888: - sr07 |= 0x19; - hdr = 0xc5; - break; - default: - return; - } - - wreg_seq(cirrus, 0x7, sr07); - - /* 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); -} - -static void cirrus_pitch_set(struct cirrus_device *cirrus, unsigned int pitch) -{ - u8 cr13, cr1b; - - /* Program the pitch */ - cr13 = pitch / 8; - wreg_crt(cirrus, VGA_CRTC_OFFSET, cr13); - - /* Enable extended blanking and pitch bits, and enable full memory */ - cr1b = 0x22; - cr1b |= (pitch >> 7) & 0x10; - cr1b |= (pitch >> 6) & 0x40; - wreg_crt(cirrus, 0x1b, cr1b); - - cirrus_set_start_address(cirrus, 0); -} - -/* ------------------------------------------------------------------ */ -/* cirrus display pipe */ - -static const uint32_t cirrus_primary_plane_formats[] = { - DRM_FORMAT_RGB565, - DRM_FORMAT_RGB888, - DRM_FORMAT_XRGB8888, -}; - -static const uint64_t cirrus_primary_plane_format_modifiers[] = { - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - -static int cirrus_primary_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_atomic_state *state) -{ - struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); - struct cirrus_primary_plane_state *new_primary_plane_state = - to_cirrus_primary_plane_state(new_plane_state); - struct drm_framebuffer *fb = new_plane_state->fb; - struct drm_crtc *new_crtc = new_plane_state->crtc; - struct drm_crtc_state *new_crtc_state = NULL; - int ret; - unsigned int pitch; - - if (new_crtc) - new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); - - ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, - DRM_PLANE_NO_SCALING, - DRM_PLANE_NO_SCALING, - false, false); - if (ret) - return ret; - else if (!new_plane_state->visible) - return 0; - - pitch = cirrus_pitch(fb); - - /* validate size constraints */ - if (pitch > CIRRUS_MAX_PITCH) - return -EINVAL; - else if (pitch * fb->height > CIRRUS_VRAM_SIZE) - return -EINVAL; - - new_primary_plane_state->format = cirrus_format(fb); - new_primary_plane_state->pitch = pitch; - - return 0; -} - -static void cirrus_primary_plane_helper_atomic_update(struct drm_plane *plane, - struct drm_atomic_state *state) -{ - struct cirrus_device *cirrus = to_cirrus(plane->dev); - struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); - struct cirrus_primary_plane_state *primary_plane_state = - to_cirrus_primary_plane_state(plane_state); - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); - struct drm_framebuffer *fb = plane_state->fb; - const struct drm_format_info *format = primary_plane_state->format; - unsigned int pitch = primary_plane_state->pitch; - struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); - struct cirrus_primary_plane_state *old_primary_plane_state = - to_cirrus_primary_plane_state(old_plane_state); - struct iosys_map vaddr = IOSYS_MAP_INIT_VADDR_IOMEM(cirrus->vram); - struct drm_atomic_helper_damage_iter iter; - struct drm_rect damage; - int idx; - - if (!fb) - return; - - if (!drm_dev_enter(&cirrus->dev, &idx)) - return; - - if (old_primary_plane_state->format != format) - cirrus_format_set(cirrus, format); - if (old_primary_plane_state->pitch != pitch) - cirrus_pitch_set(cirrus, pitch); - - drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state); - drm_atomic_for_each_plane_damage(&iter, &damage) { - unsigned int offset = drm_fb_clip_offset(pitch, format, &damage); - struct iosys_map dst = IOSYS_MAP_INIT_OFFSET(&vaddr, offset); - - drm_fb_blit(&dst, &pitch, format->format, shadow_plane_state->data, fb, - &damage, &shadow_plane_state->fmtcnv_state); - } - - drm_dev_exit(idx); -} - -static const struct drm_plane_helper_funcs cirrus_primary_plane_helper_funcs = { - DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, - .atomic_check = cirrus_primary_plane_helper_atomic_check, - .atomic_update = cirrus_primary_plane_helper_atomic_update, -}; - -static struct drm_plane_state * -cirrus_primary_plane_atomic_duplicate_state(struct drm_plane *plane) -{ - struct drm_plane_state *plane_state = plane->state; - struct cirrus_primary_plane_state *primary_plane_state = - to_cirrus_primary_plane_state(plane_state); - struct cirrus_primary_plane_state *new_primary_plane_state; - struct drm_shadow_plane_state *new_shadow_plane_state; - - if (!plane_state) - return NULL; - - new_primary_plane_state = kzalloc(sizeof(*new_primary_plane_state), GFP_KERNEL); - if (!new_primary_plane_state) - return NULL; - new_shadow_plane_state = &new_primary_plane_state->base; - - __drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state); - new_primary_plane_state->format = primary_plane_state->format; - new_primary_plane_state->pitch = primary_plane_state->pitch; - - return &new_shadow_plane_state->base; -} - -static void cirrus_primary_plane_atomic_destroy_state(struct drm_plane *plane, - struct drm_plane_state *plane_state) -{ - struct cirrus_primary_plane_state *primary_plane_state = - to_cirrus_primary_plane_state(plane_state); - - __drm_gem_destroy_shadow_plane_state(&primary_plane_state->base); - kfree(primary_plane_state); -} - -static void cirrus_reset_primary_plane(struct drm_plane *plane) -{ - struct cirrus_primary_plane_state *primary_plane_state; - - if (plane->state) { - cirrus_primary_plane_atomic_destroy_state(plane, plane->state); - plane->state = NULL; /* must be set to NULL here */ - } - - primary_plane_state = kzalloc(sizeof(*primary_plane_state), GFP_KERNEL); - if (!primary_plane_state) - return; - __drm_gem_reset_shadow_plane(plane, &primary_plane_state->base); -} - -static const struct drm_plane_funcs cirrus_primary_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_plane_cleanup, - .reset = cirrus_reset_primary_plane, - .atomic_duplicate_state = cirrus_primary_plane_atomic_duplicate_state, - .atomic_destroy_state = cirrus_primary_plane_atomic_destroy_state, -}; - -static int cirrus_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) -{ - struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); - int ret; - - if (!crtc_state->enable) - return 0; - - ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state); - if (ret) - return ret; - - return 0; -} - -static void cirrus_crtc_helper_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) -{ - struct cirrus_device *cirrus = to_cirrus(crtc->dev); - struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); - int idx; - - if (!drm_dev_enter(&cirrus->dev, &idx)) - return; - - cirrus_mode_set(cirrus, &crtc_state->mode); - - /* Unblank (needed on S3 resume, vgabios doesn't do it then) */ - outb(VGA_AR_ENABLE_DISPLAY, VGA_ATT_W); - - drm_dev_exit(idx); -} - -static const struct drm_crtc_helper_funcs cirrus_crtc_helper_funcs = { - .atomic_check = cirrus_crtc_helper_atomic_check, - .atomic_enable = cirrus_crtc_helper_atomic_enable, -}; - -static const struct drm_crtc_funcs cirrus_crtc_funcs = { - .reset = drm_atomic_helper_crtc_reset, - .destroy = drm_crtc_cleanup, - .set_config = drm_atomic_helper_set_config, - .page_flip = drm_atomic_helper_page_flip, - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, -}; - -static const struct drm_encoder_funcs cirrus_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - -static int cirrus_connector_helper_get_modes(struct drm_connector *connector) -{ - int count; - - count = drm_add_modes_noedid(connector, - connector->dev->mode_config.max_width, - connector->dev->mode_config.max_height); - drm_set_preferred_mode(connector, 1024, 768); - return count; -} - -static const struct drm_connector_helper_funcs cirrus_connector_helper_funcs = { - .get_modes = cirrus_connector_helper_get_modes, -}; - -static const struct drm_connector_funcs cirrus_connector_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_pipe_init(struct cirrus_device *cirrus) -{ - struct drm_device *dev = &cirrus->dev; - struct drm_plane *primary_plane; - struct drm_crtc *crtc; - struct drm_encoder *encoder; - struct drm_connector *connector; - int ret; - - primary_plane = &cirrus->primary_plane; - ret = drm_universal_plane_init(dev, primary_plane, 0, - &cirrus_primary_plane_funcs, - cirrus_primary_plane_formats, - ARRAY_SIZE(cirrus_primary_plane_formats), - cirrus_primary_plane_format_modifiers, - DRM_PLANE_TYPE_PRIMARY, NULL); - if (ret) - return ret; - drm_plane_helper_add(primary_plane, &cirrus_primary_plane_helper_funcs); - drm_plane_enable_fb_damage_clips(primary_plane); - - crtc = &cirrus->crtc; - ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, - &cirrus_crtc_funcs, NULL); - if (ret) - return ret; - drm_crtc_helper_add(crtc, &cirrus_crtc_helper_funcs); - - encoder = &cirrus->encoder; - ret = drm_encoder_init(dev, encoder, &cirrus_encoder_funcs, - DRM_MODE_ENCODER_DAC, NULL); - if (ret) - return ret; - encoder->possible_crtcs = drm_crtc_mask(crtc); - - connector = &cirrus->connector; - ret = drm_connector_init(dev, connector, &cirrus_connector_funcs, - DRM_MODE_CONNECTOR_VGA); - if (ret) - return ret; - drm_connector_helper_add(connector, &cirrus_connector_helper_funcs); - - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) - return ret; - - return 0; -} - -/* ------------------------------------------------------------------ */ -/* cirrus framebuffers & mode config */ - -static enum drm_mode_status cirrus_mode_config_mode_valid(struct drm_device *dev, - const struct drm_display_mode *mode) -{ - const struct drm_format_info *format = drm_format_info(DRM_FORMAT_XRGB8888); - uint64_t pitch = drm_format_info_min_pitch(format, 0, mode->hdisplay); - - if (pitch * mode->vdisplay > CIRRUS_VRAM_SIZE) - return MODE_MEM; - - return MODE_OK; -} - -static const struct drm_mode_config_funcs cirrus_mode_config_funcs = { - .fb_create = drm_gem_fb_create_with_dirty, - .mode_valid = cirrus_mode_config_mode_valid, - .atomic_check = drm_atomic_helper_check, - .atomic_commit = drm_atomic_helper_commit, -}; - -static int cirrus_mode_config_init(struct cirrus_device *cirrus) -{ - struct drm_device *dev = &cirrus->dev; - int ret; - - ret = drmm_mode_config_init(dev); - if (ret) - return ret; - - 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; - - return 0; -} - -/* ------------------------------------------------------------------ */ - -DEFINE_DRM_GEM_FOPS(cirrus_fops); - -static const struct drm_driver cirrus_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, - - .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_aperture_remove_conflicting_pci_framebuffers(pdev, &cirrus_driver); - if (ret) - return ret; - - ret = pcim_enable_device(pdev); - if (ret) - return ret; - - ret = pci_request_regions(pdev, DRIVER_NAME); - if (ret) - return ret; - - ret = -ENOMEM; - cirrus = devm_drm_dev_alloc(&pdev->dev, &cirrus_driver, - struct cirrus_device, dev); - if (IS_ERR(cirrus)) - return PTR_ERR(cirrus); - - dev = &cirrus->dev; - - cirrus->vram = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - if (cirrus->vram == NULL) - return -ENOMEM; - - cirrus->mmio = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); - if (cirrus->mmio == NULL) - return -ENOMEM; - - ret = cirrus_mode_config_init(cirrus); - if (ret) - return ret; - - ret = cirrus_pipe_init(cirrus); - if (ret < 0) - return ret; - - drm_mode_config_reset(dev); - - pci_set_drvdata(pdev, dev); - ret = drm_dev_register(dev, 0); - if (ret) - return ret; - - drm_fbdev_generic_setup(dev, 16); - return 0; -} - -static void cirrus_pci_remove(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - - drm_dev_unplug(dev); - drm_atomic_helper_shutdown(dev); -} - -static void cirrus_pci_shutdown(struct pci_dev *pdev) -{ - drm_atomic_helper_shutdown(pci_get_drvdata(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, - .shutdown = cirrus_pci_shutdown, -}; - -drm_module_pci_driver(cirrus_pci_driver) - -MODULE_DEVICE_TABLE(pci, pciidlist); -MODULE_LICENSE("GPL"); |