diff options
Diffstat (limited to 'drivers/gpu/drm/tiny')
| -rw-r--r-- | drivers/gpu/drm/tiny/Kconfig | 19 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/Makefile | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/cirrus.c | 660 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/gm12u320.c | 24 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/hx8357d.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/ili9225.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/ili9341.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/ili9486.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/mi0283qt.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/repaper.c | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/st7586.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/st7735r.c | 13 |
12 files changed, 722 insertions, 87 deletions
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 4160e74e4751..2b6414f0fa75 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -1,5 +1,24 @@ # SPDX-License-Identifier: GPL-2.0-only +config DRM_CIRRUS_QEMU + tristate "Cirrus driver for QEMU emulated device" + depends on DRM && PCI && MMU + select DRM_KMS_HELPER + select DRM_GEM_SHMEM_HELPER + help + This is a KMS driver for emulated cirrus device in qemu. + It is *NOT* intended for real cirrus devices. This requires + the modesetting userspace X.org driver. + + Cirrus is obsolete, the hardware was designed in the 90ies + and can't keep up with todays needs. More background: + https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/ + + Better alternatives are: + - stdvga (DRM_BOCHS, qemu -vga std, default in qemu 2.2+) + - qxl (DRM_QXL, qemu -vga qxl, works best with spice) + - virtio (DRM_VIRTIO_GPU), qemu -vga virtio) + config DRM_GM12U320 tristate "GM12U320 driver for USB projectors" depends on DRM && USB diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile index c96ceee71453..6ae4e9e5a35f 100644 --- a/drivers/gpu/drm/tiny/Makefile +++ b/drivers/gpu/drm/tiny/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o obj-$(CONFIG_DRM_GM12U320) += gm12u320.o obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c new file mode 100644 index 000000000000..744a8e337e41 --- /dev/null +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -0,0 +1,660 @@ +/* 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/console.h> +#include <linux/module.h> +#include <linux/pci.h> + +#include <video/cirrus.h> +#include <video/vga.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_fb_helper.h> +#include <drm/drm_file.h> +#include <drm/drm_format_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_shmem_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_ioctl.h> +#include <drm/drm_managed.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_simple_kms_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; + struct drm_simple_display_pipe pipe; + struct drm_connector conn; + unsigned int cpp; + unsigned int pitch; + void __iomem *vram; + void __iomem *mmio; +}; + +#define to_cirrus(_dev) container_of(_dev, struct cirrus_device, dev) + +/* ------------------------------------------------------------------ */ +/* + * 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 int cirrus_convert_to(struct drm_framebuffer *fb) +{ + if (fb->format->cpp[0] == 4 && fb->pitches[0] > CIRRUS_MAX_PITCH) { + if (fb->width * 3 <= CIRRUS_MAX_PITCH) + /* convert from XR24 to RG24 */ + return 3; + else + /* convert from XR24 to RG16 */ + return 2; + } + return 0; +} + +static int cirrus_cpp(struct drm_framebuffer *fb) +{ + int convert_cpp = cirrus_convert_to(fb); + + if (convert_cpp) + return convert_cpp; + return fb->format->cpp[0]; +} + +static int cirrus_pitch(struct drm_framebuffer *fb) +{ + int convert_cpp = cirrus_convert_to(fb); + + if (convert_cpp) + return convert_cpp * fb->width; + return fb->pitches[0]; +} + +static void cirrus_set_start_address(struct cirrus_device *cirrus, u32 offset) +{ + int idx; + u32 addr; + u8 tmp; + + if (!drm_dev_enter(&cirrus->dev, &idx)) + return; + + 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); + + drm_dev_exit(idx); +} + +static int cirrus_mode_set(struct cirrus_device *cirrus, + struct drm_display_mode *mode, + struct drm_framebuffer *fb) +{ + int hsyncstart, hsyncend, htotal, hdispend; + int vtotal, vdispend; + int tmp, idx; + int sr07 = 0, hdr = 0; + + if (!drm_dev_enter(&cirrus->dev, &idx)) + return -1; + + 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); + + sr07 = rreg_seq(cirrus, 0x07); + sr07 &= 0xe0; + hdr = 0; + + cirrus->cpp = cirrus_cpp(fb); + switch (cirrus->cpp * 8) { + case 8: + sr07 |= 0x11; + break; + case 16: + sr07 |= 0x17; + hdr = 0xc1; + break; + case 24: + sr07 |= 0x15; + hdr = 0xc5; + break; + case 32: + sr07 |= 0x19; + hdr = 0xc5; + break; + default: + drm_dev_exit(idx); + return -1; + } + + wreg_seq(cirrus, 0x7, sr07); + + /* Program the pitch */ + cirrus->pitch = cirrus_pitch(fb); + tmp = cirrus->pitch / 8; + wreg_crt(cirrus, VGA_CRTC_OFFSET, tmp); + + /* Enable extended blanking and pitch bits, and enable full memory */ + tmp = 0x22; + tmp |= (cirrus->pitch >> 7) & 0x10; + tmp |= (cirrus->pitch >> 6) & 0x40; + wreg_crt(cirrus, 0x1b, tmp); + + /* 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); + + cirrus_set_start_address(cirrus, 0); + + /* Unblank (needed on S3 resume, vgabios doesn't do it then) */ + outb(0x20, 0x3c0); + + drm_dev_exit(idx); + return 0; +} + +static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, + struct drm_rect *rect) +{ + struct cirrus_device *cirrus = to_cirrus(fb->dev); + void *vmap; + int idx, ret; + + ret = -ENODEV; + if (!drm_dev_enter(&cirrus->dev, &idx)) + goto out; + + ret = -ENOMEM; + vmap = drm_gem_shmem_vmap(fb->obj[0]); + if (!vmap) + goto out_dev_exit; + + if (cirrus->cpp == fb->format->cpp[0]) + drm_fb_memcpy_dstclip(cirrus->vram, + vmap, fb, rect); + + else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) + drm_fb_xrgb8888_to_rgb565_dstclip(cirrus->vram, + cirrus->pitch, + vmap, fb, rect, false); + + else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) + drm_fb_xrgb8888_to_rgb888_dstclip(cirrus->vram, + cirrus->pitch, + vmap, fb, rect); + + else + WARN_ON_ONCE("cpp mismatch"); + + drm_gem_shmem_vunmap(fb->obj[0], vmap); + ret = 0; + +out_dev_exit: + drm_dev_exit(idx); +out: + return ret; +} + +static int cirrus_fb_blit_fullscreen(struct drm_framebuffer *fb) +{ + struct drm_rect fullscreen = { + .x1 = 0, + .x2 = fb->width, + .y1 = 0, + .y2 = fb->height, + }; + return cirrus_fb_blit_rect(fb, &fullscreen); +} + +static int cirrus_check_size(int width, int height, + struct drm_framebuffer *fb) +{ + int pitch = width * 2; + + if (fb) + pitch = cirrus_pitch(fb); + + if (pitch > CIRRUS_MAX_PITCH) + return -EINVAL; + if (pitch * height > CIRRUS_VRAM_SIZE) + return -EINVAL; + return 0; +} + +/* ------------------------------------------------------------------ */ +/* cirrus connector */ + +static int cirrus_conn_get_modes(struct drm_connector *conn) +{ + int count; + + count = drm_add_modes_noedid(conn, + conn->dev->mode_config.max_width, + conn->dev->mode_config.max_height); + drm_set_preferred_mode(conn, 1024, 768); + return count; +} + +static const struct drm_connector_helper_funcs cirrus_conn_helper_funcs = { + .get_modes = cirrus_conn_get_modes, +}; + +static const struct drm_connector_funcs cirrus_conn_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_conn_init(struct cirrus_device *cirrus) +{ + drm_connector_helper_add(&cirrus->conn, &cirrus_conn_helper_funcs); + return drm_connector_init(&cirrus->dev, &cirrus->conn, + &cirrus_conn_funcs, DRM_MODE_CONNECTOR_VGA); + +} + +/* ------------------------------------------------------------------ */ +/* cirrus (simple) display pipe */ + +static enum drm_mode_status cirrus_pipe_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode) +{ + if (cirrus_check_size(mode->hdisplay, mode->vdisplay, NULL) < 0) + return MODE_BAD; + return MODE_OK; +} + +static int cirrus_pipe_check(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *plane_state, + struct drm_crtc_state *crtc_state) +{ + struct drm_framebuffer *fb = plane_state->fb; + + if (!fb) + return 0; + return cirrus_check_size(fb->width, fb->height, fb); +} + +static void cirrus_pipe_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state, + struct drm_plane_state *plane_state) +{ + struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev); + + cirrus_mode_set(cirrus, &crtc_state->mode, plane_state->fb); + cirrus_fb_blit_fullscreen(plane_state->fb); +} + +static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_state) +{ + struct cirrus_device *cirrus = to_cirrus(pipe->crtc.dev); + struct drm_plane_state *state = pipe->plane.state; + struct drm_crtc *crtc = &pipe->crtc; + struct drm_rect rect; + + if (pipe->plane.state->fb && + cirrus->cpp != cirrus_cpp(pipe->plane.state->fb)) + cirrus_mode_set(cirrus, &crtc->mode, + pipe->plane.state->fb); + + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) + cirrus_fb_blit_rect(pipe->plane.state->fb, &rect); +} + +static const struct drm_simple_display_pipe_funcs cirrus_pipe_funcs = { + .mode_valid = cirrus_pipe_mode_valid, + .check = cirrus_pipe_check, + .enable = cirrus_pipe_enable, + .update = cirrus_pipe_update, +}; + +static const uint32_t cirrus_formats[] = { + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888, +}; + +static const uint64_t cirrus_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + +static int cirrus_pipe_init(struct cirrus_device *cirrus) +{ + return drm_simple_display_pipe_init(&cirrus->dev, + &cirrus->pipe, + &cirrus_pipe_funcs, + cirrus_formats, + ARRAY_SIZE(cirrus_formats), + cirrus_modifiers, + &cirrus->conn); +} + +/* ------------------------------------------------------------------ */ +/* cirrus framebuffers & mode config */ + +static struct drm_framebuffer* +cirrus_fb_create(struct drm_device *dev, struct drm_file *file_priv, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + if (mode_cmd->pixel_format != DRM_FORMAT_RGB565 && + mode_cmd->pixel_format != DRM_FORMAT_RGB888 && + mode_cmd->pixel_format != DRM_FORMAT_XRGB8888) + return ERR_PTR(-EINVAL); + if (cirrus_check_size(mode_cmd->width, mode_cmd->height, NULL) < 0) + return ERR_PTR(-EINVAL); + return drm_gem_fb_create_with_dirty(dev, file_priv, mode_cmd); +} + +static const struct drm_mode_config_funcs cirrus_mode_config_funcs = { + .fb_create = cirrus_fb_create, + .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 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_fb_helper_remove_conflicting_pci_framebuffers(pdev, "cirrusdrmfb"); + 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_conn_init(cirrus); + if (ret < 0) + return ret; + + ret = cirrus_pipe_init(cirrus); + if (ret < 0) + return ret; + + drm_mode_config_reset(dev); + + dev->pdev = pdev; + pci_set_drvdata(pdev, dev); + ret = drm_dev_register(dev, 0); + if (ret) + return ret; + + drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth); + 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 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, +}; + +static int __init cirrus_init(void) +{ + if (vgacon_text_force()) + return -EINVAL; + return pci_register_driver(&cirrus_pci_driver); +} + +static void __exit cirrus_exit(void) +{ + pci_unregister_driver(&cirrus_pci_driver); +} + +module_init(cirrus_init); +module_exit(cirrus_exit); + +MODULE_DEVICE_TABLE(pci, pciidlist); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index 6f0ea2827d62..cc397671f689 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -98,6 +98,8 @@ struct gm12u320_device { } fb_update; }; +#define to_gm12u320(__dev) container_of(__dev, struct gm12u320_device, dev) + static const char cmd_data[CMD_SIZE] = { 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x68, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, @@ -408,7 +410,7 @@ err: static void gm12u320_fb_mark_dirty(struct drm_framebuffer *fb, struct drm_rect *dirty) { - struct gm12u320_device *gm12u320 = fb->dev->dev_private; + struct gm12u320_device *gm12u320 = to_gm12u320(fb->dev); struct drm_framebuffer *old_fb = NULL; bool wakeup = false; @@ -558,7 +560,7 @@ static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_plane_state *plane_state) { struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT }; - struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private; + struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev); gm12u320->fb_update.draw_status_timeout = FIRST_FRAME_TIMEOUT; gm12u320_fb_mark_dirty(plane_state->fb, &rect); @@ -566,7 +568,7 @@ static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe, static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe) { - struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private; + struct gm12u320_device *gm12u320 = to_gm12u320(pipe->crtc.dev); gm12u320_stop_fb_update(gm12u320); } @@ -631,22 +633,16 @@ static int gm12u320_usb_probe(struct usb_interface *interface, if (interface->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; - gm12u320 = kzalloc(sizeof(*gm12u320), GFP_KERNEL); - if (gm12u320 == NULL) - return -ENOMEM; + gm12u320 = devm_drm_dev_alloc(&interface->dev, &gm12u320_drm_driver, + struct gm12u320_device, dev); + if (IS_ERR(gm12u320)) + return PTR_ERR(gm12u320); gm12u320->udev = interface_to_usbdev(interface); INIT_DELAYED_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work); mutex_init(&gm12u320->fb_update.lock); dev = &gm12u320->dev; - ret = devm_drm_dev_init(&interface->dev, dev, &gm12u320_drm_driver); - if (ret) { - kfree(gm12u320); - return ret; - } - dev->dev_private = gm12u320; - drmm_add_final_kfree(dev, gm12u320); ret = drmm_mode_config_init(dev); if (ret) @@ -711,7 +707,7 @@ static __maybe_unused int gm12u320_suspend(struct usb_interface *interface, static __maybe_unused int gm12u320_resume(struct usb_interface *interface) { struct drm_device *dev = usb_get_intfdata(interface); - struct gm12u320_device *gm12u320 = dev->dev_private; + struct gm12u320_device *gm12u320 = to_gm12u320(dev); gm12u320_set_ecomode(gm12u320); diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index af7f3d10aac3..b4bc358a3269 100644 --- a/drivers/gpu/drm/tiny/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -226,17 +226,12 @@ static int hx8357d_probe(struct spi_device *spi) u32 rotation = 0; int ret; - dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); - if (!dbidev) - return -ENOMEM; + dbidev = devm_drm_dev_alloc(dev, &hx8357d_driver, + struct mipi_dbi_dev, drm); + if (IS_ERR(dbidev)) + return PTR_ERR(dbidev); drm = &dbidev->drm; - ret = devm_drm_dev_init(dev, drm, &hx8357d_driver); - if (ret) { - kfree(dbidev); - return ret; - } - drmm_add_final_kfree(drm, dbidev); dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW); if (IS_ERR(dc)) { diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index 118477af4491..d1a5ab6747d5 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -376,18 +376,13 @@ static int ili9225_probe(struct spi_device *spi) u32 rotation = 0; int ret; - dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); - if (!dbidev) - return -ENOMEM; + dbidev = devm_drm_dev_alloc(dev, &ili9225_driver, + struct mipi_dbi_dev, drm); + if (IS_ERR(dbidev)) + return PTR_ERR(dbidev); dbi = &dbidev->dbi; drm = &dbidev->drm; - ret = devm_drm_dev_init(dev, drm, &ili9225_driver); - if (ret) { - kfree(dbidev); - return ret; - } - drmm_add_final_kfree(drm, dbidev); dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(dbi->reset)) { diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index e152de369019..bb819f45a5d3 100644 --- a/drivers/gpu/drm/tiny/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -183,18 +183,13 @@ static int ili9341_probe(struct spi_device *spi) u32 rotation = 0; int ret; - dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); - if (!dbidev) - return -ENOMEM; + dbidev = devm_drm_dev_alloc(dev, &ili9341_driver, + struct mipi_dbi_dev, drm); + if (IS_ERR(dbidev)) + return PTR_ERR(dbidev); dbi = &dbidev->dbi; drm = &dbidev->drm; - ret = devm_drm_dev_init(dev, drm, &ili9341_driver); - if (ret) { - kfree(dbidev); - return ret; - } - drmm_add_final_kfree(drm, dbidev); dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(dbi->reset)) { diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c index c4079bf9e2c8..2702ea557d29 100644 --- a/drivers/gpu/drm/tiny/ili9486.c +++ b/drivers/gpu/drm/tiny/ili9486.c @@ -197,18 +197,13 @@ static int ili9486_probe(struct spi_device *spi) u32 rotation = 0; int ret; - dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); - if (!dbidev) - return -ENOMEM; + dbidev = devm_drm_dev_alloc(dev, &ili9486_driver, + struct mipi_dbi_dev, drm); + if (IS_ERR(dbidev)) + return PTR_ERR(dbidev); dbi = &dbidev->dbi; drm = &dbidev->drm; - ret = devm_drm_dev_init(dev, drm, &ili9486_driver); - if (ret) { - kfree(dbidev); - return ret; - } - drmm_add_final_kfree(drm, dbidev); dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(dbi->reset)) { diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index decaf57053ff..08ac549ab0f7 100644 --- a/drivers/gpu/drm/tiny/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -187,18 +187,13 @@ static int mi0283qt_probe(struct spi_device *spi) u32 rotation = 0; int ret; - dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); - if (!dbidev) - return -ENOMEM; + dbidev = devm_drm_dev_alloc(dev, &mi0283qt_driver, + struct mipi_dbi_dev, drm); + if (IS_ERR(dbidev)) + return PTR_ERR(dbidev); dbi = &dbidev->dbi; drm = &dbidev->drm; - ret = devm_drm_dev_init(dev, drm, &mi0283qt_driver); - if (ret) { - kfree(dbidev); - return ret; - } - drmm_add_final_kfree(drm, dbidev); dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(dbi->reset)) { diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 862c3ee6055d..1c0e7169545b 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -1002,19 +1002,13 @@ static int repaper_probe(struct spi_device *spi) } } - epd = kzalloc(sizeof(*epd), GFP_KERNEL); - if (!epd) - return -ENOMEM; + epd = devm_drm_dev_alloc(dev, &repaper_driver, + struct repaper_epd, drm); + if (IS_ERR(epd)) + return PTR_ERR(epd); drm = &epd->drm; - ret = devm_drm_dev_init(dev, drm, &repaper_driver); - if (ret) { - kfree(epd); - return ret; - } - drmm_add_final_kfree(drm, epd); - ret = drmm_mode_config_init(drm); if (ret) return ret; diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index c3295c717ba6..2a1fae422f7a 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -317,18 +317,13 @@ static int st7586_probe(struct spi_device *spi) size_t bufsize; int ret; - dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); - if (!dbidev) - return -ENOMEM; + dbidev = devm_drm_dev_alloc(dev, &st7586_driver, + struct mipi_dbi_dev, drm); + if (IS_ERR(dbidev)) + return PTR_ERR(dbidev); dbi = &dbidev->dbi; drm = &dbidev->drm; - ret = devm_drm_dev_init(dev, drm, &st7586_driver); - if (ret) { - kfree(dbidev); - return ret; - } - drmm_add_final_kfree(drm, dbidev); bufsize = (st7586_mode.vdisplay + 2) / 3 * st7586_mode.hdisplay; diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index c2c7dc0224dd..0af1b15efdf8 100644 --- a/drivers/gpu/drm/tiny/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -195,21 +195,16 @@ static int st7735r_probe(struct spi_device *spi) if (!cfg) cfg = (void *)spi_get_device_id(spi)->driver_data; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + priv = devm_drm_dev_alloc(dev, &st7735r_driver, + struct st7735r_priv, dbidev.drm); + if (IS_ERR(priv)) + return PTR_ERR(priv); dbidev = &priv->dbidev; priv->cfg = cfg; dbi = &dbidev->dbi; drm = &dbidev->drm; - ret = devm_drm_dev_init(dev, drm, &st7735r_driver); - if (ret) { - kfree(dbidev); - return ret; - } - drmm_add_final_kfree(drm, dbidev); dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(dbi->reset)) { |
