cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cirrus.c (16297B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * Copyright 2012-2019 Red Hat
      4 *
      5 * This file is subject to the terms and conditions of the GNU General
      6 * Public License version 2. See the file COPYING in the main
      7 * directory of this archive for more details.
      8 *
      9 * Authors: Matthew Garrett
     10 *	    Dave Airlie
     11 *	    Gerd Hoffmann
     12 *
     13 * Portions of this code derived from cirrusfb.c:
     14 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
     15 *
     16 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
     17 */
     18
     19#include <linux/iosys-map.h>
     20#include <linux/module.h>
     21#include <linux/pci.h>
     22
     23#include <video/cirrus.h>
     24#include <video/vga.h>
     25
     26#include <drm/drm_aperture.h>
     27#include <drm/drm_atomic_helper.h>
     28#include <drm/drm_atomic_state_helper.h>
     29#include <drm/drm_connector.h>
     30#include <drm/drm_damage_helper.h>
     31#include <drm/drm_drv.h>
     32#include <drm/drm_fb_helper.h>
     33#include <drm/drm_file.h>
     34#include <drm/drm_format_helper.h>
     35#include <drm/drm_fourcc.h>
     36#include <drm/drm_gem_atomic_helper.h>
     37#include <drm/drm_gem_framebuffer_helper.h>
     38#include <drm/drm_gem_shmem_helper.h>
     39#include <drm/drm_ioctl.h>
     40#include <drm/drm_managed.h>
     41#include <drm/drm_modeset_helper_vtables.h>
     42#include <drm/drm_module.h>
     43#include <drm/drm_probe_helper.h>
     44#include <drm/drm_simple_kms_helper.h>
     45
     46#define DRIVER_NAME "cirrus"
     47#define DRIVER_DESC "qemu cirrus vga"
     48#define DRIVER_DATE "2019"
     49#define DRIVER_MAJOR 2
     50#define DRIVER_MINOR 0
     51
     52#define CIRRUS_MAX_PITCH (0x1FF << 3)      /* (4096 - 1) & ~111b bytes */
     53#define CIRRUS_VRAM_SIZE (4 * 1024 * 1024) /* 4 MB */
     54
     55struct cirrus_device {
     56	struct drm_device	       dev;
     57	struct drm_simple_display_pipe pipe;
     58	struct drm_connector	       conn;
     59	unsigned int		       cpp;
     60	unsigned int		       pitch;
     61	void __iomem		       *vram;
     62	void __iomem		       *mmio;
     63};
     64
     65#define to_cirrus(_dev) container_of(_dev, struct cirrus_device, dev)
     66
     67/* ------------------------------------------------------------------ */
     68/*
     69 * The meat of this driver. The core passes us a mode and we have to program
     70 * it. The modesetting here is the bare minimum required to satisfy the qemu
     71 * emulation of this hardware, and running this against a real device is
     72 * likely to result in an inadequately programmed mode. We've already had
     73 * the opportunity to modify the mode, so whatever we receive here should
     74 * be something that can be correctly programmed and displayed
     75 */
     76
     77#define SEQ_INDEX 4
     78#define SEQ_DATA 5
     79
     80static u8 rreg_seq(struct cirrus_device *cirrus, u8 reg)
     81{
     82	iowrite8(reg, cirrus->mmio + SEQ_INDEX);
     83	return ioread8(cirrus->mmio + SEQ_DATA);
     84}
     85
     86static void wreg_seq(struct cirrus_device *cirrus, u8 reg, u8 val)
     87{
     88	iowrite8(reg, cirrus->mmio + SEQ_INDEX);
     89	iowrite8(val, cirrus->mmio + SEQ_DATA);
     90}
     91
     92#define CRT_INDEX 0x14
     93#define CRT_DATA 0x15
     94
     95static u8 rreg_crt(struct cirrus_device *cirrus, u8 reg)
     96{
     97	iowrite8(reg, cirrus->mmio + CRT_INDEX);
     98	return ioread8(cirrus->mmio + CRT_DATA);
     99}
    100
    101static void wreg_crt(struct cirrus_device *cirrus, u8 reg, u8 val)
    102{
    103	iowrite8(reg, cirrus->mmio + CRT_INDEX);
    104	iowrite8(val, cirrus->mmio + CRT_DATA);
    105}
    106
    107#define GFX_INDEX 0xe
    108#define GFX_DATA 0xf
    109
    110static void wreg_gfx(struct cirrus_device *cirrus, u8 reg, u8 val)
    111{
    112	iowrite8(reg, cirrus->mmio + GFX_INDEX);
    113	iowrite8(val, cirrus->mmio + GFX_DATA);
    114}
    115
    116#define VGA_DAC_MASK  0x06
    117
    118static void wreg_hdr(struct cirrus_device *cirrus, u8 val)
    119{
    120	ioread8(cirrus->mmio + VGA_DAC_MASK);
    121	ioread8(cirrus->mmio + VGA_DAC_MASK);
    122	ioread8(cirrus->mmio + VGA_DAC_MASK);
    123	ioread8(cirrus->mmio + VGA_DAC_MASK);
    124	iowrite8(val, cirrus->mmio + VGA_DAC_MASK);
    125}
    126
    127static int cirrus_convert_to(struct drm_framebuffer *fb)
    128{
    129	if (fb->format->cpp[0] == 4 && fb->pitches[0] > CIRRUS_MAX_PITCH) {
    130		if (fb->width * 3 <= CIRRUS_MAX_PITCH)
    131			/* convert from XR24 to RG24 */
    132			return 3;
    133		else
    134			/* convert from XR24 to RG16 */
    135			return 2;
    136	}
    137	return 0;
    138}
    139
    140static int cirrus_cpp(struct drm_framebuffer *fb)
    141{
    142	int convert_cpp = cirrus_convert_to(fb);
    143
    144	if (convert_cpp)
    145		return convert_cpp;
    146	return fb->format->cpp[0];
    147}
    148
    149static int cirrus_pitch(struct drm_framebuffer *fb)
    150{
    151	int convert_cpp = cirrus_convert_to(fb);
    152
    153	if (convert_cpp)
    154		return convert_cpp * fb->width;
    155	return fb->pitches[0];
    156}
    157
    158static void cirrus_set_start_address(struct cirrus_device *cirrus, u32 offset)
    159{
    160	int idx;
    161	u32 addr;
    162	u8 tmp;
    163
    164	if (!drm_dev_enter(&cirrus->dev, &idx))
    165		return;
    166
    167	addr = offset >> 2;
    168	wreg_crt(cirrus, 0x0c, (u8)((addr >> 8) & 0xff));
    169	wreg_crt(cirrus, 0x0d, (u8)(addr & 0xff));
    170
    171	tmp = rreg_crt(cirrus, 0x1b);
    172	tmp &= 0xf2;
    173	tmp |= (addr >> 16) & 0x01;
    174	tmp |= (addr >> 15) & 0x0c;
    175	wreg_crt(cirrus, 0x1b, tmp);
    176
    177	tmp = rreg_crt(cirrus, 0x1d);
    178	tmp &= 0x7f;
    179	tmp |= (addr >> 12) & 0x80;
    180	wreg_crt(cirrus, 0x1d, tmp);
    181
    182	drm_dev_exit(idx);
    183}
    184
    185static int cirrus_mode_set(struct cirrus_device *cirrus,
    186			   struct drm_display_mode *mode,
    187			   struct drm_framebuffer *fb)
    188{
    189	int hsyncstart, hsyncend, htotal, hdispend;
    190	int vtotal, vdispend;
    191	int tmp, idx;
    192	int sr07 = 0, hdr = 0;
    193
    194	if (!drm_dev_enter(&cirrus->dev, &idx))
    195		return -1;
    196
    197	htotal = mode->htotal / 8;
    198	hsyncend = mode->hsync_end / 8;
    199	hsyncstart = mode->hsync_start / 8;
    200	hdispend = mode->hdisplay / 8;
    201
    202	vtotal = mode->vtotal;
    203	vdispend = mode->vdisplay;
    204
    205	vdispend -= 1;
    206	vtotal -= 2;
    207
    208	htotal -= 5;
    209	hdispend -= 1;
    210	hsyncstart += 1;
    211	hsyncend += 1;
    212
    213	wreg_crt(cirrus, VGA_CRTC_V_SYNC_END, 0x20);
    214	wreg_crt(cirrus, VGA_CRTC_H_TOTAL, htotal);
    215	wreg_crt(cirrus, VGA_CRTC_H_DISP, hdispend);
    216	wreg_crt(cirrus, VGA_CRTC_H_SYNC_START, hsyncstart);
    217	wreg_crt(cirrus, VGA_CRTC_H_SYNC_END, hsyncend);
    218	wreg_crt(cirrus, VGA_CRTC_V_TOTAL, vtotal & 0xff);
    219	wreg_crt(cirrus, VGA_CRTC_V_DISP_END, vdispend & 0xff);
    220
    221	tmp = 0x40;
    222	if ((vdispend + 1) & 512)
    223		tmp |= 0x20;
    224	wreg_crt(cirrus, VGA_CRTC_MAX_SCAN, tmp);
    225
    226	/*
    227	 * Overflow bits for values that don't fit in the standard registers
    228	 */
    229	tmp = 0x10;
    230	if (vtotal & 0x100)
    231		tmp |= 0x01;
    232	if (vdispend & 0x100)
    233		tmp |= 0x02;
    234	if ((vdispend + 1) & 0x100)
    235		tmp |= 0x08;
    236	if (vtotal & 0x200)
    237		tmp |= 0x20;
    238	if (vdispend & 0x200)
    239		tmp |= 0x40;
    240	wreg_crt(cirrus, VGA_CRTC_OVERFLOW, tmp);
    241
    242	tmp = 0;
    243
    244	/* More overflow bits */
    245
    246	if ((htotal + 5) & 0x40)
    247		tmp |= 0x10;
    248	if ((htotal + 5) & 0x80)
    249		tmp |= 0x20;
    250	if (vtotal & 0x100)
    251		tmp |= 0x40;
    252	if (vtotal & 0x200)
    253		tmp |= 0x80;
    254
    255	wreg_crt(cirrus, CL_CRT1A, tmp);
    256
    257	/* Disable Hercules/CGA compatibility */
    258	wreg_crt(cirrus, VGA_CRTC_MODE, 0x03);
    259
    260	sr07 = rreg_seq(cirrus, 0x07);
    261	sr07 &= 0xe0;
    262	hdr = 0;
    263
    264	cirrus->cpp = cirrus_cpp(fb);
    265	switch (cirrus->cpp * 8) {
    266	case 8:
    267		sr07 |= 0x11;
    268		break;
    269	case 16:
    270		sr07 |= 0x17;
    271		hdr = 0xc1;
    272		break;
    273	case 24:
    274		sr07 |= 0x15;
    275		hdr = 0xc5;
    276		break;
    277	case 32:
    278		sr07 |= 0x19;
    279		hdr = 0xc5;
    280		break;
    281	default:
    282		drm_dev_exit(idx);
    283		return -1;
    284	}
    285
    286	wreg_seq(cirrus, 0x7, sr07);
    287
    288	/* Program the pitch */
    289	cirrus->pitch = cirrus_pitch(fb);
    290	tmp = cirrus->pitch / 8;
    291	wreg_crt(cirrus, VGA_CRTC_OFFSET, tmp);
    292
    293	/* Enable extended blanking and pitch bits, and enable full memory */
    294	tmp = 0x22;
    295	tmp |= (cirrus->pitch >> 7) & 0x10;
    296	tmp |= (cirrus->pitch >> 6) & 0x40;
    297	wreg_crt(cirrus, 0x1b, tmp);
    298
    299	/* Enable high-colour modes */
    300	wreg_gfx(cirrus, VGA_GFX_MODE, 0x40);
    301
    302	/* And set graphics mode */
    303	wreg_gfx(cirrus, VGA_GFX_MISC, 0x01);
    304
    305	wreg_hdr(cirrus, hdr);
    306
    307	cirrus_set_start_address(cirrus, 0);
    308
    309	/* Unblank (needed on S3 resume, vgabios doesn't do it then) */
    310	outb(0x20, 0x3c0);
    311
    312	drm_dev_exit(idx);
    313	return 0;
    314}
    315
    316static int cirrus_fb_blit_rect(struct drm_framebuffer *fb,
    317			       const struct iosys_map *map,
    318			       struct drm_rect *rect)
    319{
    320	struct cirrus_device *cirrus = to_cirrus(fb->dev);
    321	void __iomem *dst = cirrus->vram;
    322	void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
    323	int idx;
    324
    325	if (!drm_dev_enter(&cirrus->dev, &idx))
    326		return -ENODEV;
    327
    328	if (cirrus->cpp == fb->format->cpp[0]) {
    329		dst += drm_fb_clip_offset(fb->pitches[0], fb->format, rect);
    330		drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, rect);
    331
    332	} else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) {
    333		dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect);
    334		drm_fb_xrgb8888_to_rgb565_toio(dst, cirrus->pitch, vmap, fb, rect, false);
    335
    336	} else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) {
    337		dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect);
    338		drm_fb_xrgb8888_to_rgb888_toio(dst, cirrus->pitch, vmap, fb, rect);
    339
    340	} else {
    341		WARN_ON_ONCE("cpp mismatch");
    342	}
    343
    344	drm_dev_exit(idx);
    345
    346	return 0;
    347}
    348
    349static int cirrus_fb_blit_fullscreen(struct drm_framebuffer *fb,
    350				     const struct iosys_map *map)
    351{
    352	struct drm_rect fullscreen = {
    353		.x1 = 0,
    354		.x2 = fb->width,
    355		.y1 = 0,
    356		.y2 = fb->height,
    357	};
    358	return cirrus_fb_blit_rect(fb, map, &fullscreen);
    359}
    360
    361static int cirrus_check_size(int width, int height,
    362			     struct drm_framebuffer *fb)
    363{
    364	int pitch = width * 2;
    365
    366	if (fb)
    367		pitch = cirrus_pitch(fb);
    368
    369	if (pitch > CIRRUS_MAX_PITCH)
    370		return -EINVAL;
    371	if (pitch * height > CIRRUS_VRAM_SIZE)
    372		return -EINVAL;
    373	return 0;
    374}
    375
    376/* ------------------------------------------------------------------ */
    377/* cirrus connector						      */
    378
    379static int cirrus_conn_get_modes(struct drm_connector *conn)
    380{
    381	int count;
    382
    383	count = drm_add_modes_noedid(conn,
    384				     conn->dev->mode_config.max_width,
    385				     conn->dev->mode_config.max_height);
    386	drm_set_preferred_mode(conn, 1024, 768);
    387	return count;
    388}
    389
    390static const struct drm_connector_helper_funcs cirrus_conn_helper_funcs = {
    391	.get_modes = cirrus_conn_get_modes,
    392};
    393
    394static const struct drm_connector_funcs cirrus_conn_funcs = {
    395	.fill_modes = drm_helper_probe_single_connector_modes,
    396	.destroy = drm_connector_cleanup,
    397	.reset = drm_atomic_helper_connector_reset,
    398	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
    399	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
    400};
    401
    402static int cirrus_conn_init(struct cirrus_device *cirrus)
    403{
    404	drm_connector_helper_add(&cirrus->conn, &cirrus_conn_helper_funcs);
    405	return drm_connector_init(&cirrus->dev, &cirrus->conn,
    406				  &cirrus_conn_funcs, DRM_MODE_CONNECTOR_VGA);
    407
    408}
    409
    410/* ------------------------------------------------------------------ */
    411/* cirrus (simple) display pipe					      */
    412
    413static enum drm_mode_status cirrus_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
    414						   const struct drm_display_mode *mode)
    415{
    416	if (cirrus_check_size(mode->hdisplay, mode->vdisplay, NULL) < 0)
    417		return MODE_BAD;
    418	return MODE_OK;
    419}
    420
    421static int cirrus_pipe_check(struct drm_simple_display_pipe *pipe,
    422			     struct drm_plane_state *plane_state,
    423			     struct drm_crtc_state *crtc_state)
    424{
    425	struct drm_framebuffer *fb = plane_state->fb;
    426
    427	if (!fb)
    428		return 0;
    429	return cirrus_check_size(fb->width, fb->height, fb);
    430}
    431
    432static void cirrus_pipe_enable(struct drm_simple_display_pipe *pipe,
    433			       struct drm_crtc_state *crtc_state,
    434			       struct drm_plane_state *plane_state)
    435{
    436	struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev);
    437	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
    438
    439	cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb);
    440	cirrus_fb_blit_fullscreen(plane_state->fb, &shadow_plane_state->data[0]);
    441}
    442
    443static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,
    444			       struct drm_plane_state *old_state)
    445{
    446	struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev);
    447	struct drm_plane_state *state = pipe->plane.state;
    448	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
    449	struct drm_crtc *crtc = &pipe->crtc;
    450	struct drm_rect rect;
    451
    452	if (state->fb && cirrus->cpp != cirrus_cpp(state->fb))
    453		cirrus_mode_set(cirrus, &crtc->mode, state->fb);
    454
    455	if (drm_atomic_helper_damage_merged(old_state, state, &rect))
    456		cirrus_fb_blit_rect(state->fb, &shadow_plane_state->data[0], &rect);
    457}
    458
    459static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = {
    460	.mode_valid = cirrus_pipe_mode_valid,
    461	.check	    = cirrus_pipe_check,
    462	.enable	    = cirrus_pipe_enable,
    463	.update	    = cirrus_pipe_update,
    464	DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
    465};
    466
    467static const uint32_t cirrus_formats[] = {
    468	DRM_FORMAT_RGB565,
    469	DRM_FORMAT_RGB888,
    470	DRM_FORMAT_XRGB8888,
    471};
    472
    473static const uint64_t cirrus_modifiers[] = {
    474	DRM_FORMAT_MOD_LINEAR,
    475	DRM_FORMAT_MOD_INVALID
    476};
    477
    478static int cirrus_pipe_init(struct cirrus_device *cirrus)
    479{
    480	return drm_simple_display_pipe_init(&cirrus->dev,
    481					    &cirrus->pipe,
    482					    &cirrus_pipe_funcs,
    483					    cirrus_formats,
    484					    ARRAY_SIZE(cirrus_formats),
    485					    cirrus_modifiers,
    486					    &cirrus->conn);
    487}
    488
    489/* ------------------------------------------------------------------ */
    490/* cirrus framebuffers & mode config				      */
    491
    492static struct drm_framebuffer*
    493cirrus_fb_create(struct drm_device *dev, struct drm_file *file_priv,
    494		 const struct drm_mode_fb_cmd2 *mode_cmd)
    495{
    496	if (mode_cmd->pixel_format != DRM_FORMAT_RGB565 &&
    497	    mode_cmd->pixel_format != DRM_FORMAT_RGB888 &&
    498	    mode_cmd->pixel_format != DRM_FORMAT_XRGB8888)
    499		return ERR_PTR(-EINVAL);
    500	if (cirrus_check_size(mode_cmd->width, mode_cmd->height, NULL) < 0)
    501		return ERR_PTR(-EINVAL);
    502	return drm_gem_fb_create_with_dirty(dev, file_priv, mode_cmd);
    503}
    504
    505static const struct drm_mode_config_funcs cirrus_mode_config_funcs = {
    506	.fb_create = cirrus_fb_create,
    507	.atomic_check = drm_atomic_helper_check,
    508	.atomic_commit = drm_atomic_helper_commit,
    509};
    510
    511static int cirrus_mode_config_init(struct cirrus_device *cirrus)
    512{
    513	struct drm_device *dev = &cirrus->dev;
    514	int ret;
    515
    516	ret = drmm_mode_config_init(dev);
    517	if (ret)
    518		return ret;
    519
    520	dev->mode_config.min_width = 0;
    521	dev->mode_config.min_height = 0;
    522	dev->mode_config.max_width = CIRRUS_MAX_PITCH / 2;
    523	dev->mode_config.max_height = 1024;
    524	dev->mode_config.preferred_depth = 16;
    525	dev->mode_config.prefer_shadow = 0;
    526	dev->mode_config.funcs = &cirrus_mode_config_funcs;
    527
    528	return 0;
    529}
    530
    531/* ------------------------------------------------------------------ */
    532
    533DEFINE_DRM_GEM_FOPS(cirrus_fops);
    534
    535static const struct drm_driver cirrus_driver = {
    536	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
    537
    538	.name		 = DRIVER_NAME,
    539	.desc		 = DRIVER_DESC,
    540	.date		 = DRIVER_DATE,
    541	.major		 = DRIVER_MAJOR,
    542	.minor		 = DRIVER_MINOR,
    543
    544	.fops		 = &cirrus_fops,
    545	DRM_GEM_SHMEM_DRIVER_OPS,
    546};
    547
    548static int cirrus_pci_probe(struct pci_dev *pdev,
    549			    const struct pci_device_id *ent)
    550{
    551	struct drm_device *dev;
    552	struct cirrus_device *cirrus;
    553	int ret;
    554
    555	ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &cirrus_driver);
    556	if (ret)
    557		return ret;
    558
    559	ret = pcim_enable_device(pdev);
    560	if (ret)
    561		return ret;
    562
    563	ret = pci_request_regions(pdev, DRIVER_NAME);
    564	if (ret)
    565		return ret;
    566
    567	ret = -ENOMEM;
    568	cirrus = devm_drm_dev_alloc(&pdev->dev, &cirrus_driver,
    569				    struct cirrus_device, dev);
    570	if (IS_ERR(cirrus))
    571		return PTR_ERR(cirrus);
    572
    573	dev = &cirrus->dev;
    574
    575	cirrus->vram = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 0),
    576				    pci_resource_len(pdev, 0));
    577	if (cirrus->vram == NULL)
    578		return -ENOMEM;
    579
    580	cirrus->mmio = devm_ioremap(&pdev->dev, pci_resource_start(pdev, 1),
    581				    pci_resource_len(pdev, 1));
    582	if (cirrus->mmio == NULL)
    583		return -ENOMEM;
    584
    585	ret = cirrus_mode_config_init(cirrus);
    586	if (ret)
    587		return ret;
    588
    589	ret = cirrus_conn_init(cirrus);
    590	if (ret < 0)
    591		return ret;
    592
    593	ret = cirrus_pipe_init(cirrus);
    594	if (ret < 0)
    595		return ret;
    596
    597	drm_mode_config_reset(dev);
    598
    599	pci_set_drvdata(pdev, dev);
    600	ret = drm_dev_register(dev, 0);
    601	if (ret)
    602		return ret;
    603
    604	drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
    605	return 0;
    606}
    607
    608static void cirrus_pci_remove(struct pci_dev *pdev)
    609{
    610	struct drm_device *dev = pci_get_drvdata(pdev);
    611
    612	drm_dev_unplug(dev);
    613	drm_atomic_helper_shutdown(dev);
    614}
    615
    616static const struct pci_device_id pciidlist[] = {
    617	{
    618		.vendor    = PCI_VENDOR_ID_CIRRUS,
    619		.device    = PCI_DEVICE_ID_CIRRUS_5446,
    620		/* only bind to the cirrus chip in qemu */
    621		.subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
    622		.subdevice = PCI_SUBDEVICE_ID_QEMU,
    623	}, {
    624		.vendor    = PCI_VENDOR_ID_CIRRUS,
    625		.device    = PCI_DEVICE_ID_CIRRUS_5446,
    626		.subvendor = PCI_VENDOR_ID_XEN,
    627		.subdevice = 0x0001,
    628	},
    629	{ /* end if list */ }
    630};
    631
    632static struct pci_driver cirrus_pci_driver = {
    633	.name = DRIVER_NAME,
    634	.id_table = pciidlist,
    635	.probe = cirrus_pci_probe,
    636	.remove = cirrus_pci_remove,
    637};
    638
    639drm_module_pci_driver(cirrus_pci_driver)
    640
    641MODULE_DEVICE_TABLE(pci, pciidlist);
    642MODULE_LICENSE("GPL");