From patchwork Thu Jun 25 12:00:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11624959 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 851A8913 for ; Thu, 25 Jun 2020 12:00:20 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6D5442067D for ; Thu, 25 Jun 2020 12:00:20 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6D5442067D Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 434E06EB48; Thu, 25 Jun 2020 12:00:16 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 006556EBBA for ; Thu, 25 Jun 2020 12:00:14 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 42BEAACC5; Thu, 25 Jun 2020 12:00:13 +0000 (UTC) From: Thomas Zimmermann To: maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@linux.ie, daniel@ffwll.ch, kraxel@redhat.com, lgirdwood@gmail.com, broonie@kernel.org, robh@kernel.org, sam@ravnborg.org, emil.l.velikov@gmail.com, noralf@tronnes.org, geert+renesas@glider.be, hdegoede@redhat.com Subject: [PATCH 1/9] drm/format-helper: Pass destination pitch to drm_fb_memcpy_dstclip() Date: Thu, 25 Jun 2020 14:00:03 +0200 Message-Id: <20200625120011.16168-2-tzimmermann@suse.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200625120011.16168-1-tzimmermann@suse.de> References: <20200625120011.16168-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The memcpy's destination buffer might have a different pitch than the source. Support different pitches as function argument. Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_format_helper.c | 9 +++++---- drivers/gpu/drm/mgag200/mgag200_mode.c | 2 +- drivers/gpu/drm/tiny/cirrus.c | 2 +- include/drm/drm_format_helper.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index c043ca364c86..8d5a683afea7 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -52,6 +52,7 @@ EXPORT_SYMBOL(drm_fb_memcpy); /** * drm_fb_memcpy_dstclip - Copy clip buffer * @dst: Destination buffer (iomem) + * @dst_pitch: Number of bytes between two consecutive scanlines within dst * @vaddr: Source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy @@ -59,12 +60,12 @@ EXPORT_SYMBOL(drm_fb_memcpy); * This function applies clipping on dst, i.e. the destination is a * full (iomem) framebuffer but only the clip rect content is copied over. */ -void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, - struct drm_framebuffer *fb, +void drm_fb_memcpy_dstclip(void __iomem *dst, unsigned int dst_pitch, + void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip) { unsigned int cpp = fb->format->cpp[0]; - unsigned int offset = clip_offset(clip, fb->pitches[0], cpp); + unsigned int offset = clip_offset(clip, dst_pitch, cpp); size_t len = (clip->x2 - clip->x1) * cpp; unsigned int y, lines = clip->y2 - clip->y1; @@ -73,7 +74,7 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, for (y = 0; y < lines; y++) { memcpy_toio(dst, vaddr, len); vaddr += fb->pitches[0]; - dst += fb->pitches[0]; + dst += dst_pitch; } } EXPORT_SYMBOL(drm_fb_memcpy_dstclip); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index f16bd278ab7e..7d4f3a62d885 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1586,7 +1586,7 @@ mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb, if (drm_WARN_ON(dev, !vmap)) return; /* BUG: SHMEM BO should always be vmapped */ - drm_fb_memcpy_dstclip(mdev->vram, vmap, fb, clip); + drm_fb_memcpy_dstclip(mdev->vram, fb->pitches[0], vmap, fb, clip); drm_gem_shmem_vunmap(fb->obj[0], vmap); diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index 744a8e337e41..2dd9e5e31e3d 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -327,7 +327,7 @@ static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, goto out_dev_exit; if (cirrus->cpp == fb->format->cpp[0]) - drm_fb_memcpy_dstclip(cirrus->vram, + drm_fb_memcpy_dstclip(cirrus->vram, fb->pitches[0], vmap, fb, rect); else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 5f9e37032468..2b5036a5fbe7 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -11,7 +11,7 @@ struct drm_rect; void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip); -void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, +void drm_fb_memcpy_dstclip(void __iomem *dst, unsigned int dst_pitch, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip); void drm_fb_swab(void *dst, void *src, struct drm_framebuffer *fb, From patchwork Thu Jun 25 12:00:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11624963 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 63F2E14E3 for ; Thu, 25 Jun 2020 12:00:24 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4B78C204EC for ; Thu, 25 Jun 2020 12:00:24 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4B78C204EC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D016F6EBC1; Thu, 25 Jun 2020 12:00:16 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 32CC96EBBB for ; Thu, 25 Jun 2020 12:00:15 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 733C4ACF0; Thu, 25 Jun 2020 12:00:13 +0000 (UTC) From: Thomas Zimmermann To: maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@linux.ie, daniel@ffwll.ch, kraxel@redhat.com, lgirdwood@gmail.com, broonie@kernel.org, robh@kernel.org, sam@ravnborg.org, emil.l.velikov@gmail.com, noralf@tronnes.org, geert+renesas@glider.be, hdegoede@redhat.com Subject: [PATCH 2/9] drm/format-helper: Add blitter functions Date: Thu, 25 Jun 2020 14:00:04 +0200 Message-Id: <20200625120011.16168-3-tzimmermann@suse.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200625120011.16168-1-tzimmermann@suse.de> References: <20200625120011.16168-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The blitter functions copy a framebuffer to I/O memory using one of the existing conversion functions. Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_format_helper.c | 87 +++++++++++++++++++++++++++++ include/drm/drm_format_helper.h | 8 +++ 2 files changed, 95 insertions(+) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 8d5a683afea7..0e885cd34107 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -344,3 +344,90 @@ void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, } EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); +/** + * drm_fb_blit_rect_dstclip - Copy parts of a framebuffer to display memory + * @dst: The display memory to copy to + * @dst_pitch: Number of bytes between two consecutive scanlines within dst + * @dst_format: FOURCC code of the display's color format + * @vmap: The framebuffer memory to copy from + * @fb: The framebuffer to copy from + * @clip: Clip rectangle area to copy + * + * This function copies parts of a framebuffer to display memory. If the + * formats of the display and the framebuffer mismatch, the blit function + * will attempt to convert between them. + * + * Use drm_fb_blit_dstclip() to copy the full framebuffer. + * + * Returns: + * 0 on success, or + * -EINVAL if the color-format conversion failed, or + * a negative error code otherwise. + */ +int drm_fb_blit_rect_dstclip(void __iomem *dst, unsigned int dst_pitch, + uint32_t dst_format, void *vmap, + struct drm_framebuffer *fb, + struct drm_rect *clip) +{ + uint32_t fb_format = fb->format->format; + + /* treat alpha channel like filler bits */ + if (fb_format == DRM_FORMAT_ARGB8888) + fb_format = DRM_FORMAT_XRGB8888; + if (dst_format == DRM_FORMAT_ARGB8888) + dst_format = DRM_FORMAT_XRGB8888; + + if (dst_format == fb_format) { + drm_fb_memcpy_dstclip(dst, dst_pitch, vmap, fb, clip); + return 0; + + } else if (dst_format == DRM_FORMAT_RGB565) { + if (fb_format == DRM_FORMAT_XRGB8888) { + drm_fb_xrgb8888_to_rgb565_dstclip(dst, dst_pitch, + vmap, fb, clip, + false); + return 0; + } + } else if (dst_format == DRM_FORMAT_RGB888) { + if (fb_format == DRM_FORMAT_XRGB8888) { + drm_fb_xrgb8888_to_rgb888_dstclip(dst, dst_pitch, + vmap, fb, clip); + return 0; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL(drm_fb_blit_rect_dstclip); + +/** + * drm_fb_blit_dstclip - Copy framebuffer to display memory + * @dst: The display memory to copy to + * @dst_pitch: Number of bytes between two consecutive scanlines within dst + * @dst_format: FOURCC code of the display's color format + * @vmap: The framebuffer memory to copy from + * @fb: The framebuffer to copy from + * + * This function copies a full framebuffer to display memory. If the formats + * of the display and the framebuffer mismatch, the copy function will + * attempt to convert between them. + * + * See drm_fb_blit_rect_dstclip() for more inforamtion. + * + * Returns: + * 0 on success, or a negative error code otherwise. + */ +int drm_fb_blit_dstclip(void __iomem *dst, unsigned int dst_pitch, + uint32_t dst_format, void *vmap, + struct drm_framebuffer *fb) +{ + struct drm_rect fullscreen = { + .x1 = 0, + .x2 = fb->width, + .y1 = 0, + .y2 = fb->height, + }; + return drm_fb_blit_rect_dstclip(dst, dst_pitch, dst_format, vmap, fb, + &fullscreen); +} +EXPORT_SYMBOL(drm_fb_blit_dstclip); diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 2b5036a5fbe7..4e0258a61311 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -28,4 +28,12 @@ void drm_fb_xrgb8888_to_rgb888_dstclip(void __iomem *dst, unsigned int dst_pitch void drm_fb_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip); +int drm_fb_blit_rect_dstclip(void __iomem *dst, unsigned int dst_pitch, + uint32_t dst_format, void *vmap, + struct drm_framebuffer *fb, + struct drm_rect *rect); +int drm_fb_blit_dstclip(void __iomem *dst, unsigned int dst_pitch, + uint32_t dst_format, void *vmap, + struct drm_framebuffer *fb); + #endif /* __LINUX_DRM_FORMAT_HELPER_H */ From patchwork Thu Jun 25 12:00:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11624957 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C327814E3 for ; Thu, 25 Jun 2020 12:00:17 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AA6DB207D8 for ; Thu, 25 Jun 2020 12:00:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org AA6DB207D8 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 264676EB42; Thu, 25 Jun 2020 12:00:16 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 63B916EB42 for ; Thu, 25 Jun 2020 12:00:15 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id B58FAAD5F; Thu, 25 Jun 2020 12:00:13 +0000 (UTC) From: Thomas Zimmermann To: maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@linux.ie, daniel@ffwll.ch, kraxel@redhat.com, lgirdwood@gmail.com, broonie@kernel.org, robh@kernel.org, sam@ravnborg.org, emil.l.velikov@gmail.com, noralf@tronnes.org, geert+renesas@glider.be, hdegoede@redhat.com Subject: [PATCH 3/9] drm: Add simplekms driver Date: Thu, 25 Jun 2020 14:00:05 +0200 Message-Id: <20200625120011.16168-4-tzimmermann@suse.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200625120011.16168-1-tzimmermann@suse.de> References: <20200625120011.16168-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The simplekms driver is a DRM driver for simplefb framebuffers as provided by the kernel's boot code. This driver enables basic graphical output on many different graphics devices that are provided by the platform (e.g., EFI, VESA, embedded framebuffers). With the kernel's simplefb infrastructure, the kernel receives a pre-configured framebuffer from the system (i.e., firmware, boot loader). It creates a platform device to which simplekms attaches. The system's framebuffer consists of a memory range, size and format. Based on these values, simplekms creates a DRM devices. No actual modesetting is possible. Signed-off-by: Thomas Zimmermann --- MAINTAINERS | 6 + drivers/gpu/drm/tiny/Kconfig | 16 + drivers/gpu/drm/tiny/Makefile | 1 + drivers/gpu/drm/tiny/simplekms.c | 495 +++++++++++++++++++++++++++++++ 4 files changed, 518 insertions(+) create mode 100644 drivers/gpu/drm/tiny/simplekms.c diff --git a/MAINTAINERS b/MAINTAINERS index f17d99164a77..ac517dc8d05d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5505,6 +5505,12 @@ S: Orphan / Obsolete F: drivers/gpu/drm/savage/ F: include/uapi/drm/savage_drm.h +DRM DRIVER FOR SIMPLE FRAMEBUFFERS +M: Thomas Zimmermann +S: Maintained +T: git git://anongit.freedesktop.org/drm/drm-misc +F: drivers/gpu/drm/tiny/simplekms.c + DRM DRIVER FOR SIS VIDEO CARDS S: Orphan / Obsolete F: drivers/gpu/drm/sis/ diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 2b6414f0fa75..50dbde8bdcb2 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -28,6 +28,22 @@ config DRM_GM12U320 This is a KMS driver for projectors which use the GM12U320 chipset for video transfer over USB2/3, such as the Acer C120 mini projector. +config DRM_SIMPLEKMS + tristate "Simple framebuffer driver" + depends on DRM + select DRM_GEM_SHMEM_HELPER + select DRM_KMS_HELPER + help + DRM driver for simple platform-provided framebuffers. + + This driver assumes that the display hardware has been initialized + by the firmware or bootloader before the kernel boots. Scanout + buffer, size, and display format must be provided via device tree, + UEFI, VESA, etc. + + On x86 and compatible, you should also select CONFIG_X86_SYSFB to + use UEFI and VESA framebuffers. + config TINYDRM_HX8357D tristate "DRM support for HX8357D display panels" depends on DRM && SPI diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile index 6ae4e9e5a35f..e83fbbfa7344 100644 --- a/drivers/gpu/drm/tiny/Makefile +++ b/drivers/gpu/drm/tiny/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o obj-$(CONFIG_DRM_GM12U320) += gm12u320.o +obj-$(CONFIG_DRM_SIMPLEKMS) += simplekms.o obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o obj-$(CONFIG_TINYDRM_ILI9341) += ili9341.o diff --git a/drivers/gpu/drm/tiny/simplekms.c b/drivers/gpu/drm/tiny/simplekms.c new file mode 100644 index 000000000000..dc7cf3983945 --- /dev/null +++ b/drivers/gpu/drm/tiny/simplekms.c @@ -0,0 +1,495 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "simplekms" +#define DRIVER_DESC "DRM driver for simple-framebuffer platform devices" +#define DRIVER_DATE "20200625" +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 + +/* + * Assume a monitor resolution of 96 dpi to + * get a somewhat reasonable screen size. + */ +#define RES_MM(d) \ + (((d) * 254ul) / (96ul * 10ul)) + +#define SIMPLEKMS_MODE(hd, vd) \ + DRM_SIMPLE_MODE(hd, vd, RES_MM(hd), RES_MM(vd)) + +/* + * Helpers for simplefb + */ + +static int +simplefb_get_validated_int(struct drm_device *dev, const char *name, + uint32_t value) +{ + if (value > INT_MAX) { + drm_err(dev, "simplefb: invalid framebuffer %s of %u\n", + name, value); + return -EINVAL; + } + return (int)value; +} + +static int +simplefb_get_validated_int0(struct drm_device *dev, const char *name, + uint32_t value) +{ + if (!value) { + drm_err(dev, "simplefb: invalid framebuffer %s of %u\n", + name, value); + return -EINVAL; + } + return simplefb_get_validated_int(dev, name, value); +} + +static const struct drm_format_info * +simplefb_get_validated_format(struct drm_device *dev, const char *format_name) +{ + static const struct simplefb_format formats[] = SIMPLEFB_FORMATS; + const struct simplefb_format *fmt = formats; + const struct simplefb_format *end = fmt + ARRAY_SIZE(formats); + + if (!format_name) { + drm_err(dev, "simplefb: missing framebuffer format\n"); + return ERR_PTR(-EINVAL); + } + + while (fmt < end) { + if (!strcmp(format_name, fmt->name)) + return drm_format_info(fmt->fourcc); + ++fmt; + } + + drm_err(dev, "simplefb: unknown framebuffer format %s\n", + format_name); + + return ERR_PTR(-EINVAL); +} + +static int +simplefb_get_width_pd(struct drm_device *dev, + const struct simplefb_platform_data *pd) +{ + return simplefb_get_validated_int0(dev, "width", pd->width); +} + +static int +simplefb_get_height_pd(struct drm_device *dev, + const struct simplefb_platform_data *pd) +{ + return simplefb_get_validated_int0(dev, "height", pd->height); +} + +static int +simplefb_get_stride_pd(struct drm_device *dev, + const struct simplefb_platform_data *pd) +{ + return simplefb_get_validated_int(dev, "stride", pd->stride); +} + +static const struct drm_format_info * +simplefb_get_format_pd(struct drm_device *dev, + const struct simplefb_platform_data *pd) +{ + return simplefb_get_validated_format(dev, pd->format); +} + +/* + * Simple Framebuffer device + */ + +struct simplekms_device { + struct drm_device dev; + struct platform_device *pdev; + + /* simplefb settings */ + struct drm_display_mode mode; + const struct drm_format_info *format; + unsigned int pitch; + + /* memory management */ + struct resource *mem; + void __iomem *screen_base; + + /* modesetting */ + struct drm_connector connector; + struct drm_simple_display_pipe pipe; +}; + +static struct simplekms_device *simplekms_device_of_dev(struct drm_device *dev) +{ + return container_of(dev, struct simplekms_device, dev); +} + +/* + * Simplefb settings + */ + +static struct drm_display_mode simplekms_mode(unsigned int width, + unsigned int height) +{ + struct drm_display_mode mode = { SIMPLEKMS_MODE(width, height) }; + + mode.clock = 60 /* Hz */ * mode.hdisplay * mode.vdisplay; + drm_mode_set_name(&mode); + + return mode; +} + +static int simplekms_device_init_fb(struct simplekms_device *sdev) +{ + int width, height, stride; + const struct drm_format_info *format; + struct drm_format_name_buf buf; + struct drm_device *dev = &sdev->dev; + struct platform_device *pdev = sdev->pdev; + const struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev); + + if (pd) { + width = simplefb_get_width_pd(dev, pd); + if (width < 0) + return width; + height = simplefb_get_height_pd(dev, pd); + if (height < 0) + return height; + stride = simplefb_get_stride_pd(dev, pd); + if (stride < 0) + return stride; + format = simplefb_get_format_pd(dev, pd); + if (IS_ERR(format)) + return PTR_ERR(format); + } else { + drm_err(dev, "no simplefb configuration found\n"); + return -ENODEV; + } + + sdev->mode = simplekms_mode(width, height); + sdev->format = format; + sdev->pitch = stride; + + drm_dbg_kms(dev, "display mode={" DRM_MODE_FMT "}\n", + DRM_MODE_ARG(&sdev->mode)); + drm_dbg_kms(dev, + "framebuffer format=\"%s\", size=%dx%d, stride=%d byte\n", + drm_get_format_name(format->format, &buf), width, + height, stride); + + return 0; +} + +/* + * Memory management + */ + +static int simplekms_device_init_mm(struct simplekms_device *sdev) +{ + struct platform_device *pdev = sdev->pdev; + struct resource *mem; + void __iomem *screen_base; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) + return -EINVAL; + + screen_base = devm_ioremap_wc(&pdev->dev, mem->start, + resource_size(mem)); + if (!screen_base) + return -ENOMEM; + + sdev->mem = mem; + sdev->screen_base = screen_base; + + return 0; +} + +/* + * Modesetting + */ + +/* + * Support all formats of simplefb and maybe more; in order + * of preference. The display's update function will do any + * conversion necessary. + * + * TODO: Add blit helpers for remaining formats and uncomment + * constants. + */ +static const uint32_t simplekms_formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGB565, + //DRM_FORMAT_XRGB1555, + //DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGB888, + //DRM_FORMAT_XRGB2101010, + //DRM_FORMAT_ARGB2101010, +}; + +static const uint64_t simplekms_format_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + +static int simplekms_connector_get_modes(struct drm_connector *connector) +{ + struct simplekms_device *sdev = simplekms_device_of_dev(connector->dev); + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->dev, &sdev->mode); + if (!mode) + return 0; + + if (mode->name[0] == '\0') + drm_mode_set_name(mode); + + mode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + + if (mode->width_mm) + connector->display_info.width_mm = mode->width_mm; + if (mode->height_mm) + connector->display_info.height_mm = mode->height_mm; + + return 1; +} + +static const struct drm_connector_helper_funcs simplekms_connector_helper_funcs = { + .get_modes = simplekms_connector_get_modes, +}; + +static const struct drm_connector_funcs simplekms_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int +simplekms_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, + const struct drm_display_mode *mode) +{ + struct simplekms_device *sdev = simplekms_device_of_dev(pipe->connector->dev); + + if (mode->hdisplay != sdev->mode.hdisplay && + mode->vdisplay != sdev->mode.vdisplay) + return MODE_ONE_SIZE; + else if (mode->hdisplay != sdev->mode.hdisplay) + return MODE_ONE_WIDTH; + else if (mode->vdisplay != sdev->mode.vdisplay) + return MODE_ONE_HEIGHT; + + return MODE_OK; +} + +static void +simplekms_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state, + struct drm_plane_state *plane_state) +{ + struct simplekms_device *sdev = simplekms_device_of_dev(pipe->connector->dev); + struct drm_plane_state *state = pipe->plane.state; + struct drm_framebuffer *fb = state->fb; + void *vmap; + + vmap = drm_gem_shmem_vmap(fb->obj[0]); + if (!vmap) + return; + + drm_fb_blit_dstclip(sdev->screen_base, sdev->pitch, + sdev->format->format, vmap, fb); + + drm_gem_shmem_vunmap(fb->obj[0], vmap); +} + +static void +simplekms_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_plane_state) +{ + struct simplekms_device *sdev = simplekms_device_of_dev(pipe->connector->dev); + struct drm_plane_state *state = pipe->plane.state; + struct drm_framebuffer *fb = state->fb; + struct drm_rect clip; + void *vmap; + + if (!drm_atomic_helper_damage_merged(old_plane_state, state, &clip)) + return; + + vmap = drm_gem_shmem_vmap(fb->obj[0]); + if (!vmap) + return; + + drm_fb_blit_rect_dstclip(sdev->screen_base, sdev->pitch, + sdev->format->format, vmap, fb, &clip); + + drm_gem_shmem_vunmap(fb->obj[0], vmap); +} + +static const struct drm_simple_display_pipe_funcs +simplekms_simple_display_pipe_funcs = { + .mode_valid = simplekms_simple_display_pipe_mode_valid, + .enable = simplekms_simple_display_pipe_enable, + .update = simplekms_simple_display_pipe_update, + .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, +}; + +static const struct drm_mode_config_funcs simplekms_mode_config_funcs = { + .fb_create = drm_gem_fb_create_with_dirty, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int simplekms_device_init_modeset(struct simplekms_device *sdev) +{ + struct drm_device *dev = &sdev->dev; + struct drm_display_mode *mode = &sdev->mode; + struct drm_connector *connector = &sdev->connector; + struct drm_simple_display_pipe *pipe = &sdev->pipe; + int ret; + + ret = drmm_mode_config_init(dev); + if (ret) + return ret; + + dev->mode_config.min_width = mode->hdisplay; + dev->mode_config.max_width = mode->hdisplay; + dev->mode_config.min_height = mode->vdisplay; + dev->mode_config.max_height = mode->vdisplay; + dev->mode_config.prefer_shadow = true; + dev->mode_config.preferred_depth = sdev->format->cpp[0] * 8; + dev->mode_config.funcs = &simplekms_mode_config_funcs; + + drm_connector_helper_add(connector, &simplekms_connector_helper_funcs); + ret = drm_connector_init(dev, connector, &simplekms_connector_funcs, + DRM_MODE_CONNECTOR_Unknown); + if (ret) + return ret; + + ret = drm_simple_display_pipe_init(dev, pipe, + &simplekms_simple_display_pipe_funcs, + simplekms_formats, + ARRAY_SIZE(simplekms_formats), + simplekms_format_modifiers, + connector); + if (ret) + return ret; + + drm_mode_config_reset(dev); + + return 0; +} + +/* + * Init / Cleanup + */ + +static void simplekms_device_cleanup(struct simplekms_device* sdev) +{ + struct drm_device *dev = &sdev->dev; + + drm_dev_unregister(dev); +} + +static struct simplekms_device * +simplekms_device_create(struct drm_driver *drv, struct platform_device *pdev) +{ + struct simplekms_device *sdev; + int ret; + + sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simplekms_device, + dev); + if (IS_ERR(sdev)) + return ERR_CAST(sdev); + sdev->pdev = pdev; + + ret = simplekms_device_init_fb(sdev); + if (ret) + return ERR_PTR(ret); + ret = simplekms_device_init_mm(sdev); + if (ret) + return ERR_PTR(ret); + ret = simplekms_device_init_modeset(sdev); + if (ret) + return ERR_PTR(ret); + + return sdev; +} + +/* + * DRM driver + */ + +DEFINE_DRM_GEM_FOPS(simplekms_fops); + +static struct drm_driver simplekms_driver = { + DRM_GEM_SHMEM_DRIVER_OPS, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET, + .fops = &simplekms_fops, +}; + +/* + * Platform driver + */ + +static int simplekms_probe(struct platform_device *pdev) +{ + struct simplekms_device *sdev; + struct drm_device *dev; + int ret; + + sdev = simplekms_device_create(&simplekms_driver, pdev); + if (IS_ERR(sdev)) + return PTR_ERR(sdev); + dev = &sdev->dev; + + ret = drm_dev_register(dev, 0); + if (ret) + return ret; + + return 0; +} + +static int simplekms_remove(struct platform_device *pdev) +{ + struct simplekms_device *sdev = platform_get_drvdata(pdev); + + simplekms_device_cleanup(sdev); + + return 0; +} + +static struct platform_driver simplekms_platform_driver = { + .driver = { + .name = "simple-framebuffer", /* connect to sysfb */ + }, + .probe = simplekms_probe, + .remove = simplekms_remove, +}; + +module_platform_driver(simplekms_platform_driver); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL v2"); From patchwork Thu Jun 25 12:00:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11624965 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 33493913 for ; Thu, 25 Jun 2020 12:00:26 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1B2F0204EC for ; Thu, 25 Jun 2020 12:00:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1B2F0204EC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B3B786EBC0; Thu, 25 Jun 2020 12:00:16 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8F70F6EBBA for ; Thu, 25 Jun 2020 12:00:15 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id E6348AD6B; Thu, 25 Jun 2020 12:00:13 +0000 (UTC) From: Thomas Zimmermann To: maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@linux.ie, daniel@ffwll.ch, kraxel@redhat.com, lgirdwood@gmail.com, broonie@kernel.org, robh@kernel.org, sam@ravnborg.org, emil.l.velikov@gmail.com, noralf@tronnes.org, geert+renesas@glider.be, hdegoede@redhat.com Subject: [PATCH 4/9] drm/simplekms: Add fbdev emulation Date: Thu, 25 Jun 2020 14:00:06 +0200 Message-Id: <20200625120011.16168-5-tzimmermann@suse.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200625120011.16168-1-tzimmermann@suse.de> References: <20200625120011.16168-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" This displays a console on the simplefb framebuffer. The default framebuffer format is being used. Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter --- drivers/gpu/drm/tiny/simplekms.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/tiny/simplekms.c b/drivers/gpu/drm/tiny/simplekms.c index dc7cf3983945..ac2ebfcedd22 100644 --- a/drivers/gpu/drm/tiny/simplekms.c +++ b/drivers/gpu/drm/tiny/simplekms.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -469,6 +470,8 @@ static int simplekms_probe(struct platform_device *pdev) if (ret) return ret; + drm_fbdev_generic_setup(dev, 0); + return 0; } From patchwork Thu Jun 25 12:00:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11624969 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 69305913 for ; Thu, 25 Jun 2020 12:00:29 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 511AE204EC for ; Thu, 25 Jun 2020 12:00:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 511AE204EC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A47C46EBC2; Thu, 25 Jun 2020 12:00:18 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6C1136EBBA for ; Thu, 25 Jun 2020 12:00:16 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 39E3FAD79; Thu, 25 Jun 2020 12:00:14 +0000 (UTC) From: Thomas Zimmermann To: maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@linux.ie, daniel@ffwll.ch, kraxel@redhat.com, lgirdwood@gmail.com, broonie@kernel.org, robh@kernel.org, sam@ravnborg.org, emil.l.velikov@gmail.com, noralf@tronnes.org, geert+renesas@glider.be, hdegoede@redhat.com Subject: [PATCH 5/9] drm/simplekms: Initialize framebuffer data from device-tree node Date: Thu, 25 Jun 2020 14:00:07 +0200 Message-Id: <20200625120011.16168-6-tzimmermann@suse.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200625120011.16168-1-tzimmermann@suse.de> References: <20200625120011.16168-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" A firmware framebuffer might also be specified via device-tree files. If no device platform data is given, try the DT device node. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/tiny/simplekms.c | 84 ++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/gpu/drm/tiny/simplekms.c b/drivers/gpu/drm/tiny/simplekms.c index ac2ebfcedd22..87636307aa4f 100644 --- a/drivers/gpu/drm/tiny/simplekms.c +++ b/drivers/gpu/drm/tiny/simplekms.c @@ -113,6 +113,76 @@ simplefb_get_format_pd(struct drm_device *dev, return simplefb_get_validated_format(dev, pd->format); } +static int +simplefb_read_u32_of(struct drm_device *dev, struct device_node *of_node, + const char* name, u32 *value) +{ + int ret = of_property_read_u32(of_node, name, value); + if (ret) + drm_err(dev, "simplefb: can't parse framebuffer %s: error %d\n", + name, ret); + return ret; +} + +static int +simplefb_read_string_of(struct drm_device *dev, struct device_node *of_node, + const char* name, const char **value) +{ + int ret = of_property_read_string(of_node, name, value); + if (ret) + drm_err(dev, "simplefb: can't parse framebuffer %s: error %d\n", + name, ret); + return ret; +} + +static int +simplefb_get_width_of(struct drm_device *dev, struct device_node *of_node) +{ + int ret; + u32 width; + + ret = simplefb_read_u32_of(dev, of_node, "width", &width); + if (ret) + return ret; + return simplefb_get_validated_int0(dev, "width", width); +} + +static int +simplefb_get_height_of(struct drm_device *dev, struct device_node *of_node) +{ + int ret; + u32 height; + + ret = simplefb_read_u32_of(dev, of_node, "height", &height); + if (ret) + return ret; + return simplefb_get_validated_int0(dev, "height", height); +} + +static int +simplefb_get_stride_of(struct drm_device *dev, struct device_node *of_node) +{ + int ret; + u32 stride; + + ret = simplefb_read_u32_of(dev, of_node, "stride", &stride); + if (ret) + return ret; + return simplefb_get_validated_int(dev, "stride", stride); +} + +static const struct drm_format_info * +simplefb_get_format_of(struct drm_device *dev, struct device_node *of_node) +{ + int ret; + const char *format; + + ret = simplefb_read_string_of(dev, of_node, "format", &format); + if (ret) + return ERR_PTR(ret); + return simplefb_get_validated_format(dev, format); +} + /* * Simple Framebuffer device */ @@ -163,6 +233,7 @@ static int simplekms_device_init_fb(struct simplekms_device *sdev) struct drm_device *dev = &sdev->dev; struct platform_device *pdev = sdev->pdev; const struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev); + struct device_node *of_node = pdev->dev.of_node; if (pd) { width = simplefb_get_width_pd(dev, pd); @@ -177,6 +248,19 @@ static int simplekms_device_init_fb(struct simplekms_device *sdev) format = simplefb_get_format_pd(dev, pd); if (IS_ERR(format)) return PTR_ERR(format); + } else if (of_node) { + width = simplefb_get_width_of(dev, of_node); + if (width < 0) + return width; + height = simplefb_get_height_of(dev, of_node); + if (height < 0) + return height; + stride = simplefb_get_stride_of(dev, of_node); + if (stride < 0) + return stride; + format = simplefb_get_format_of(dev, of_node); + if (IS_ERR(format)) + return PTR_ERR(format); } else { drm_err(dev, "no simplefb configuration found\n"); return -ENODEV; From patchwork Thu Jun 25 12:00:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11624967 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D27BA913 for ; Thu, 25 Jun 2020 12:00:27 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B9EF1204EC for ; Thu, 25 Jun 2020 12:00:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B9EF1204EC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 18E806EBBB; Thu, 25 Jun 2020 12:00:18 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6E7896EBBB for ; Thu, 25 Jun 2020 12:00:16 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 5C0F7AEAC; Thu, 25 Jun 2020 12:00:14 +0000 (UTC) From: Thomas Zimmermann To: maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@linux.ie, daniel@ffwll.ch, kraxel@redhat.com, lgirdwood@gmail.com, broonie@kernel.org, robh@kernel.org, sam@ravnborg.org, emil.l.velikov@gmail.com, noralf@tronnes.org, geert+renesas@glider.be, hdegoede@redhat.com Subject: [PATCH 6/9] drm/simplekms: Acquire clocks from DT device node Date: Thu, 25 Jun 2020 14:00:08 +0200 Message-Id: <20200625120011.16168-7-tzimmermann@suse.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200625120011.16168-1-tzimmermann@suse.de> References: <20200625120011.16168-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Make sure required hardware clocks are enabled while the firmware framebuffer is in use. The basic code has been taken from the simplefb driver and adapted to DRM. Clocks are released automatically via devres helpers. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/tiny/simplekms.c | 108 +++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/drivers/gpu/drm/tiny/simplekms.c b/drivers/gpu/drm/tiny/simplekms.c index 87636307aa4f..aca186decb48 100644 --- a/drivers/gpu/drm/tiny/simplekms.c +++ b/drivers/gpu/drm/tiny/simplekms.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only +#include +#include #include #include @@ -191,6 +193,12 @@ struct simplekms_device { struct drm_device dev; struct platform_device *pdev; + /* clocks */ +#if defined CONFIG_OF && defined CONFIG_COMMON_CLK + unsigned int clk_count; + struct clk **clks; +#endif + /* simplefb settings */ struct drm_display_mode mode; const struct drm_format_info *format; @@ -210,6 +218,103 @@ static struct simplekms_device *simplekms_device_of_dev(struct drm_device *dev) return container_of(dev, struct simplekms_device, dev); } +/* + * Hardware + */ + +#if defined CONFIG_OF && defined CONFIG_COMMON_CLK +/* + * Clock handling code. + * + * Here we handle the clocks property of our "simple-framebuffer" dt node. + * This is necessary so that we can make sure that any clocks needed by + * the display engine that the bootloader set up for us (and for which it + * provided a simplefb dt node), stay up, for the life of the simplefb + * driver. + * + * When the driver unloads, we cleanly disable, and then release the clocks. + * + * We only complain about errors here, no action is taken as the most likely + * error can only happen due to a mismatch between the bootloader which set + * up simplefb, and the clock definitions in the device tree. Chances are + * that there are no adverse effects, and if there are, a clean teardown of + * the fb probe will not help us much either. So just complain and carry on, + * and hope that the user actually gets a working fb at the end of things. + */ + +static void simplekms_device_release_clocks(void *res) +{ + struct simplekms_device *sdev = simplekms_device_of_dev(res); + unsigned int i; + + for (i = 0; i < sdev->clk_count; ++i) { + if (sdev->clks[i]) { + clk_disable_unprepare(sdev->clks[i]); + clk_put(sdev->clks[i]); + } + } +} + +static int simplekms_device_init_clocks(struct simplekms_device *sdev) +{ + struct drm_device *dev = &sdev->dev; + struct platform_device *pdev = sdev->pdev; + struct device_node *of_node = pdev->dev.of_node; + struct clk *clock; + unsigned int i; + int ret; + + if (dev_get_platdata(&pdev->dev) || !of_node) + return 0; + + sdev->clk_count = of_clk_get_parent_count(of_node); + if (!sdev->clk_count) + return 0; + + sdev->clks = drmm_kzalloc(dev, sdev->clk_count * sizeof(sdev->clks[0]), + GFP_KERNEL); + if (!sdev->clks) + return -ENOMEM; + + for (i = 0; i < sdev->clk_count; ++i) { + clock = of_clk_get(of_node, i); + if (IS_ERR(clock)) { + ret = PTR_ERR(clock); + if (ret == -EPROBE_DEFER) + goto err; + drm_err(dev, "clock %u not found: %d\n", i, ret); + continue; + } + ret = clk_prepare_enable(clock); + if (ret) { + drm_err(dev, "failed to enable clock %u: %d\n", + i, ret); + clk_put(clock); + } + sdev->clks[i] = clock; + } + + return devm_add_action_or_reset(&pdev->dev, + simplekms_device_release_clocks, + sdev); + +err: + while (i) { + --i; + if (sdev->clks[i]) { + clk_disable_unprepare(sdev->clks[i]); + clk_put(sdev->clks[i]); + } + } + return ret; +} +#else +static int simplekms_device_init_clocks(struct simplekms_device *sdev) +{ + return 0; +} +#endif + /* * Simplefb settings */ @@ -505,6 +610,9 @@ simplekms_device_create(struct drm_driver *drv, struct platform_device *pdev) return ERR_CAST(sdev); sdev->pdev = pdev; + ret = simplekms_device_init_clocks(sdev); + if (ret) + return ERR_PTR(ret); ret = simplekms_device_init_fb(sdev); if (ret) return ERR_PTR(ret); From patchwork Thu Jun 25 12:00:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11624971 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2281614E3 for ; Thu, 25 Jun 2020 12:00:31 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0A721204EC for ; Thu, 25 Jun 2020 12:00:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0A721204EC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id BED7B6EBC3; Thu, 25 Jun 2020 12:00:19 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9556D6EBBE for ; Thu, 25 Jun 2020 12:00:16 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 94F6AAFEF; Thu, 25 Jun 2020 12:00:14 +0000 (UTC) From: Thomas Zimmermann To: maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@linux.ie, daniel@ffwll.ch, kraxel@redhat.com, lgirdwood@gmail.com, broonie@kernel.org, robh@kernel.org, sam@ravnborg.org, emil.l.velikov@gmail.com, noralf@tronnes.org, geert+renesas@glider.be, hdegoede@redhat.com Subject: [PATCH 7/9] drm/simplekms: Acquire regulators from DT device node Date: Thu, 25 Jun 2020 14:00:09 +0200 Message-Id: <20200625120011.16168-8-tzimmermann@suse.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200625120011.16168-1-tzimmermann@suse.de> References: <20200625120011.16168-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Make sure required hardware regulators are enabled while the firmware framebuffer is in use. The basic code has been taken from the simplefb driver and adapted to DRM. Regulators are released automatically via devres helpers. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/tiny/simplekms.c | 128 +++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/drivers/gpu/drm/tiny/simplekms.c b/drivers/gpu/drm/tiny/simplekms.c index aca186decb48..ae5d3cbadbe8 100644 --- a/drivers/gpu/drm/tiny/simplekms.c +++ b/drivers/gpu/drm/tiny/simplekms.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -198,6 +199,11 @@ struct simplekms_device { unsigned int clk_count; struct clk **clks; #endif + /* regulators */ +#if defined CONFIG_OF && defined CONFIG_REGULATOR + unsigned int regulator_count; + struct regulator **regulators; +#endif /* simplefb settings */ struct drm_display_mode mode; @@ -315,6 +321,125 @@ static int simplekms_device_init_clocks(struct simplekms_device *sdev) } #endif +#if defined CONFIG_OF && defined CONFIG_REGULATOR + +#define SUPPLY_SUFFIX "-supply" + +/* + * Regulator handling code. + * + * Here we handle the num-supplies and vin*-supply properties of our + * "simple-framebuffer" dt node. This is necessary so that we can make sure + * that any regulators needed by the display hardware that the bootloader + * set up for us (and for which it provided a simplefb dt node), stay up, + * for the life of the simplefb driver. + * + * When the driver unloads, we cleanly disable, and then release the + * regulators. + * + * We only complain about errors here, no action is taken as the most likely + * error can only happen due to a mismatch between the bootloader which set + * up simplefb, and the regulator definitions in the device tree. Chances are + * that there are no adverse effects, and if there are, a clean teardown of + * the fb probe will not help us much either. So just complain and carry on, + * and hope that the user actually gets a working fb at the end of things. + */ + +static void simplekms_device_release_regulators(void *res) +{ + struct simplekms_device *sdev = simplekms_device_of_dev(res); + unsigned int i; + + for (i = 0; i < sdev->regulator_count; ++i) { + if (sdev->regulators[i]) { + regulator_disable(sdev->regulators[i]); + regulator_put(sdev->regulators[i]); + } + } +} + +static int simplekms_device_init_regulators(struct simplekms_device *sdev) +{ + struct drm_device *dev = &sdev->dev; + struct platform_device *pdev = sdev->pdev; + struct device_node *of_node = pdev->dev.of_node; + struct property *prop; + struct regulator *regulator; + const char *p; + unsigned int count = 0, i = 0; + int ret; + + if (dev_get_platdata(&pdev->dev) || !of_node) + return 0; + + /* Count the number of regulator supplies */ + for_each_property_of_node(of_node, prop) { + p = strstr(prop->name, SUPPLY_SUFFIX); + if (p && p != prop->name) + ++count; + } + + if (!count) + return 0; + + sdev->regulators = drmm_kzalloc(dev, + count * sizeof(sdev->regulators[0]), + GFP_KERNEL); + if (!sdev->regulators) + return -ENOMEM; + + for_each_property_of_node(of_node, prop) { + char name[32]; /* 32 is max size of property name */ + size_t len; + + p = strstr(prop->name, SUPPLY_SUFFIX); + if (!p || p == prop->name) + continue; + len = strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1; + strlcpy(name, prop->name, len); + + regulator = regulator_get_optional(&pdev->dev, name); + if (IS_ERR(regulator)) { + ret = PTR_ERR(regulator); + if (ret == -EPROBE_DEFER) + goto err; + drm_err(dev, "regulator %s not found: %d\n", + name, ret); + continue; + } + + ret = regulator_enable(regulator); + if (ret) { + drm_err(dev, "failed to enable regulator %u: %d\n", + i, ret); + regulator_put(regulator); + } + + sdev->regulators[i++] = regulator; + } + sdev->regulator_count = i; + + return devm_add_action_or_reset(&pdev->dev, + simplekms_device_release_regulators, + sdev); + +err: + while (i) { + --i; + if (sdev->regulators[i]) { + regulator_disable(sdev->regulators[i]); + regulator_put(sdev->regulators[i]); + } + } + return ret; +} +#else +static int simplekms_device_init_regulators(struct simplekms_device *sdev) +{ + return 0; +} +#endif + /* * Simplefb settings */ @@ -611,6 +736,9 @@ simplekms_device_create(struct drm_driver *drv, struct platform_device *pdev) sdev->pdev = pdev; ret = simplekms_device_init_clocks(sdev); + if (ret) + return ERR_PTR(ret); + ret = simplekms_device_init_regulators(sdev); if (ret) return ERR_PTR(ret); ret = simplekms_device_init_fb(sdev); From patchwork Thu Jun 25 12:00:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11624975 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C4E02913 for ; Thu, 25 Jun 2020 12:00:36 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AD6FA207D8 for ; Thu, 25 Jun 2020 12:00:36 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org AD6FA207D8 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 113FC6EA8B; Thu, 25 Jun 2020 12:00:34 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id D5A256EBC3 for ; Thu, 25 Jun 2020 12:00:16 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 3D5CDB01D; Thu, 25 Jun 2020 12:00:15 +0000 (UTC) From: Thomas Zimmermann To: maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@linux.ie, daniel@ffwll.ch, kraxel@redhat.com, lgirdwood@gmail.com, broonie@kernel.org, robh@kernel.org, sam@ravnborg.org, emil.l.velikov@gmail.com, noralf@tronnes.org, geert+renesas@glider.be, hdegoede@redhat.com Subject: [PATCH 8/9] drm: Add infrastructure for platform devices Date: Thu, 25 Jun 2020 14:00:10 +0200 Message-Id: <20200625120011.16168-9-tzimmermann@suse.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200625120011.16168-1-tzimmermann@suse.de> References: <20200625120011.16168-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Platform devices might operate on firmware framebuffers, such as VESA or EFI. Before a native driver for the graphics hardware can take over the device, it has to remove any platform driver that operates on the firmware framebuffer. Platform helpers provide the infrastructure for platform drivers to acquire firmware framebuffers, and for native drivers to remove them lateron. It works similar to the related fbdev mechanism. During initialization, the platform driver acquires the firmware framebuffer's I/O memory and provides a callback to be removed. The native driver later uses this inforamtion to remove any platform driver for it's framebuffer I/O memory. The platform helper's removal code is integrated into the existing code for removing conflicting fraembuffers, so native drivers use it automatically. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/Kconfig | 6 ++ drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_platform.c | 118 +++++++++++++++++++++++++++++++++ include/drm/drm_fb_helper.h | 18 ++++- include/drm/drm_platform.h | 42 ++++++++++++ 5 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/drm_platform.c create mode 100644 include/drm/drm_platform.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index c4fd57d8b717..e9d6892f9d38 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -229,6 +229,12 @@ config DRM_SCHED tristate depends on DRM +config DRM_PLATFORM_HELPER + bool + depends on DRM + help + Helpers for DRM platform devices + source "drivers/gpu/drm/i2c/Kconfig" source "drivers/gpu/drm/arm/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 2c0e5a7e5953..8ceb21d0770a 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -32,6 +32,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_PCI) += drm_pci.o drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o +drm-$(CONFIG_DRM_PLATFORM_HELPER) += drm_platform.o drm_vram_helper-y := drm_gem_vram_helper.o obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c new file mode 100644 index 000000000000..09a2f2a31aa5 --- /dev/null +++ b/drivers/gpu/drm/drm_platform.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +#include +#include + +#include +#include +#include + +static LIST_HEAD(drm_apertures); + +static DEFINE_MUTEX(drm_apertures_lock); + +static bool overlap(resource_size_t base1, resource_size_t end1, + resource_size_t base2, resource_size_t end2) +{ + return (base1 < end2) && (end1 > base2); +} + +static struct drm_aperture * +drm_aperture_acquire(struct drm_device *dev, + resource_size_t base, resource_size_t size, + const struct drm_aperture_funcs *funcs) +{ + size_t end = base + size; + struct list_head *pos; + struct drm_aperture *ap; + + mutex_lock(&drm_apertures_lock); + + list_for_each(pos, &drm_apertures) { + ap = container_of(pos, struct drm_aperture, lh); + if (overlap(base, end, ap->base, ap->base + ap->size)) + return ERR_PTR(-EBUSY); + } + + ap = drmm_kzalloc(dev, sizeof(*ap), GFP_KERNEL); + if (!ap) + return ERR_PTR(-ENOMEM); + + ap->dev = dev; + ap->base = base; + ap->size = size; + ap->funcs = funcs; + INIT_LIST_HEAD(&ap->lh); + + list_add(&ap->lh, &drm_apertures); + + mutex_unlock(&drm_apertures_lock); + + return ap; +} + +static void drm_aperture_release(struct drm_aperture *ap) +{ + bool kicked_out = ap->kicked_out; + + if (!kicked_out) + mutex_lock(&drm_apertures_lock); + + list_del(&ap->lh); + if (ap->funcs->release) + ap->funcs->release(ap); + + if (!kicked_out) + mutex_unlock(&drm_apertures_lock); +} + +static void drm_aperture_acquire_release(struct drm_device *dev, void *ptr) +{ + struct drm_aperture *ap = ptr; + + drm_aperture_release(ap); +} + +struct drm_aperture * +drmm_aperture_acquire(struct drm_device *dev, + resource_size_t base, resource_size_t size, + const struct drm_aperture_funcs *funcs) +{ + struct drm_aperture *ap; + int ret; + + ap = drm_aperture_acquire(dev, base, size, funcs); + if (IS_ERR(ap)) + return ap; + ret = drmm_add_action_or_reset(dev, drm_aperture_acquire_release, ap); + if (ret) + return ERR_PTR(ret); + + return ap; +} +EXPORT_SYMBOL(drmm_aperture_acquire); + +void drm_kickout_apertures_at(resource_size_t base, resource_size_t size) +{ + resource_size_t end = base + size; + struct list_head *pos, *n; + + mutex_lock(&drm_apertures_lock); + + list_for_each_safe(pos, n, &drm_apertures) { + struct drm_aperture *ap = + container_of(pos, struct drm_aperture, lh); + + if (!overlap(base, end, ap->base, ap->base + ap->size)) + continue; + + ap->kicked_out = true; + if (ap->funcs->kickout) + ap->funcs->kickout(ap); + else + drm_dev_put(ap->dev); + } + + mutex_unlock(&drm_apertures_lock); +} +EXPORT_SYMBOL(drm_kickout_apertures_at); diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 306aa3a60be9..a919b78b1961 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -35,7 +35,9 @@ struct drm_fb_helper; #include #include #include +#include #include +#include #include enum mode_set_atomic { @@ -465,6 +467,11 @@ static inline int drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a, const char *name, bool primary) { + int i; + + for (i = 0; i < a->count; ++i) + drm_kickout_apertures_at(a->ranges[i].base, a->ranges[i].size); + #if IS_REACHABLE(CONFIG_FB) return remove_conflicting_framebuffers(a, name, primary); #else @@ -487,7 +494,16 @@ static inline int drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name) { - int ret = 0; + resource_size_t base, size; + int bar, ret = 0; + + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { + if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) + continue; + base = pci_resource_start(pdev, bar); + size = pci_resource_len(pdev, bar); + drm_kickout_apertures_at(base, size); + } /* * WARNING: Apparently we must kick fbdev drivers before vgacon, diff --git a/include/drm/drm_platform.h b/include/drm/drm_platform.h new file mode 100644 index 000000000000..475e88ee1fbd --- /dev/null +++ b/include/drm/drm_platform.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +#ifndef _DRM_PLATFORM_H_ +#define _DRM_PLATFORM_H_ + +#include +#include + +struct drm_aperture; +struct drm_device; + +struct drm_aperture_funcs { + void (*kickout)(struct drm_aperture *ap); + void (*release)(struct drm_aperture *ap); +}; + +struct drm_aperture { + struct drm_device *dev; + resource_size_t base; + resource_size_t size; + + const struct drm_aperture_funcs *funcs; + + struct list_head lh; + bool kicked_out; +}; + +struct drm_aperture * +drmm_aperture_acquire(struct drm_device *dev, + resource_size_t base, resource_size_t size, + const struct drm_aperture_funcs *funcs); + +#if defined (CONFIG_DRM_PLATFORM_HELPER) +void drm_kickout_apertures_at(resource_size_t base, resource_size_t size); +#else +static inline void +drm_kickout_apertures_at(resource_size_t base, resource_size_t size) +{ +} +#endif + +#endif From patchwork Thu Jun 25 12:00:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Zimmermann X-Patchwork-Id: 11624973 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5D1D114E3 for ; Thu, 25 Jun 2020 12:00:35 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 44C58204EC for ; Thu, 25 Jun 2020 12:00:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 44C58204EC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1726E6EBBA; Thu, 25 Jun 2020 12:00:34 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2A0236EBBA for ; Thu, 25 Jun 2020 12:00:17 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 741B2B053; Thu, 25 Jun 2020 12:00:15 +0000 (UTC) From: Thomas Zimmermann To: maarten.lankhorst@linux.intel.com, mripard@kernel.org, airlied@linux.ie, daniel@ffwll.ch, kraxel@redhat.com, lgirdwood@gmail.com, broonie@kernel.org, robh@kernel.org, sam@ravnborg.org, emil.l.velikov@gmail.com, noralf@tronnes.org, geert+renesas@glider.be, hdegoede@redhat.com Subject: [PATCH 9/9] drm/simplekms: Acquire memory aperture for framebuffer Date: Thu, 25 Jun 2020 14:00:11 +0200 Message-Id: <20200625120011.16168-10-tzimmermann@suse.de> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200625120011.16168-1-tzimmermann@suse.de> References: <20200625120011.16168-1-tzimmermann@suse.de> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" We register the simplekms device with the DRM platform helpers. A native driver for the graphics hardware will kickout the simplekms driver before taking over the device. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/tiny/Kconfig | 1 + drivers/gpu/drm/tiny/simplekms.c | 94 +++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 50dbde8bdcb2..a47ed337a7fe 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -33,6 +33,7 @@ config DRM_SIMPLEKMS depends on DRM select DRM_GEM_SHMEM_HELPER select DRM_KMS_HELPER + select DRM_PLATFORM_HELPER help DRM driver for simple platform-provided framebuffers. diff --git a/drivers/gpu/drm/tiny/simplekms.c b/drivers/gpu/drm/tiny/simplekms.c index ae5d3cbadbe8..a903a4e0100a 100644 --- a/drivers/gpu/drm/tiny/simplekms.c +++ b/drivers/gpu/drm/tiny/simplekms.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include @@ -36,6 +38,12 @@ #define SIMPLEKMS_MODE(hd, vd) \ DRM_SIMPLE_MODE(hd, vd, RES_MM(hd), RES_MM(vd)) +/* + * Protects the platform device's drvdata against + * concurrent manipulation. + */ +static DEFINE_SPINLOCK(simplekms_drvdata_lock); + /* * Helpers for simplefb */ @@ -211,6 +219,7 @@ struct simplekms_device { unsigned int pitch; /* memory management */ + struct drm_aperture *aperture; struct resource *mem; void __iomem *screen_base; @@ -224,6 +233,8 @@ static struct simplekms_device *simplekms_device_of_dev(struct drm_device *dev) return container_of(dev, struct simplekms_device, dev); } +static void simplekms_device_cleanup(struct simplekms_device *sdev); + /* * Hardware */ @@ -514,22 +525,72 @@ static int simplekms_device_init_fb(struct simplekms_device *sdev) * Memory management */ +static void simplekms_aperture_kickout(struct drm_aperture *ap) +{ + struct drm_device *dev = ap->dev; + struct simplekms_device *sdev = simplekms_device_of_dev(dev); + struct platform_device *pdev = sdev->pdev; + + if (WARN_ON(!sdev->aperture)) + return; /* BUG: driver already got kicked out */ + + drm_dev_unregister(dev); + + sdev->aperture = NULL; /* memory is released by platform helpers */ + + spin_lock(&simplekms_drvdata_lock); + sdev = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); /* required; see simplekms_remove() */ + spin_unlock(&simplekms_drvdata_lock); + + /* + * Return if a concurrent simplekms_remove() cleans up the + * device. See simplekms_remove(). + */ + if (!sdev) + return; + + /* + * After the aperture has been released, there's no reason + * to keep the DRM device around. + */ + simplekms_device_cleanup(sdev); +} + +static const struct drm_aperture_funcs simplekms_aperture_funcs = { + .kickout = simplekms_aperture_kickout, +}; + static int simplekms_device_init_mm(struct simplekms_device *sdev) { + struct drm_device *dev = &sdev->dev; struct platform_device *pdev = sdev->pdev; struct resource *mem; + struct drm_aperture *ap; void __iomem *screen_base; + int ret; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) return -EINVAL; + ap = drmm_aperture_acquire(dev, mem->start, resource_size(mem), + &simplekms_aperture_funcs); + if (IS_ERR(ap)) { + ret = PTR_ERR(ap); + drm_err(dev, + "could not acquire memory range [0x%llx:0x%llx]: " + "error %d\n", mem->start, mem->end, ret); + return ret; + } + screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem)); if (!screen_base) return -ENOMEM; sdev->mem = mem; + sdev->aperture = ap; sdev->screen_base = screen_base; return 0; @@ -625,6 +686,9 @@ simplekms_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_framebuffer *fb = state->fb; void *vmap; + if (!sdev->aperture) + return; + vmap = drm_gem_shmem_vmap(fb->obj[0]); if (!vmap) return; @@ -645,6 +709,9 @@ simplekms_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_rect clip; void *vmap; + if (!sdev->aperture) + return; + if (!drm_atomic_helper_damage_merged(old_plane_state, state, &clip)) return; @@ -716,11 +783,12 @@ static int simplekms_device_init_modeset(struct simplekms_device *sdev) * Init / Cleanup */ -static void simplekms_device_cleanup(struct simplekms_device* sdev) +static void simplekms_device_cleanup(struct simplekms_device *sdev) { struct drm_device *dev = &sdev->dev; - drm_dev_unregister(dev); + if (dev->registered) + drm_dev_unregister(dev); } static struct simplekms_device * @@ -797,7 +865,27 @@ static int simplekms_probe(struct platform_device *pdev) static int simplekms_remove(struct platform_device *pdev) { - struct simplekms_device *sdev = platform_get_drvdata(pdev); + struct simplekms_device *sdev; + + spin_lock(&simplekms_drvdata_lock); + sdev = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); + spin_unlock(&simplekms_drvdata_lock); + + /* + * The platform driver shares its reference to dev with the + * platform helpers for apertures. That reference is either + * released here when unloading the driver; or it's released + * when the driver gets kicked out by another driver. In the + * latter case, the aperture release routine clears the data + * field of the platform device. + * + * Therefore, sdev being NULL is a valid state if the driver + * has been kicked out by another DRM driver. In this case, + * it's all been cleaned up and we can return immediately. + */ + if (!sdev) + return 0; simplekms_device_cleanup(sdev);