1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright 2012-2019 Red Hat
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.
9 * Authors: Matthew Garrett
13 * Portions of this code derived from cirrusfb.c:
14 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
16 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
19 #include <linux/console.h>
20 #include <linux/dma-buf-map.h>
21 #include <linux/module.h>
22 #include <linux/pci.h>
24 #include <video/cirrus.h>
25 #include <video/vga.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_shmem_helper.h>
37 #include <drm/drm_gem_framebuffer_helper.h>
38 #include <drm/drm_ioctl.h>
39 #include <drm/drm_managed.h>
40 #include <drm/drm_modeset_helper_vtables.h>
41 #include <drm/drm_probe_helper.h>
42 #include <drm/drm_simple_kms_helper.h>
44 #define DRIVER_NAME "cirrus"
45 #define DRIVER_DESC "qemu cirrus vga"
46 #define DRIVER_DATE "2019"
47 #define DRIVER_MAJOR 2
48 #define DRIVER_MINOR 0
50 #define CIRRUS_MAX_PITCH (0x1FF << 3) /* (4096 - 1) & ~111b bytes */
51 #define CIRRUS_VRAM_SIZE (4 * 1024 * 1024) /* 4 MB */
53 struct cirrus_device
{
54 struct drm_device dev
;
55 struct drm_simple_display_pipe pipe
;
56 struct drm_connector conn
;
63 #define to_cirrus(_dev) container_of(_dev, struct cirrus_device, dev)
65 /* ------------------------------------------------------------------ */
67 * The meat of this driver. The core passes us a mode and we have to program
68 * it. The modesetting here is the bare minimum required to satisfy the qemu
69 * emulation of this hardware, and running this against a real device is
70 * likely to result in an inadequately programmed mode. We've already had
71 * the opportunity to modify the mode, so whatever we receive here should
72 * be something that can be correctly programmed and displayed
78 static u8
rreg_seq(struct cirrus_device
*cirrus
, u8 reg
)
80 iowrite8(reg
, cirrus
->mmio
+ SEQ_INDEX
);
81 return ioread8(cirrus
->mmio
+ SEQ_DATA
);
84 static void wreg_seq(struct cirrus_device
*cirrus
, u8 reg
, u8 val
)
86 iowrite8(reg
, cirrus
->mmio
+ SEQ_INDEX
);
87 iowrite8(val
, cirrus
->mmio
+ SEQ_DATA
);
90 #define CRT_INDEX 0x14
93 static u8
rreg_crt(struct cirrus_device
*cirrus
, u8 reg
)
95 iowrite8(reg
, cirrus
->mmio
+ CRT_INDEX
);
96 return ioread8(cirrus
->mmio
+ CRT_DATA
);
99 static void wreg_crt(struct cirrus_device
*cirrus
, u8 reg
, u8 val
)
101 iowrite8(reg
, cirrus
->mmio
+ CRT_INDEX
);
102 iowrite8(val
, cirrus
->mmio
+ CRT_DATA
);
105 #define GFX_INDEX 0xe
108 static void wreg_gfx(struct cirrus_device
*cirrus
, u8 reg
, u8 val
)
110 iowrite8(reg
, cirrus
->mmio
+ GFX_INDEX
);
111 iowrite8(val
, cirrus
->mmio
+ GFX_DATA
);
114 #define VGA_DAC_MASK 0x06
116 static void wreg_hdr(struct cirrus_device
*cirrus
, u8 val
)
118 ioread8(cirrus
->mmio
+ VGA_DAC_MASK
);
119 ioread8(cirrus
->mmio
+ VGA_DAC_MASK
);
120 ioread8(cirrus
->mmio
+ VGA_DAC_MASK
);
121 ioread8(cirrus
->mmio
+ VGA_DAC_MASK
);
122 iowrite8(val
, cirrus
->mmio
+ VGA_DAC_MASK
);
125 static int cirrus_convert_to(struct drm_framebuffer
*fb
)
127 if (fb
->format
->cpp
[0] == 4 && fb
->pitches
[0] > CIRRUS_MAX_PITCH
) {
128 if (fb
->width
* 3 <= CIRRUS_MAX_PITCH
)
129 /* convert from XR24 to RG24 */
132 /* convert from XR24 to RG16 */
138 static int cirrus_cpp(struct drm_framebuffer
*fb
)
140 int convert_cpp
= cirrus_convert_to(fb
);
144 return fb
->format
->cpp
[0];
147 static int cirrus_pitch(struct drm_framebuffer
*fb
)
149 int convert_cpp
= cirrus_convert_to(fb
);
152 return convert_cpp
* fb
->width
;
153 return fb
->pitches
[0];
156 static void cirrus_set_start_address(struct cirrus_device
*cirrus
, u32 offset
)
162 if (!drm_dev_enter(&cirrus
->dev
, &idx
))
166 wreg_crt(cirrus
, 0x0c, (u8
)((addr
>> 8) & 0xff));
167 wreg_crt(cirrus
, 0x0d, (u8
)(addr
& 0xff));
169 tmp
= rreg_crt(cirrus
, 0x1b);
171 tmp
|= (addr
>> 16) & 0x01;
172 tmp
|= (addr
>> 15) & 0x0c;
173 wreg_crt(cirrus
, 0x1b, tmp
);
175 tmp
= rreg_crt(cirrus
, 0x1d);
177 tmp
|= (addr
>> 12) & 0x80;
178 wreg_crt(cirrus
, 0x1d, tmp
);
183 static int cirrus_mode_set(struct cirrus_device
*cirrus
,
184 struct drm_display_mode
*mode
,
185 struct drm_framebuffer
*fb
)
187 int hsyncstart
, hsyncend
, htotal
, hdispend
;
188 int vtotal
, vdispend
;
190 int sr07
= 0, hdr
= 0;
192 if (!drm_dev_enter(&cirrus
->dev
, &idx
))
195 htotal
= mode
->htotal
/ 8;
196 hsyncend
= mode
->hsync_end
/ 8;
197 hsyncstart
= mode
->hsync_start
/ 8;
198 hdispend
= mode
->hdisplay
/ 8;
200 vtotal
= mode
->vtotal
;
201 vdispend
= mode
->vdisplay
;
211 wreg_crt(cirrus
, VGA_CRTC_V_SYNC_END
, 0x20);
212 wreg_crt(cirrus
, VGA_CRTC_H_TOTAL
, htotal
);
213 wreg_crt(cirrus
, VGA_CRTC_H_DISP
, hdispend
);
214 wreg_crt(cirrus
, VGA_CRTC_H_SYNC_START
, hsyncstart
);
215 wreg_crt(cirrus
, VGA_CRTC_H_SYNC_END
, hsyncend
);
216 wreg_crt(cirrus
, VGA_CRTC_V_TOTAL
, vtotal
& 0xff);
217 wreg_crt(cirrus
, VGA_CRTC_V_DISP_END
, vdispend
& 0xff);
220 if ((vdispend
+ 1) & 512)
222 wreg_crt(cirrus
, VGA_CRTC_MAX_SCAN
, tmp
);
225 * Overflow bits for values that don't fit in the standard registers
230 if (vdispend
& 0x100)
232 if ((vdispend
+ 1) & 0x100)
236 if (vdispend
& 0x200)
238 wreg_crt(cirrus
, VGA_CRTC_OVERFLOW
, tmp
);
242 /* More overflow bits */
244 if ((htotal
+ 5) & 0x40)
246 if ((htotal
+ 5) & 0x80)
253 wreg_crt(cirrus
, CL_CRT1A
, tmp
);
255 /* Disable Hercules/CGA compatibility */
256 wreg_crt(cirrus
, VGA_CRTC_MODE
, 0x03);
258 sr07
= rreg_seq(cirrus
, 0x07);
262 cirrus
->cpp
= cirrus_cpp(fb
);
263 switch (cirrus
->cpp
* 8) {
284 wreg_seq(cirrus
, 0x7, sr07
);
286 /* Program the pitch */
287 cirrus
->pitch
= cirrus_pitch(fb
);
288 tmp
= cirrus
->pitch
/ 8;
289 wreg_crt(cirrus
, VGA_CRTC_OFFSET
, tmp
);
291 /* Enable extended blanking and pitch bits, and enable full memory */
293 tmp
|= (cirrus
->pitch
>> 7) & 0x10;
294 tmp
|= (cirrus
->pitch
>> 6) & 0x40;
295 wreg_crt(cirrus
, 0x1b, tmp
);
297 /* Enable high-colour modes */
298 wreg_gfx(cirrus
, VGA_GFX_MODE
, 0x40);
300 /* And set graphics mode */
301 wreg_gfx(cirrus
, VGA_GFX_MISC
, 0x01);
303 wreg_hdr(cirrus
, hdr
);
305 cirrus_set_start_address(cirrus
, 0);
307 /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
314 static int cirrus_fb_blit_rect(struct drm_framebuffer
*fb
,
315 struct drm_rect
*rect
)
317 struct cirrus_device
*cirrus
= to_cirrus(fb
->dev
);
318 struct dma_buf_map map
;
323 if (!drm_dev_enter(&cirrus
->dev
, &idx
))
326 ret
= drm_gem_shmem_vmap(fb
->obj
[0], &map
);
329 vmap
= map
.vaddr
; /* TODO: Use mapping abstraction properly */
331 if (cirrus
->cpp
== fb
->format
->cpp
[0])
332 drm_fb_memcpy_dstclip(cirrus
->vram
,
335 else if (fb
->format
->cpp
[0] == 4 && cirrus
->cpp
== 2)
336 drm_fb_xrgb8888_to_rgb565_dstclip(cirrus
->vram
,
338 vmap
, fb
, rect
, false);
340 else if (fb
->format
->cpp
[0] == 4 && cirrus
->cpp
== 3)
341 drm_fb_xrgb8888_to_rgb888_dstclip(cirrus
->vram
,
346 WARN_ON_ONCE("cpp mismatch");
348 drm_gem_shmem_vunmap(fb
->obj
[0], &map
);
357 static int cirrus_fb_blit_fullscreen(struct drm_framebuffer
*fb
)
359 struct drm_rect fullscreen
= {
365 return cirrus_fb_blit_rect(fb
, &fullscreen
);
368 static int cirrus_check_size(int width
, int height
,
369 struct drm_framebuffer
*fb
)
371 int pitch
= width
* 2;
374 pitch
= cirrus_pitch(fb
);
376 if (pitch
> CIRRUS_MAX_PITCH
)
378 if (pitch
* height
> CIRRUS_VRAM_SIZE
)
383 /* ------------------------------------------------------------------ */
384 /* cirrus connector */
386 static int cirrus_conn_get_modes(struct drm_connector
*conn
)
390 count
= drm_add_modes_noedid(conn
,
391 conn
->dev
->mode_config
.max_width
,
392 conn
->dev
->mode_config
.max_height
);
393 drm_set_preferred_mode(conn
, 1024, 768);
397 static const struct drm_connector_helper_funcs cirrus_conn_helper_funcs
= {
398 .get_modes
= cirrus_conn_get_modes
,
401 static const struct drm_connector_funcs cirrus_conn_funcs
= {
402 .fill_modes
= drm_helper_probe_single_connector_modes
,
403 .destroy
= drm_connector_cleanup
,
404 .reset
= drm_atomic_helper_connector_reset
,
405 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
406 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
409 static int cirrus_conn_init(struct cirrus_device
*cirrus
)
411 drm_connector_helper_add(&cirrus
->conn
, &cirrus_conn_helper_funcs
);
412 return drm_connector_init(&cirrus
->dev
, &cirrus
->conn
,
413 &cirrus_conn_funcs
, DRM_MODE_CONNECTOR_VGA
);
417 /* ------------------------------------------------------------------ */
418 /* cirrus (simple) display pipe */
420 static enum drm_mode_status
cirrus_pipe_mode_valid(struct drm_simple_display_pipe
*pipe
,
421 const struct drm_display_mode
*mode
)
423 if (cirrus_check_size(mode
->hdisplay
, mode
->vdisplay
, NULL
) < 0)
428 static int cirrus_pipe_check(struct drm_simple_display_pipe
*pipe
,
429 struct drm_plane_state
*plane_state
,
430 struct drm_crtc_state
*crtc_state
)
432 struct drm_framebuffer
*fb
= plane_state
->fb
;
436 return cirrus_check_size(fb
->width
, fb
->height
, fb
);
439 static void cirrus_pipe_enable(struct drm_simple_display_pipe
*pipe
,
440 struct drm_crtc_state
*crtc_state
,
441 struct drm_plane_state
*plane_state
)
443 struct cirrus_device
*cirrus
= to_cirrus(pipe
->crtc
.dev
);
445 cirrus_mode_set(cirrus
, &crtc_state
->mode
, plane_state
->fb
);
446 cirrus_fb_blit_fullscreen(plane_state
->fb
);
449 static void cirrus_pipe_update(struct drm_simple_display_pipe
*pipe
,
450 struct drm_plane_state
*old_state
)
452 struct cirrus_device
*cirrus
= to_cirrus(pipe
->crtc
.dev
);
453 struct drm_plane_state
*state
= pipe
->plane
.state
;
454 struct drm_crtc
*crtc
= &pipe
->crtc
;
455 struct drm_rect rect
;
457 if (pipe
->plane
.state
->fb
&&
458 cirrus
->cpp
!= cirrus_cpp(pipe
->plane
.state
->fb
))
459 cirrus_mode_set(cirrus
, &crtc
->mode
,
460 pipe
->plane
.state
->fb
);
462 if (drm_atomic_helper_damage_merged(old_state
, state
, &rect
))
463 cirrus_fb_blit_rect(pipe
->plane
.state
->fb
, &rect
);
466 static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs
= {
467 .mode_valid
= cirrus_pipe_mode_valid
,
468 .check
= cirrus_pipe_check
,
469 .enable
= cirrus_pipe_enable
,
470 .update
= cirrus_pipe_update
,
473 static const uint32_t cirrus_formats
[] = {
479 static const uint64_t cirrus_modifiers
[] = {
480 DRM_FORMAT_MOD_LINEAR
,
481 DRM_FORMAT_MOD_INVALID
484 static int cirrus_pipe_init(struct cirrus_device
*cirrus
)
486 return drm_simple_display_pipe_init(&cirrus
->dev
,
490 ARRAY_SIZE(cirrus_formats
),
495 /* ------------------------------------------------------------------ */
496 /* cirrus framebuffers & mode config */
498 static struct drm_framebuffer
*
499 cirrus_fb_create(struct drm_device
*dev
, struct drm_file
*file_priv
,
500 const struct drm_mode_fb_cmd2
*mode_cmd
)
502 if (mode_cmd
->pixel_format
!= DRM_FORMAT_RGB565
&&
503 mode_cmd
->pixel_format
!= DRM_FORMAT_RGB888
&&
504 mode_cmd
->pixel_format
!= DRM_FORMAT_XRGB8888
)
505 return ERR_PTR(-EINVAL
);
506 if (cirrus_check_size(mode_cmd
->width
, mode_cmd
->height
, NULL
) < 0)
507 return ERR_PTR(-EINVAL
);
508 return drm_gem_fb_create_with_dirty(dev
, file_priv
, mode_cmd
);
511 static const struct drm_mode_config_funcs cirrus_mode_config_funcs
= {
512 .fb_create
= cirrus_fb_create
,
513 .atomic_check
= drm_atomic_helper_check
,
514 .atomic_commit
= drm_atomic_helper_commit
,
517 static int cirrus_mode_config_init(struct cirrus_device
*cirrus
)
519 struct drm_device
*dev
= &cirrus
->dev
;
522 ret
= drmm_mode_config_init(dev
);
526 dev
->mode_config
.min_width
= 0;
527 dev
->mode_config
.min_height
= 0;
528 dev
->mode_config
.max_width
= CIRRUS_MAX_PITCH
/ 2;
529 dev
->mode_config
.max_height
= 1024;
530 dev
->mode_config
.preferred_depth
= 16;
531 dev
->mode_config
.prefer_shadow
= 0;
532 dev
->mode_config
.funcs
= &cirrus_mode_config_funcs
;
537 /* ------------------------------------------------------------------ */
539 DEFINE_DRM_GEM_FOPS(cirrus_fops
);
541 static const struct drm_driver cirrus_driver
= {
542 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_ATOMIC
,
547 .major
= DRIVER_MAJOR
,
548 .minor
= DRIVER_MINOR
,
550 .fops
= &cirrus_fops
,
551 DRM_GEM_SHMEM_DRIVER_OPS
,
554 static int cirrus_pci_probe(struct pci_dev
*pdev
,
555 const struct pci_device_id
*ent
)
557 struct drm_device
*dev
;
558 struct cirrus_device
*cirrus
;
561 ret
= drm_fb_helper_remove_conflicting_pci_framebuffers(pdev
, "cirrusdrmfb");
565 ret
= pcim_enable_device(pdev
);
569 ret
= pci_request_regions(pdev
, DRIVER_NAME
);
574 cirrus
= devm_drm_dev_alloc(&pdev
->dev
, &cirrus_driver
,
575 struct cirrus_device
, dev
);
577 return PTR_ERR(cirrus
);
581 cirrus
->vram
= devm_ioremap(&pdev
->dev
, pci_resource_start(pdev
, 0),
582 pci_resource_len(pdev
, 0));
583 if (cirrus
->vram
== NULL
)
586 cirrus
->mmio
= devm_ioremap(&pdev
->dev
, pci_resource_start(pdev
, 1),
587 pci_resource_len(pdev
, 1));
588 if (cirrus
->mmio
== NULL
)
591 ret
= cirrus_mode_config_init(cirrus
);
595 ret
= cirrus_conn_init(cirrus
);
599 ret
= cirrus_pipe_init(cirrus
);
603 drm_mode_config_reset(dev
);
606 pci_set_drvdata(pdev
, dev
);
607 ret
= drm_dev_register(dev
, 0);
611 drm_fbdev_generic_setup(dev
, dev
->mode_config
.preferred_depth
);
615 static void cirrus_pci_remove(struct pci_dev
*pdev
)
617 struct drm_device
*dev
= pci_get_drvdata(pdev
);
620 drm_atomic_helper_shutdown(dev
);
623 static const struct pci_device_id pciidlist
[] = {
625 .vendor
= PCI_VENDOR_ID_CIRRUS
,
626 .device
= PCI_DEVICE_ID_CIRRUS_5446
,
627 /* only bind to the cirrus chip in qemu */
628 .subvendor
= PCI_SUBVENDOR_ID_REDHAT_QUMRANET
,
629 .subdevice
= PCI_SUBDEVICE_ID_QEMU
,
631 .vendor
= PCI_VENDOR_ID_CIRRUS
,
632 .device
= PCI_DEVICE_ID_CIRRUS_5446
,
633 .subvendor
= PCI_VENDOR_ID_XEN
,
636 { /* end if list */ }
639 static struct pci_driver cirrus_pci_driver
= {
641 .id_table
= pciidlist
,
642 .probe
= cirrus_pci_probe
,
643 .remove
= cirrus_pci_remove
,
646 static int __init
cirrus_init(void)
648 if (vgacon_text_force())
650 return pci_register_driver(&cirrus_pci_driver
);
653 static void __exit
cirrus_exit(void)
655 pci_unregister_driver(&cirrus_pci_driver
);
658 module_init(cirrus_init
);
659 module_exit(cirrus_exit
);
661 MODULE_DEVICE_TABLE(pci
, pciidlist
);
662 MODULE_LICENSE("GPL");