Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Copyright 2012-2019 Red Hat
0004  *
0005  * This file is subject to the terms and conditions of the GNU General
0006  * Public License version 2. See the file COPYING in the main
0007  * directory of this archive for more details.
0008  *
0009  * Authors: Matthew Garrett
0010  *      Dave Airlie
0011  *      Gerd Hoffmann
0012  *
0013  * Portions of this code derived from cirrusfb.c:
0014  * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
0015  *
0016  * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
0017  */
0018 
0019 #include <linux/iosys-map.h>
0020 #include <linux/module.h>
0021 #include <linux/pci.h>
0022 
0023 #include <video/cirrus.h>
0024 #include <video/vga.h>
0025 
0026 #include <drm/drm_aperture.h>
0027 #include <drm/drm_atomic_helper.h>
0028 #include <drm/drm_atomic_state_helper.h>
0029 #include <drm/drm_connector.h>
0030 #include <drm/drm_damage_helper.h>
0031 #include <drm/drm_drv.h>
0032 #include <drm/drm_edid.h>
0033 #include <drm/drm_fb_helper.h>
0034 #include <drm/drm_file.h>
0035 #include <drm/drm_format_helper.h>
0036 #include <drm/drm_fourcc.h>
0037 #include <drm/drm_framebuffer.h>
0038 #include <drm/drm_gem_atomic_helper.h>
0039 #include <drm/drm_gem_framebuffer_helper.h>
0040 #include <drm/drm_gem_shmem_helper.h>
0041 #include <drm/drm_ioctl.h>
0042 #include <drm/drm_managed.h>
0043 #include <drm/drm_modeset_helper_vtables.h>
0044 #include <drm/drm_module.h>
0045 #include <drm/drm_probe_helper.h>
0046 #include <drm/drm_simple_kms_helper.h>
0047 
0048 #define DRIVER_NAME "cirrus"
0049 #define DRIVER_DESC "qemu cirrus vga"
0050 #define DRIVER_DATE "2019"
0051 #define DRIVER_MAJOR 2
0052 #define DRIVER_MINOR 0
0053 
0054 #define CIRRUS_MAX_PITCH (0x1FF << 3)      /* (4096 - 1) & ~111b bytes */
0055 #define CIRRUS_VRAM_SIZE (4 * 1024 * 1024) /* 4 MB */
0056 
0057 struct cirrus_device {
0058     struct drm_device          dev;
0059     struct drm_simple_display_pipe pipe;
0060     struct drm_connector           conn;
0061     unsigned int               cpp;
0062     unsigned int               pitch;
0063     void __iomem               *vram;
0064     void __iomem               *mmio;
0065 };
0066 
0067 #define to_cirrus(_dev) container_of(_dev, struct cirrus_device, dev)
0068 
0069 /* ------------------------------------------------------------------ */
0070 /*
0071  * The meat of this driver. The core passes us a mode and we have to program
0072  * it. The modesetting here is the bare minimum required to satisfy the qemu
0073  * emulation of this hardware, and running this against a real device is
0074  * likely to result in an inadequately programmed mode. We've already had
0075  * the opportunity to modify the mode, so whatever we receive here should
0076  * be something that can be correctly programmed and displayed
0077  */
0078 
0079 #define SEQ_INDEX 4
0080 #define SEQ_DATA 5
0081 
0082 static u8 rreg_seq(struct cirrus_device *cirrus, u8 reg)
0083 {
0084     iowrite8(reg, cirrus->mmio + SEQ_INDEX);
0085     return ioread8(cirrus->mmio + SEQ_DATA);
0086 }
0087 
0088 static void wreg_seq(struct cirrus_device *cirrus, u8 reg, u8 val)
0089 {
0090     iowrite8(reg, cirrus->mmio + SEQ_INDEX);
0091     iowrite8(val, cirrus->mmio + SEQ_DATA);
0092 }
0093 
0094 #define CRT_INDEX 0x14
0095 #define CRT_DATA 0x15
0096 
0097 static u8 rreg_crt(struct cirrus_device *cirrus, u8 reg)
0098 {
0099     iowrite8(reg, cirrus->mmio + CRT_INDEX);
0100     return ioread8(cirrus->mmio + CRT_DATA);
0101 }
0102 
0103 static void wreg_crt(struct cirrus_device *cirrus, u8 reg, u8 val)
0104 {
0105     iowrite8(reg, cirrus->mmio + CRT_INDEX);
0106     iowrite8(val, cirrus->mmio + CRT_DATA);
0107 }
0108 
0109 #define GFX_INDEX 0xe
0110 #define GFX_DATA 0xf
0111 
0112 static void wreg_gfx(struct cirrus_device *cirrus, u8 reg, u8 val)
0113 {
0114     iowrite8(reg, cirrus->mmio + GFX_INDEX);
0115     iowrite8(val, cirrus->mmio + GFX_DATA);
0116 }
0117 
0118 #define VGA_DAC_MASK  0x06
0119 
0120 static void wreg_hdr(struct cirrus_device *cirrus, u8 val)
0121 {
0122     ioread8(cirrus->mmio + VGA_DAC_MASK);
0123     ioread8(cirrus->mmio + VGA_DAC_MASK);
0124     ioread8(cirrus->mmio + VGA_DAC_MASK);
0125     ioread8(cirrus->mmio + VGA_DAC_MASK);
0126     iowrite8(val, cirrus->mmio + VGA_DAC_MASK);
0127 }
0128 
0129 static int cirrus_convert_to(struct drm_framebuffer *fb)
0130 {
0131     if (fb->format->cpp[0] == 4 && fb->pitches[0] > CIRRUS_MAX_PITCH) {
0132         if (fb->width * 3 <= CIRRUS_MAX_PITCH)
0133             /* convert from XR24 to RG24 */
0134             return 3;
0135         else
0136             /* convert from XR24 to RG16 */
0137             return 2;
0138     }
0139     return 0;
0140 }
0141 
0142 static int cirrus_cpp(struct drm_framebuffer *fb)
0143 {
0144     int convert_cpp = cirrus_convert_to(fb);
0145 
0146     if (convert_cpp)
0147         return convert_cpp;
0148     return fb->format->cpp[0];
0149 }
0150 
0151 static int cirrus_pitch(struct drm_framebuffer *fb)
0152 {
0153     int convert_cpp = cirrus_convert_to(fb);
0154 
0155     if (convert_cpp)
0156         return convert_cpp * fb->width;
0157     return fb->pitches[0];
0158 }
0159 
0160 static void cirrus_set_start_address(struct cirrus_device *cirrus, u32 offset)
0161 {
0162     int idx;
0163     u32 addr;
0164     u8 tmp;
0165 
0166     if (!drm_dev_enter(&cirrus->dev, &idx))
0167         return;
0168 
0169     addr = offset >> 2;
0170     wreg_crt(cirrus, 0x0c, (u8)((addr >> 8) & 0xff));
0171     wreg_crt(cirrus, 0x0d, (u8)(addr & 0xff));
0172 
0173     tmp = rreg_crt(cirrus, 0x1b);
0174     tmp &= 0xf2;
0175     tmp |= (addr >> 16) & 0x01;
0176     tmp |= (addr >> 15) & 0x0c;
0177     wreg_crt(cirrus, 0x1b, tmp);
0178 
0179     tmp = rreg_crt(cirrus, 0x1d);
0180     tmp &= 0x7f;
0181     tmp |= (addr >> 12) & 0x80;
0182     wreg_crt(cirrus, 0x1d, tmp);
0183 
0184     drm_dev_exit(idx);
0185 }
0186 
0187 static int cirrus_mode_set(struct cirrus_device *cirrus,
0188                struct drm_display_mode *mode,
0189                struct drm_framebuffer *fb)
0190 {
0191     int hsyncstart, hsyncend, htotal, hdispend;
0192     int vtotal, vdispend;
0193     int tmp, idx;
0194     int sr07 = 0, hdr = 0;
0195 
0196     if (!drm_dev_enter(&cirrus->dev, &idx))
0197         return -1;
0198 
0199     htotal = mode->htotal / 8;
0200     hsyncend = mode->hsync_end / 8;
0201     hsyncstart = mode->hsync_start / 8;
0202     hdispend = mode->hdisplay / 8;
0203 
0204     vtotal = mode->vtotal;
0205     vdispend = mode->vdisplay;
0206 
0207     vdispend -= 1;
0208     vtotal -= 2;
0209 
0210     htotal -= 5;
0211     hdispend -= 1;
0212     hsyncstart += 1;
0213     hsyncend += 1;
0214 
0215     wreg_crt(cirrus, VGA_CRTC_V_SYNC_END, 0x20);
0216     wreg_crt(cirrus, VGA_CRTC_H_TOTAL, htotal);
0217     wreg_crt(cirrus, VGA_CRTC_H_DISP, hdispend);
0218     wreg_crt(cirrus, VGA_CRTC_H_SYNC_START, hsyncstart);
0219     wreg_crt(cirrus, VGA_CRTC_H_SYNC_END, hsyncend);
0220     wreg_crt(cirrus, VGA_CRTC_V_TOTAL, vtotal & 0xff);
0221     wreg_crt(cirrus, VGA_CRTC_V_DISP_END, vdispend & 0xff);
0222 
0223     tmp = 0x40;
0224     if ((vdispend + 1) & 512)
0225         tmp |= 0x20;
0226     wreg_crt(cirrus, VGA_CRTC_MAX_SCAN, tmp);
0227 
0228     /*
0229      * Overflow bits for values that don't fit in the standard registers
0230      */
0231     tmp = 0x10;
0232     if (vtotal & 0x100)
0233         tmp |= 0x01;
0234     if (vdispend & 0x100)
0235         tmp |= 0x02;
0236     if ((vdispend + 1) & 0x100)
0237         tmp |= 0x08;
0238     if (vtotal & 0x200)
0239         tmp |= 0x20;
0240     if (vdispend & 0x200)
0241         tmp |= 0x40;
0242     wreg_crt(cirrus, VGA_CRTC_OVERFLOW, tmp);
0243 
0244     tmp = 0;
0245 
0246     /* More overflow bits */
0247 
0248     if ((htotal + 5) & 0x40)
0249         tmp |= 0x10;
0250     if ((htotal + 5) & 0x80)
0251         tmp |= 0x20;
0252     if (vtotal & 0x100)
0253         tmp |= 0x40;
0254     if (vtotal & 0x200)
0255         tmp |= 0x80;
0256 
0257     wreg_crt(cirrus, CL_CRT1A, tmp);
0258 
0259     /* Disable Hercules/CGA compatibility */
0260     wreg_crt(cirrus, VGA_CRTC_MODE, 0x03);
0261 
0262     sr07 = rreg_seq(cirrus, 0x07);
0263     sr07 &= 0xe0;
0264     hdr = 0;
0265 
0266     cirrus->cpp = cirrus_cpp(fb);
0267     switch (cirrus->cpp * 8) {
0268     case 8:
0269         sr07 |= 0x11;
0270         break;
0271     case 16:
0272         sr07 |= 0x17;
0273         hdr = 0xc1;
0274         break;
0275     case 24:
0276         sr07 |= 0x15;
0277         hdr = 0xc5;
0278         break;
0279     case 32:
0280         sr07 |= 0x19;
0281         hdr = 0xc5;
0282         break;
0283     default:
0284         drm_dev_exit(idx);
0285         return -1;
0286     }
0287 
0288     wreg_seq(cirrus, 0x7, sr07);
0289 
0290     /* Program the pitch */
0291     cirrus->pitch = cirrus_pitch(fb);
0292     tmp = cirrus->pitch / 8;
0293     wreg_crt(cirrus, VGA_CRTC_OFFSET, tmp);
0294 
0295     /* Enable extended blanking and pitch bits, and enable full memory */
0296     tmp = 0x22;
0297     tmp |= (cirrus->pitch >> 7) & 0x10;
0298     tmp |= (cirrus->pitch >> 6) & 0x40;
0299     wreg_crt(cirrus, 0x1b, tmp);
0300 
0301     /* Enable high-colour modes */
0302     wreg_gfx(cirrus, VGA_GFX_MODE, 0x40);
0303 
0304     /* And set graphics mode */
0305     wreg_gfx(cirrus, VGA_GFX_MISC, 0x01);
0306 
0307     wreg_hdr(cirrus, hdr);
0308 
0309     cirrus_set_start_address(cirrus, 0);
0310 
0311     /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
0312     outb(0x20, 0x3c0);
0313 
0314     drm_dev_exit(idx);
0315     return 0;
0316 }
0317 
0318 static int cirrus_fb_blit_rect(struct drm_framebuffer *fb,
0319                    const struct iosys_map *map,
0320                    struct drm_rect *rect)
0321 {
0322     struct cirrus_device *cirrus = to_cirrus(fb->dev);
0323     void __iomem *dst = cirrus->vram;
0324     void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
0325     int idx;
0326 
0327     if (!drm_dev_enter(&cirrus->dev, &idx))
0328         return -ENODEV;
0329 
0330     if (cirrus->cpp == fb->format->cpp[0]) {
0331         dst += drm_fb_clip_offset(fb->pitches[0], fb->format, rect);
0332         drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, rect);
0333 
0334     } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) {
0335         dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect);
0336         drm_fb_xrgb8888_to_rgb565_toio(dst, cirrus->pitch, vmap, fb, rect, false);
0337 
0338     } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) {
0339         dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect);
0340         drm_fb_xrgb8888_to_rgb888_toio(dst, cirrus->pitch, vmap, fb, rect);
0341 
0342     } else {
0343         WARN_ON_ONCE("cpp mismatch");
0344     }
0345 
0346     drm_dev_exit(idx);
0347 
0348     return 0;
0349 }
0350 
0351 static int cirrus_fb_blit_fullscreen(struct drm_framebuffer *fb,
0352                      const struct iosys_map *map)
0353 {
0354     struct drm_rect fullscreen = {
0355         .x1 = 0,
0356         .x2 = fb->width,
0357         .y1 = 0,
0358         .y2 = fb->height,
0359     };
0360     return cirrus_fb_blit_rect(fb, map, &fullscreen);
0361 }
0362 
0363 static int cirrus_check_size(int width, int height,
0364                  struct drm_framebuffer *fb)
0365 {
0366     int pitch = width * 2;
0367 
0368     if (fb)
0369         pitch = cirrus_pitch(fb);
0370 
0371     if (pitch > CIRRUS_MAX_PITCH)
0372         return -EINVAL;
0373     if (pitch * height > CIRRUS_VRAM_SIZE)
0374         return -EINVAL;
0375     return 0;
0376 }
0377 
0378 /* ------------------------------------------------------------------ */
0379 /* cirrus connector                           */
0380 
0381 static int cirrus_conn_get_modes(struct drm_connector *conn)
0382 {
0383     int count;
0384 
0385     count = drm_add_modes_noedid(conn,
0386                      conn->dev->mode_config.max_width,
0387                      conn->dev->mode_config.max_height);
0388     drm_set_preferred_mode(conn, 1024, 768);
0389     return count;
0390 }
0391 
0392 static const struct drm_connector_helper_funcs cirrus_conn_helper_funcs = {
0393     .get_modes = cirrus_conn_get_modes,
0394 };
0395 
0396 static const struct drm_connector_funcs cirrus_conn_funcs = {
0397     .fill_modes = drm_helper_probe_single_connector_modes,
0398     .destroy = drm_connector_cleanup,
0399     .reset = drm_atomic_helper_connector_reset,
0400     .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0401     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0402 };
0403 
0404 static int cirrus_conn_init(struct cirrus_device *cirrus)
0405 {
0406     drm_connector_helper_add(&cirrus->conn, &cirrus_conn_helper_funcs);
0407     return drm_connector_init(&cirrus->dev, &cirrus->conn,
0408                   &cirrus_conn_funcs, DRM_MODE_CONNECTOR_VGA);
0409 
0410 }
0411 
0412 /* ------------------------------------------------------------------ */
0413 /* cirrus (simple) display pipe                       */
0414 
0415 static enum drm_mode_status cirrus_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
0416                            const struct drm_display_mode *mode)
0417 {
0418     if (cirrus_check_size(mode->hdisplay, mode->vdisplay, NULL) < 0)
0419         return MODE_BAD;
0420     return MODE_OK;
0421 }
0422 
0423 static int cirrus_pipe_check(struct drm_simple_display_pipe *pipe,
0424                  struct drm_plane_state *plane_state,
0425                  struct drm_crtc_state *crtc_state)
0426 {
0427     struct drm_framebuffer *fb = plane_state->fb;
0428 
0429     if (!fb)
0430         return 0;
0431     return cirrus_check_size(fb->width, fb->height, fb);
0432 }
0433 
0434 static void cirrus_pipe_enable(struct drm_simple_display_pipe *pipe,
0435                    struct drm_crtc_state *crtc_state,
0436                    struct drm_plane_state *plane_state)
0437 {
0438     struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev);
0439     struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
0440 
0441     cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb);
0442     cirrus_fb_blit_fullscreen(plane_state->fb, &shadow_plane_state->data[0]);
0443 }
0444 
0445 static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
0446                    struct drm_plane_state *old_state)
0447 {
0448     struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev);
0449     struct drm_plane_state *state = pipe->plane.state;
0450     struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
0451     struct drm_crtc *crtc = &pipe->crtc;
0452     struct drm_rect rect;
0453 
0454     if (state->fb && cirrus->cpp != cirrus_cpp(state->fb))
0455         cirrus_mode_set(cirrus, &crtc->mode, state->fb);
0456 
0457     if (drm_atomic_helper_damage_merged(old_state, state, &rect))
0458         cirrus_fb_blit_rect(state->fb, &shadow_plane_state->data[0], &rect);
0459 }
0460 
0461 static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = {
0462     .mode_valid = cirrus_pipe_mode_valid,
0463     .check      = cirrus_pipe_check,
0464     .enable     = cirrus_pipe_enable,
0465     .update     = cirrus_pipe_update,
0466     DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
0467 };
0468 
0469 static const uint32_t cirrus_formats[] = {
0470     DRM_FORMAT_RGB565,
0471     DRM_FORMAT_RGB888,
0472     DRM_FORMAT_XRGB8888,
0473 };
0474 
0475 static const uint64_t cirrus_modifiers[] = {
0476     DRM_FORMAT_MOD_LINEAR,
0477     DRM_FORMAT_MOD_INVALID
0478 };
0479 
0480 static int cirrus_pipe_init(struct cirrus_device *cirrus)
0481 {
0482     return drm_simple_display_pipe_init(&cirrus->dev,
0483                         &cirrus->pipe,
0484                         &cirrus_pipe_funcs,
0485                         cirrus_formats,
0486                         ARRAY_SIZE(cirrus_formats),
0487                         cirrus_modifiers,
0488                         &cirrus->conn);
0489 }
0490 
0491 /* ------------------------------------------------------------------ */
0492 /* cirrus framebuffers & mode config                      */
0493 
0494 static struct drm_framebuffer*
0495 cirrus_fb_create(struct drm_device *dev, struct drm_file *file_priv,
0496          const struct drm_mode_fb_cmd2 *mode_cmd)
0497 {
0498     if (mode_cmd->pixel_format != DRM_FORMAT_RGB565 &&
0499         mode_cmd->pixel_format != DRM_FORMAT_RGB888 &&
0500         mode_cmd->pixel_format != DRM_FORMAT_XRGB8888)
0501         return ERR_PTR(-EINVAL);
0502     if (cirrus_check_size(mode_cmd->width, mode_cmd->height, NULL) < 0)
0503         return ERR_PTR(-EINVAL);
0504     return drm_gem_fb_create_with_dirty(dev, file_priv, mode_cmd);
0505 }
0506 
0507 static const struct drm_mode_config_funcs cirrus_mode_config_funcs = {
0508     .fb_create = cirrus_fb_create,
0509     .atomic_check = drm_atomic_helper_check,
0510     .atomic_commit = drm_atomic_helper_commit,
0511 };
0512 
0513 static int cirrus_mode_config_init(struct cirrus_device *cirrus)
0514 {
0515     struct drm_device *dev = &cirrus->dev;
0516     int ret;
0517 
0518     ret = drmm_mode_config_init(dev);
0519     if (ret)
0520         return ret;
0521 
0522     dev->mode_config.min_width = 0;
0523     dev->mode_config.min_height = 0;
0524     dev->mode_config.max_width = CIRRUS_MAX_PITCH / 2;
0525     dev->mode_config.max_height = 1024;
0526     dev->mode_config.preferred_depth = 16;
0527     dev->mode_config.prefer_shadow = 0;
0528     dev->mode_config.funcs = &cirrus_mode_config_funcs;
0529 
0530     return 0;
0531 }
0532 
0533 /* ------------------------------------------------------------------ */
0534 
0535 DEFINE_DRM_GEM_FOPS(cirrus_fops);
0536 
0537 static const struct drm_driver cirrus_driver = {
0538     .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
0539 
0540     .name        = DRIVER_NAME,
0541     .desc        = DRIVER_DESC,
0542     .date        = DRIVER_DATE,
0543     .major       = DRIVER_MAJOR,
0544     .minor       = DRIVER_MINOR,
0545 
0546     .fops        = &cirrus_fops,
0547     DRM_GEM_SHMEM_DRIVER_OPS,
0548 };
0549 
0550 static int cirrus_pci_probe(struct pci_dev *pdev,
0551                 const struct pci_device_id *ent)
0552 {
0553     struct drm_device *dev;
0554     struct cirrus_device *cirrus;
0555     int ret;
0556 
0557     ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &cirrus_driver);
0558     if (ret)
0559         return ret;
0560 
0561     ret = pcim_enable_device(pdev);
0562     if (ret)
0563         return ret;
0564 
0565     ret = pci_request_regions(pdev, DRIVER_NAME);
0566     if (ret)
0567         return ret;
0568 
0569     ret = -ENOMEM;
0570     cirrus = devm_drm_dev_alloc(&pdev->dev, &cirrus_driver,
0571                     struct cirrus_device, dev);
0572     if (IS_ERR(cirrus))
0573         return PTR_ERR(cirrus);
0574 
0575     dev = &cirrus->dev;
0576 
0577     cirrus->vram = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0),
0578                     pci_resource_len(pdev, 0));
0579     if (cirrus->vram == NULL)
0580         return -ENOMEM;
0581 
0582     cirrus->mmio = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 1),
0583                     pci_resource_len(pdev, 1));
0584     if (cirrus->mmio == NULL)
0585         return -ENOMEM;
0586 
0587     ret = cirrus_mode_config_init(cirrus);
0588     if (ret)
0589         return ret;
0590 
0591     ret = cirrus_conn_init(cirrus);
0592     if (ret < 0)
0593         return ret;
0594 
0595     ret = cirrus_pipe_init(cirrus);
0596     if (ret < 0)
0597         return ret;
0598 
0599     drm_mode_config_reset(dev);
0600 
0601     pci_set_drvdata(pdev, dev);
0602     ret = drm_dev_register(dev, 0);
0603     if (ret)
0604         return ret;
0605 
0606     drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
0607     return 0;
0608 }
0609 
0610 static void cirrus_pci_remove(struct pci_dev *pdev)
0611 {
0612     struct drm_device *dev = pci_get_drvdata(pdev);
0613 
0614     drm_dev_unplug(dev);
0615     drm_atomic_helper_shutdown(dev);
0616 }
0617 
0618 static const struct pci_device_id pciidlist[] = {
0619     {
0620         .vendor    = PCI_VENDOR_ID_CIRRUS,
0621         .device    = PCI_DEVICE_ID_CIRRUS_5446,
0622         /* only bind to the cirrus chip in qemu */
0623         .subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
0624         .subdevice = PCI_SUBDEVICE_ID_QEMU,
0625     }, {
0626         .vendor    = PCI_VENDOR_ID_CIRRUS,
0627         .device    = PCI_DEVICE_ID_CIRRUS_5446,
0628         .subvendor = PCI_VENDOR_ID_XEN,
0629         .subdevice = 0x0001,
0630     },
0631     { /* end if list */ }
0632 };
0633 
0634 static struct pci_driver cirrus_pci_driver = {
0635     .name = DRIVER_NAME,
0636     .id_table = pciidlist,
0637     .probe = cirrus_pci_probe,
0638     .remove = cirrus_pci_remove,
0639 };
0640 
0641 drm_module_pci_driver(cirrus_pci_driver)
0642 
0643 MODULE_DEVICE_TABLE(pci, pciidlist);
0644 MODULE_LICENSE("GPL");