0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
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)
0055 #define CIRRUS_VRAM_SIZE (4 * 1024 * 1024)
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
0072
0073
0074
0075
0076
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
0134 return 3;
0135 else
0136
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
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
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
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
0291 cirrus->pitch = cirrus_pitch(fb);
0292 tmp = cirrus->pitch / 8;
0293 wreg_crt(cirrus, VGA_CRTC_OFFSET, tmp);
0294
0295
0296 tmp = 0x22;
0297 tmp |= (cirrus->pitch >> 7) & 0x10;
0298 tmp |= (cirrus->pitch >> 6) & 0x40;
0299 wreg_crt(cirrus, 0x1b, tmp);
0300
0301
0302 wreg_gfx(cirrus, VGA_GFX_MODE, 0x40);
0303
0304
0305 wreg_gfx(cirrus, VGA_GFX_MISC, 0x01);
0306
0307 wreg_hdr(cirrus, hdr);
0308
0309 cirrus_set_start_address(cirrus, 0);
0310
0311
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;
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
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
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
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
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 { }
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");