linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
@ 2021-04-16  9:00 Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 1/9] drm/format-helper: Pass destination pitch to drm_fb_memcpy_dstclip() Thomas Zimmermann
                   ` (10 more replies)
  0 siblings, 11 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann

This patchset adds support for simple-framebuffer platform devices and
a handover mechanism for native drivers to take-over control of the
hardware.

The new driver, called simpledrm, binds to a simple-frambuffer platform
device. The kernel's boot code creates such devices for firmware-provided
framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot
loader sets up the framebuffers. Description via device tree is also an
option.

Simpledrm is small enough to be linked into the kernel. The driver's main
purpose is to provide graphical output during the early phases of the boot
process, before the native DRM drivers are available. Native drivers are
typically loaded from an initrd ram disk. Occationally simpledrm can also
serve as interim solution on graphics hardware without native DRM driver.

So far distributions rely on fbdev drivers, such as efifb, vesafb or
simplefb, for early-boot graphical output. However fbdev is deprecated and
the drivers do not provide DRM interfaces for modern userspace.

Patches 1 and 2 prepare the DRM format helpers for simpledrm.

Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
pageflips, SHMEM buffers are copied into the framebuffer memory, similar
to cirrus or mgag200. The code in patches 7 and 8 handles clocks and
regulators. It's based on the simplefb drivers, but has been modified for
DRM.

Patches 3 and 9 add a hand-over mechanism. Simpledrm acquires it's
framebuffer's I/O-memory range and can be hot-unplugged by a native driver.
The native driver will remove simpledrm before taking over the hardware.
The removal is integrated into existing helpers, so existing drivers use
it automatically.

I've also been working on fastboot support (i.e., flicker-free booting).
This requires state-readout from simpledrm via generic interfaces, as
outlined in [1]. I do have some prototype code, but it will take a while
to get this ready. Simpledrm will then support it.

I've tested simpledrm with x86 EFI and VESA framebuffers, which both work
reliably. The fbdev console and Weston work automatically. Xorg requires
manual configuration of the device. Xorgs current modesetting driver does
not work with both, platform and PCI device, for the same physical
hardware. Once configured, X11 works. I looked into X11, but couldn't see
an easy way of fixing the problem. With the push towards Wayland+Xwayland
I expect the problem to become a non-issue soon. Additional testing has
been reported at [2].

One cosmetical issue is that simpledrm's device file is card0 and the
native driver's device file is card1. After simpledrm has been kicked out,
only card1 is left. This does not seem to be a practical problem however.

TODO/IDEAS:
       	* provide deferred takeover
	* provide bootsplash DRM client
	* make simplekms usable with ARM-EFI fbs

v4:
	* provide interface for acquiring firmware framebuffers (Daniel)
	* make simpledrm and simplefb mutually exclusive (Maxime)
	* documentation fixes
v3:
	* clear screen to black when disabled (Daniel)
	* rebase onto existing aperture helpers
	* detach via hot-unplug via platform_device_unregister()
v2:
	* rename to simpledrm, aperture helpers
	* reorganized patches
	* use hotplug helpers for removal (Daniel)
	* added DT match tables (Rob)
	* use shadow-plane helpers
	* lots of minor cleanups

[1] https://lore.kernel.org/dri-devel/CAKMK7uHtqHy_oz4W7F+hmp9iqp7W5Ra8CxPvJ=9BwmvfU-O0gg@mail.gmail.com/
[2] https://lore.kernel.org/dri-devel/1761762.3HQLrFs1K7@nerdopolis/

Thomas Zimmermann (9):
  drm/format-helper: Pass destination pitch to drm_fb_memcpy_dstclip()
  drm/format-helper: Add blitter functions
  drm/aperture: Add infrastructure for aperture ownership
  drm: Add simpledrm driver
  drm/simpledrm: Add fbdev emulation
  drm/simpledrm: Initialize framebuffer data from device-tree node
  drm/simpledrm: Acquire clocks from DT device node
  drm/simpledrm: Acquire regulators from DT device node
  drm/simpledrm: Acquire memory aperture for framebuffer

 Documentation/gpu/drm-internals.rst    |  21 +-
 MAINTAINERS                            |   7 +
 drivers/gpu/drm/drm_aperture.c         | 221 +++++-
 drivers/gpu/drm/drm_format_helper.c    |  96 ++-
 drivers/gpu/drm/mgag200/mgag200_mode.c |   2 +-
 drivers/gpu/drm/tiny/Kconfig           |  16 +
 drivers/gpu/drm/tiny/Makefile          |   1 +
 drivers/gpu/drm/tiny/cirrus.c          |   2 +-
 drivers/gpu/drm/tiny/simpledrm.c       | 896 +++++++++++++++++++++++++
 drivers/video/fbdev/Kconfig            |   2 +-
 include/drm/drm_aperture.h             |  20 +-
 include/drm/drm_format_helper.h        |  10 +-
 12 files changed, 1254 insertions(+), 40 deletions(-)
 create mode 100644 drivers/gpu/drm/tiny/simpledrm.c

--
2.31.1


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v4 1/9] drm/format-helper: Pass destination pitch to drm_fb_memcpy_dstclip()
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
@ 2021-04-16  9:00 ` Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 2/9] drm/format-helper: Add blitter functions Thomas Zimmermann
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann, Daniel Vetter

The memcpy's destination buffer might have a different pitch than the
source. Support different pitches as function argument.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Tested-by: nerdopolis <bluescreen_avenger@verizon.net>
---
 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 cece3e57fb27..9d576240faed 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1554,7 +1554,7 @@ mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb,
 {
 	void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
 
-	drm_fb_memcpy_dstclip(mdev->vram, vmap, fb, clip);
+	drm_fb_memcpy_dstclip(mdev->vram, fb->pitches[0], vmap, fb, clip);
 
 	/* Always scanout image at VRAM offset 0 */
 	mgag200_set_startadd(mdev, (u32)0);
diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c
index e3afb45d9a5c..42611dacde88 100644
--- a/drivers/gpu/drm/tiny/cirrus.c
+++ b/drivers/gpu/drm/tiny/cirrus.c
@@ -324,7 +324,7 @@ static int cirrus_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_
 		return -ENODEV;
 
 	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,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v4 2/9] drm/format-helper: Add blitter functions
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 1/9] drm/format-helper: Pass destination pitch to drm_fb_memcpy_dstclip() Thomas Zimmermann
@ 2021-04-16  9:00 ` Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 3/9] drm/aperture: Add infrastructure for aperture ownership Thomas Zimmermann
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann, Daniel Vetter

The blitter functions copy a framebuffer to I/O memory using one of
the existing conversion functions.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Tested-by: nerdopolis <bluescreen_avenger@verizon.net>
---
 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 */
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v4 3/9] drm/aperture: Add infrastructure for aperture ownership
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 1/9] drm/format-helper: Pass destination pitch to drm_fb_memcpy_dstclip() Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 2/9] drm/format-helper: Add blitter functions Thomas Zimmermann
@ 2021-04-16  9:00 ` Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 4/9] drm: Add simpledrm driver Thomas Zimmermann
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann, Daniel Vetter

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. Aperture helpers provide the infrastructure for platform
drivers to acquire firmware framebuffers, and for native drivers to remove
them later on.

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 information to
remove any platform driver for it's framebuffer I/O memory.

The aperture removal code is integrated into the existing code for removing
conflicting framebuffers, so native drivers use it automatically.

v4:
	* hide detach callback in implementation (Daniel)
	* documentation fixes
v3:
	* rebase onto existing aperture infrastructure
	* release aperture from list during detach; fix dangling apertures
	* don't export struct drm_aperture
	* document struct drm_aperture_funcs
v2:
	* rename plaform helpers to aperture helpers
	* tie to device lifetime with devm_ functions
	* removed unsued remove() callback
	* rename kickout to detach
	* make struct drm_aperture private
	* rebase onto existing drm_aperture.h header file
	* use MIT license only for simplicity
	* documentation

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Tested-by: nerdopolis <bluescreen_avenger@verizon.net>
---
 Documentation/gpu/drm-internals.rst |  21 ++-
 drivers/gpu/drm/drm_aperture.c      | 221 +++++++++++++++++++++++++++-
 include/drm/drm_aperture.h          |  20 +--
 3 files changed, 230 insertions(+), 32 deletions(-)

diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst
index 06af044c882f..2f4056200611 100644
--- a/Documentation/gpu/drm-internals.rst
+++ b/Documentation/gpu/drm-internals.rst
@@ -75,18 +75,6 @@ update it, its value is mostly useless. The DRM core prints it to the
 kernel log at initialization time and passes it to userspace through the
 DRM_IOCTL_VERSION ioctl.
 
-Managing Ownership of the Framebuffer Aperture
-----------------------------------------------
-
-.. kernel-doc:: drivers/gpu/drm/drm_aperture.c
-   :doc: overview
-
-.. kernel-doc:: include/drm/drm_aperture.h
-   :internal:
-
-.. kernel-doc:: drivers/gpu/drm/drm_aperture.c
-   :export:
-
 Device Instance and Driver Handling
 -----------------------------------
 
@@ -102,6 +90,15 @@ Device Instance and Driver Handling
 .. kernel-doc:: drivers/gpu/drm/drm_drv.c
    :export:
 
+Managing Ownership of the Framebuffer Aperture
+----------------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_aperture.c
+   :doc: overview
+
+.. kernel-doc:: drivers/gpu/drm/drm_aperture.c
+   :export:
+
 Driver Load
 -----------
 
diff --git a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c
index e034dd7f9b09..0ad17d09610d 100644
--- a/drivers/gpu/drm/drm_aperture.c
+++ b/drivers/gpu/drm/drm_aperture.c
@@ -1,9 +1,18 @@
 // SPDX-License-Identifier: MIT
 
+#include <linux/device.h>
 #include <linux/fb.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h> /* for firmware helpers */
+#include <linux/slab.h>
+#include <linux/types.h>
 #include <linux/vgaarb.h>
 
 #include <drm/drm_aperture.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_print.h>
 
 /**
  * DOC: overview
@@ -62,8 +71,200 @@
  * framebuffer apertures automatically. Device drivers without knowledge of
  * the framebuffer's location shall call drm_aperture_remove_framebuffers(),
  * which removes all drivers for known framebuffer.
+ *
+ * Drivers that are susceptible to being removed by other drivers, such as
+ * generic EFI or VESA drivers, have to register themselves as owners of their
+ * given framebuffer memory. Ownership of the framebuffer memory is achived
+ * by calling devm_aperture_acquire_from_firmware(). On success, the driver
+ * is the owner of the framebuffer range. The function fails if the
+ * framebuffer is already by another driver. See below for an example.
+ *
+ * .. code-block:: c
+ *
+ *	static int acquire_framebuffers(struct drm_device *dev, struct platform_device *pdev)
+ *	{
+ *		resource_size_t base, size;
+ *
+ *		mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ *		if (!mem)
+ *			return -EINVAL;
+ *		base = mem->start;
+ *		size = resource_size(mem);
+ *
+ *		return devm_acquire_aperture_from_firmware(dev, base, size);
+ *	}
+ *
+ *	static int probe(struct platform_device *pdev)
+ *	{
+ *		struct drm_device *dev;
+ *		int ret;
+ *
+ *		// ... Initialize the device...
+ *		dev = devm_drm_dev_alloc();
+ *		...
+ *
+ *		// ... and acquire ownership of the framebuffer.
+ *		ret = acquire_framebuffers(dev, pdev);
+ *		if (ret)
+ *			return ret;
+ *
+ *		drm_dev_register(dev, 0);
+ *
+ *		return 0;
+ *	}
+ *
+ * The generic driver is now subject to forced removal by other drivers. This
+ * only works for platform drivers that support hot unplug.
+ * When a driver calls drm_aperture_remove_conflicting_framebuffers() et al
+ * for the registered framebuffer range, the aperture helpers call
+ * platform_device_unregister() and the generic driver unloads itself. It
+ * may not access the device's registers, framebuffer memory, ROM, etc
+ * afterwards.
  */
 
+struct drm_aperture {
+	struct drm_device *dev;
+	resource_size_t base;
+	resource_size_t size;
+	struct list_head lh;
+	void (*detach)(struct drm_device *dev);
+};
+
+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 void devm_aperture_acquire_release(void *data)
+{
+	struct drm_aperture *ap = data;
+	bool detached = !ap->dev;
+
+	if (detached)
+		return;
+
+	mutex_lock(&drm_apertures_lock);
+	list_del(&ap->lh);
+	mutex_unlock(&drm_apertures_lock);
+}
+
+static int devm_aperture_acquire(struct drm_device *dev,
+				 resource_size_t base, resource_size_t size,
+				 void (*detach)(struct drm_device *))
+{
+	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 -EBUSY;
+	}
+
+	ap = devm_kzalloc(dev->dev, sizeof(*ap), GFP_KERNEL);
+	if (!ap)
+		return -ENOMEM;
+
+	ap->dev = dev;
+	ap->base = base;
+	ap->size = size;
+	ap->detach = detach;
+	INIT_LIST_HEAD(&ap->lh);
+
+	list_add(&ap->lh, &drm_apertures);
+
+	mutex_unlock(&drm_apertures_lock);
+
+	return devm_add_action_or_reset(dev->dev, devm_aperture_acquire_release, ap);
+}
+
+static void drm_aperture_detach_firmware(struct drm_device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev->dev);
+
+	/*
+	 * Remove the device from the device hierarchy. This is the right thing
+	 * to do for firmware-based DRM drivers, such as EFI, VESA or VGA. After
+	 * the new driver takes over the hardware, the firmware device's state
+	 * will be lost.
+	 *
+	 * For non-platform devices, a new callback would be required.
+	 *
+	 * If the aperture helpers ever need to handle native drivers, this call
+	 * would only have to unplug the DRM device, so that the hardware device
+	 * stays around after detachment.
+	 */
+	platform_device_unregister(pdev);
+}
+
+/**
+ * devm_aperture_acquire_from_firmware - Acquires ownership of a firmware framebuffer
+ *                                       on behalf of a DRM driver.
+ * @dev:	the DRM device to own the framebuffer memory
+ * @base:	the framebuffer's byte offset in physical memory
+ * @size:	the framebuffer size in bytes
+ *
+ * Installs the given device as the new owner of the framebuffer. The function
+ * expects the framebuffer to be provided by a platform device that has been
+ * set up by firmware. Firmware can be any generic interface, such as EFI,
+ * VESA, VGA, etc. If the native hardware driver takes over ownership of the
+ * frambuffer range, the firmware state gets lost. Aperture helpers will then
+ * unregister the platform device automatically. Acquired apertures are
+ * released automatically if the underlying device goes away.
+ *
+ * The function fails if the framebuffer range, or parts of it, is currently
+ * owned by another driver. To evict current owners, callers should use
+ * drm_aperture_remove_conflicting_framebuffers() et al. before calling this
+ * function. The function also fails if the given device is not a platform
+ * device.
+ *
+ * Returns:
+ * 0 on success, or a negative errno value otherwise.
+ */
+int devm_aperture_acquire_from_firmware(struct drm_device *dev, resource_size_t base,
+					resource_size_t size)
+{
+	if (drm_WARN_ON(dev, !dev_is_platform(dev->dev)))
+		return -EINVAL;
+
+	return devm_aperture_acquire(dev, base, size, drm_aperture_detach_firmware);
+}
+EXPORT_SYMBOL(devm_aperture_acquire_from_firmware);
+
+static void drm_aperture_detach_drivers(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);
+		struct drm_device *dev = ap->dev;
+
+		if (WARN_ON_ONCE(!dev))
+			continue;
+
+		if (!overlap(base, end, ap->base, ap->base + ap->size))
+			continue;
+
+		ap->dev = NULL; /* detach from device */
+		list_del(&ap->lh);
+
+		ap->detach(dev);
+	}
+
+	mutex_unlock(&drm_apertures_lock);
+}
+
 /**
  * drm_aperture_remove_conflicting_framebuffers - remove existing framebuffers in the given range
  * @base: the aperture's base address in physical memory
@@ -94,10 +295,13 @@ int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_
 	ret = remove_conflicting_framebuffers(a, name, primary);
 	kfree(a);
 
-	return ret;
-#else
-	return 0;
+	if (ret)
+		return ret;
 #endif
+
+	drm_aperture_detach_drivers(base, size);
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers);
 
@@ -115,7 +319,16 @@ EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers);
  */
 int drm_aperture_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_aperture_detach_drivers(base, size);
+	}
 
 	/*
 	 * WARNING: Apparently we must kick fbdev drivers before vgacon,
diff --git a/include/drm/drm_aperture.h b/include/drm/drm_aperture.h
index 23cc01647ed3..a6e8d287eaab 100644
--- a/include/drm/drm_aperture.h
+++ b/include/drm/drm_aperture.h
@@ -5,27 +5,15 @@
 
 #include <linux/types.h>
 
+struct drm_device;
 struct pci_dev;
 
+int devm_aperture_acquire_from_firmware(struct drm_device *dev, resource_size_t base,
+					resource_size_t size);
+
 int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size,
 						 bool primary, const char *name);
 
 int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name);
 
-/**
- * drm_aperture_remove_framebuffers - remove all existing framebuffers
- * @primary: also kick vga16fb if present
- * @name: requesting driver name
- *
- * This function removes all graphics device drivers. Use this function on systems
- * that can have their framebuffer located anywhere in memory.
- *
- * Returns:
- * 0 on success, or a negative errno code otherwise
- */
-static inline int drm_aperture_remove_framebuffers(bool primary, const char *name)
-{
-	return drm_aperture_remove_conflicting_framebuffers(0, (resource_size_t)-1, primary, name);
-}
-
 #endif
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v4 4/9] drm: Add simpledrm driver
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
                   ` (2 preceding siblings ...)
  2021-04-16  9:00 ` [PATCH v4 3/9] drm/aperture: Add infrastructure for aperture ownership Thomas Zimmermann
@ 2021-04-16  9:00 ` Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 5/9] drm/simpledrm: Add fbdev emulation Thomas Zimmermann
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann

The simpledrm driver is a DRM driver for simple-framebuffer 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 simple-framebuffer infrastructure, the kernel receives
a pre-configured framebuffer from the system (i.e., firmware, boot
loader). It creates a platform device to which simpledrm attaches.
The system's framebuffer consists of a memory range, size and format.
Based on these values, simpledrm creates a DRM devices. No actual
modesetting is possible.

v4:
	* disable simplefb if simpledrm has been selected (Maxime)
v3:
	* add disable function that clears screen to black (Daniel)
	* set shadow buffering only for fbdev emulation
	* set platform-driver data during device creation
v2:
	* rename driver to simpledrm
	* add dri-devel to MAINTAINERS entry
	* put native format first in primary-plane format list (Daniel)
	* inline simplekms_device_cleanup() (Daniel)
	* use helpers for shadow-buffered planes
	* fix whitespace errors

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Tested-by: nerdopolis <bluescreen_avenger@verizon.net>
---
 MAINTAINERS                      |   7 +
 drivers/gpu/drm/tiny/Kconfig     |  16 +
 drivers/gpu/drm/tiny/Makefile    |   1 +
 drivers/gpu/drm/tiny/simpledrm.c | 545 +++++++++++++++++++++++++++++++
 drivers/video/fbdev/Kconfig      |   2 +-
 5 files changed, 570 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/tiny/simpledrm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7c45120759e6..4935776250e4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5765,6 +5765,13 @@ S:	Orphan / Obsolete
 F:	drivers/gpu/drm/savage/
 F:	include/uapi/drm/savage_drm.h
 
+DRM DRIVER FOR SIMPLE FRAMEBUFFERS
+M:	Thomas Zimmermann <tzimmermann@suse.de>
+L:	dri-devel@lists.freedesktop.org
+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 9bbaa1a69050..d46f95d9196d 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -38,6 +38,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_SIMPLEDRM
+	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 bef6780bdd6f..9cc847e756da 100644
--- a/drivers/gpu/drm/tiny/Makefile
+++ b/drivers/gpu/drm/tiny/Makefile
@@ -3,6 +3,7 @@
 obj-$(CONFIG_DRM_ARCPGU)		+= arcpgu.o
 obj-$(CONFIG_DRM_CIRRUS_QEMU)		+= cirrus.o
 obj-$(CONFIG_DRM_GM12U320)		+= gm12u320.o
+obj-$(CONFIG_DRM_SIMPLEDRM)		+= simpledrm.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/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
new file mode 100644
index 000000000000..0473a90a4024
--- /dev/null
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/platform_data/simplefb.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.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	"simpledrm"
+#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 SIMPLEDRM_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 simpledrm_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 */
+	uint32_t formats[8];
+	size_t nformats;
+	struct drm_connector connector;
+	struct drm_simple_display_pipe pipe;
+};
+
+static struct simpledrm_device *simpledrm_device_of_dev(struct drm_device *dev)
+{
+	return container_of(dev, struct simpledrm_device, dev);
+}
+
+/*
+ *  Simplefb settings
+ */
+
+static struct drm_display_mode simpledrm_mode(unsigned int width,
+					      unsigned int height)
+{
+	struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) };
+
+	mode.clock = 60 /* Hz */ * mode.hdisplay * mode.vdisplay;
+	drm_mode_set_name(&mode);
+
+	return mode;
+}
+
+static int simpledrm_device_init_fb(struct simpledrm_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 = simpledrm_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 simpledrm_device_init_mm(struct simpledrm_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 simpledrm_default_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 simpledrm_format_modifiers[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static int simpledrm_connector_helper_get_modes(struct drm_connector *connector)
+{
+	struct simpledrm_device *sdev = simpledrm_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 simpledrm_connector_helper_funcs = {
+	.get_modes = simpledrm_connector_helper_get_modes,
+};
+
+static const struct drm_connector_funcs simpledrm_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
+simpledrm_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
+				    const struct drm_display_mode *mode)
+{
+	struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.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
+simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
+				     struct drm_crtc_state *crtc_state,
+				     struct drm_plane_state *plane_state)
+{
+	struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
+	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+	struct drm_framebuffer *fb = plane_state->fb;
+	void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */
+
+	if (!fb)
+		return;
+
+	drm_fb_blit_dstclip(sdev->screen_base, sdev->pitch,
+			    sdev->format->format, vmap, fb);
+}
+
+static void
+simpledrm_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+	struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
+	struct drm_device *dev = &sdev->dev;
+	int idx;
+
+	if (!drm_dev_enter(dev, &idx))
+		return;
+
+	/* Clear screen to black if disabled */
+	memset_io(sdev->screen_base, 0, sdev->pitch * sdev->mode.vdisplay);
+
+	drm_dev_exit(idx);
+}
+
+static void
+simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
+				     struct drm_plane_state *old_plane_state)
+{
+	struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
+	struct drm_plane_state *plane_state = pipe->plane.state;
+	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+	void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */
+	struct drm_framebuffer *fb = plane_state->fb;
+	struct drm_rect clip;
+
+	if (!fb)
+		return;
+
+	if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &clip))
+		return;
+
+	drm_fb_blit_rect_dstclip(sdev->screen_base, sdev->pitch,
+				 sdev->format->format, vmap, fb, &clip);
+}
+
+static const struct drm_simple_display_pipe_funcs
+simpledrm_simple_display_pipe_funcs = {
+	.mode_valid = simpledrm_simple_display_pipe_mode_valid,
+	.enable = simpledrm_simple_display_pipe_enable,
+	.disable = simpledrm_simple_display_pipe_disable,
+	.update = simpledrm_simple_display_pipe_update,
+	DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
+};
+
+static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = {
+	.fb_create = drm_gem_fb_create_with_dirty,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static const uint32_t *simpledrm_device_formats(struct simpledrm_device *sdev,
+						size_t *nformats_out)
+{
+	struct drm_device *dev = &sdev->dev;
+	size_t i;
+
+	if (sdev->nformats)
+		goto out; /* don't rebuild list on recurring calls */
+
+	/* native format goes first */
+	sdev->formats[0] = sdev->format->format;
+	sdev->nformats = 1;
+
+	/* default formats go second */
+	for (i = 0; i < ARRAY_SIZE(simpledrm_default_formats); ++i) {
+		if (simpledrm_default_formats[i] == sdev->format->format)
+			continue; /* native format already went first */
+		sdev->formats[sdev->nformats] = simpledrm_default_formats[i];
+		sdev->nformats++;
+	}
+
+	/*
+	 * TODO: The simpledrm driver converts framebuffers to the native
+	 * format when copying them to device memory. If there are more
+	 * formats listed than supported by the driver, the native format
+	 * is not supported by the conversion helpers. Therefore *only*
+	 * support the native format and add a conversion helper ASAP.
+	 */
+	if (drm_WARN_ONCE(dev, i != sdev->nformats,
+			  "format conversion helpers required for %p4cc",
+			  &sdev->format->format)) {
+		sdev->nformats = 1;
+	}
+
+out:
+	*nformats_out = sdev->nformats;
+	return sdev->formats;
+}
+
+static int simpledrm_device_init_modeset(struct simpledrm_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;
+	const uint32_t *formats;
+	size_t nformats;
+	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_fbdev = true;
+	dev->mode_config.preferred_depth = sdev->format->cpp[0] * 8;
+	dev->mode_config.funcs = &simpledrm_mode_config_funcs;
+
+	ret = drm_connector_init(dev, connector, &simpledrm_connector_funcs,
+				 DRM_MODE_CONNECTOR_Unknown);
+	if (ret)
+		return ret;
+	drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs);
+
+	formats = simpledrm_device_formats(sdev, &nformats);
+
+	ret = drm_simple_display_pipe_init(dev, pipe, &simpledrm_simple_display_pipe_funcs,
+					   formats, nformats, simpledrm_format_modifiers,
+					   connector);
+	if (ret)
+		return ret;
+
+	drm_mode_config_reset(dev);
+
+	return 0;
+}
+
+/*
+ * Init / Cleanup
+ */
+
+static struct simpledrm_device *
+simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev)
+{
+	struct simpledrm_device *sdev;
+	int ret;
+
+	sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simpledrm_device,
+				  dev);
+	if (IS_ERR(sdev))
+		return ERR_CAST(sdev);
+	sdev->pdev = pdev;
+	platform_set_drvdata(pdev, sdev);
+
+	ret = simpledrm_device_init_fb(sdev);
+	if (ret)
+		return ERR_PTR(ret);
+	ret = simpledrm_device_init_mm(sdev);
+	if (ret)
+		return ERR_PTR(ret);
+	ret = simpledrm_device_init_modeset(sdev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return sdev;
+}
+
+/*
+ * DRM driver
+ */
+
+DEFINE_DRM_GEM_FOPS(simpledrm_fops);
+
+static struct drm_driver simpledrm_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			= &simpledrm_fops,
+};
+
+/*
+ * Platform driver
+ */
+
+static int simpledrm_probe(struct platform_device *pdev)
+{
+	struct simpledrm_device *sdev;
+	struct drm_device *dev;
+	int ret;
+
+	sdev = simpledrm_device_create(&simpledrm_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 simpledrm_remove(struct platform_device *pdev)
+{
+	struct simpledrm_device *sdev = platform_get_drvdata(pdev);
+	struct drm_device *dev = &sdev->dev;
+
+	drm_dev_unregister(dev);
+
+	return 0;
+}
+
+static struct platform_driver simpledrm_platform_driver = {
+	.driver = {
+		.name = "simple-framebuffer", /* connect to sysfb */
+	},
+	.probe = simpledrm_probe,
+	.remove = simpledrm_remove,
+};
+
+module_platform_driver(simpledrm_platform_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 4f02db65dede..5e1ad0c92bfc 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2192,7 +2192,7 @@ config FB_HYPERV
 
 config FB_SIMPLE
 	bool "Simple framebuffer support"
-	depends on (FB = y)
+	depends on (FB = y) && !DRM_SIMPLEDRM
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v4 5/9] drm/simpledrm: Add fbdev emulation
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
                   ` (3 preceding siblings ...)
  2021-04-16  9:00 ` [PATCH v4 4/9] drm: Add simpledrm driver Thomas Zimmermann
@ 2021-04-16  9:00 ` Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 6/9] drm/simpledrm: Initialize framebuffer data from device-tree node Thomas Zimmermann
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann, Daniel Vetter

This displays a console on simpledrm's framebuffer. The default
framebuffer format is being used.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Tested-by: nerdopolis <bluescreen_avenger@verizon.net>
---
 drivers/gpu/drm/tiny/simpledrm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 0473a90a4024..64e8a8581d9a 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -8,6 +8,7 @@
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_device.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
 #include <drm/drm_format_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
@@ -518,6 +519,8 @@ static int simpledrm_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	drm_fbdev_generic_setup(dev, 0);
+
 	return 0;
 }
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v4 6/9] drm/simpledrm: Initialize framebuffer data from device-tree node
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
                   ` (4 preceding siblings ...)
  2021-04-16  9:00 ` [PATCH v4 5/9] drm/simpledrm: Add fbdev emulation Thomas Zimmermann
@ 2021-04-16  9:00 ` Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 7/9] drm/simpledrm: Acquire clocks from DT device node Thomas Zimmermann
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann

A firmware framebuffer might also be specified via device-tree files. If
no device platform data is given, try the DT device node.

v2:
	* add Device Tree match table
	* clean-up parser wrappers

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Tested-by: nerdopolis <bluescreen_avenger@verizon.net>
---
 drivers/gpu/drm/tiny/simpledrm.c | 89 ++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 64e8a8581d9a..53d6bec7d0b2 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -114,6 +114,74 @@ 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: cannot 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: cannot 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)
+{
+	u32 width;
+	int 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)
+{
+	u32 height;
+	int 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)
+{
+	u32 stride;
+	int 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)
+{
+	const char *format;
+	int 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
  */
@@ -166,6 +234,7 @@ static int simpledrm_device_init_fb(struct simpledrm_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);
@@ -180,6 +249,19 @@ static int simpledrm_device_init_fb(struct simpledrm_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;
@@ -534,9 +616,16 @@ static int simpledrm_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id simpledrm_of_match_table[] = {
+	{ .compatible = "simple-framebuffer", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, simpledrm_of_match_table);
+
 static struct platform_driver simpledrm_platform_driver = {
 	.driver = {
 		.name = "simple-framebuffer", /* connect to sysfb */
+		.of_match_table = simpledrm_of_match_table,
 	},
 	.probe = simpledrm_probe,
 	.remove = simpledrm_remove,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v4 7/9] drm/simpledrm: Acquire clocks from DT device node
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
                   ` (5 preceding siblings ...)
  2021-04-16  9:00 ` [PATCH v4 6/9] drm/simpledrm: Initialize framebuffer data from device-tree node Thomas Zimmermann
@ 2021-04-16  9:00 ` Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 8/9] drm/simpledrm: Acquire regulators " Thomas Zimmermann
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann

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 <tzimmermann@suse.de>
Tested-by: nerdopolis <bluescreen_avenger@verizon.net>
---
 drivers/gpu/drm/tiny/simpledrm.c | 108 +++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 53d6bec7d0b2..996318500abf 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/clk.h>
+#include <linux/of_clk.h>
 #include <linux/platform_data/simplefb.h>
 #include <linux/platform_device.h>
 
@@ -190,6 +192,12 @@ struct simpledrm_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;
@@ -211,6 +219,103 @@ static struct simpledrm_device *simpledrm_device_of_dev(struct drm_device *dev)
 	return container_of(dev, struct simpledrm_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 simpledrm_device_release_clocks(void *res)
+{
+	struct simpledrm_device *sdev = simpledrm_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 simpledrm_device_init_clocks(struct simpledrm_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,
+					simpledrm_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 simpledrm_device_init_clocks(struct simpledrm_device *sdev)
+{
+	return 0;
+}
+#endif
+
 /*
  *  Simplefb settings
  */
@@ -552,6 +657,9 @@ simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev)
 	sdev->pdev = pdev;
 	platform_set_drvdata(pdev, sdev);
 
+	ret = simpledrm_device_init_clocks(sdev);
+	if (ret)
+		return ERR_PTR(ret);
 	ret = simpledrm_device_init_fb(sdev);
 	if (ret)
 		return ERR_PTR(ret);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v4 8/9] drm/simpledrm: Acquire regulators from DT device node
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
                   ` (6 preceding siblings ...)
  2021-04-16  9:00 ` [PATCH v4 7/9] drm/simpledrm: Acquire clocks from DT device node Thomas Zimmermann
@ 2021-04-16  9:00 ` Thomas Zimmermann
  2021-04-16  9:00 ` [PATCH v4 9/9] drm/simpledrm: Acquire memory aperture for framebuffer Thomas Zimmermann
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann

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.

v2:
	* use strscpy()

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Tested-by: nerdopolis <bluescreen_avenger@verizon.net>
---
 drivers/gpu/drm/tiny/simpledrm.c | 128 +++++++++++++++++++++++++++++++
 1 file changed, 128 insertions(+)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 996318500abf..9d522473cd7c 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -4,6 +4,7 @@
 #include <linux/of_clk.h>
 #include <linux/platform_data/simplefb.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 
 #include <drm/drm_atomic_state_helper.h>
 #include <drm/drm_connector.h>
@@ -197,6 +198,11 @@ struct simpledrm_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;
@@ -316,6 +322,125 @@ static int simpledrm_device_init_clocks(struct simpledrm_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 simpledrm_device_release_regulators(void *res)
+{
+	struct simpledrm_device *sdev = simpledrm_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 simpledrm_device_init_regulators(struct simpledrm_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;
+		strscpy(name, prop->name, min(sizeof(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,
+					simpledrm_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 simpledrm_device_init_regulators(struct simpledrm_device *sdev)
+{
+	return 0;
+}
+#endif
+
 /*
  *  Simplefb settings
  */
@@ -658,6 +783,9 @@ simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev)
 	platform_set_drvdata(pdev, sdev);
 
 	ret = simpledrm_device_init_clocks(sdev);
+	if (ret)
+		return ERR_PTR(ret);
+	ret = simpledrm_device_init_regulators(sdev);
 	if (ret)
 		return ERR_PTR(ret);
 	ret = simpledrm_device_init_fb(sdev);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v4 9/9] drm/simpledrm: Acquire memory aperture for framebuffer
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
                   ` (7 preceding siblings ...)
  2021-04-16  9:00 ` [PATCH v4 8/9] drm/simpledrm: Acquire regulators " Thomas Zimmermann
@ 2021-04-16  9:00 ` Thomas Zimmermann
  2021-04-19  8:00 ` [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Geert Uytterhoeven
  2021-04-29 10:24 ` Maxime Ripard
  10 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-16  9:00 UTC (permalink / raw)
  To: daniel, airlied, maarten.lankhorst, mripard, kraxel, corbet,
	lgirdwood, broonie, sam, robh, emil.l.velikov, geert+renesas,
	hdegoede, bluescreen_avenger, gregkh
  Cc: dri-devel, linux-doc, virtualization, Thomas Zimmermann

We register the simplekms device with the DRM platform helpers. A
native driver for the graphics hardware will kick-out the simpledrm
driver before taking over the device.

The original generic platform device from the simple-framebuffer boot
code will be unregistered. The native driver will use whatever native
hardware device it received.

v4:
	* convert to drm_aperture_acquire_from_firmware()
v3:
	* use platform_device_unregister() and handle detachment
	  like hot-unplug event (Daniel)
v2:
	* adapt to aperture changes
	* use drm_dev_unplug() and drm_dev_enter/exit()
	* don't split error string

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Tested-by: nerdopolis <bluescreen_avenger@verizon.net>
---
 drivers/gpu/drm/tiny/simpledrm.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 9d522473cd7c..2bdb477d9326 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -6,6 +6,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 
+#include <drm/drm_aperture.h>
 #include <drm/drm_atomic_state_helper.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_damage_helper.h>
@@ -517,14 +518,23 @@ static int simpledrm_device_init_fb(struct simpledrm_device *sdev)
 
 static int simpledrm_device_init_mm(struct simpledrm_device *sdev)
 {
+	struct drm_device *dev = &sdev->dev;
 	struct platform_device *pdev = sdev->pdev;
 	struct resource *mem;
 	void __iomem *screen_base;
+	int ret;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem)
 		return -EINVAL;
 
+	ret = devm_aperture_acquire_from_firmware(dev, mem->start, resource_size(mem));
+	if (ret) {
+		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)
@@ -625,12 +635,18 @@ simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
 	struct drm_framebuffer *fb = plane_state->fb;
 	void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */
+	struct drm_device *dev = &sdev->dev;
+	int idx;
 
 	if (!fb)
 		return;
 
+	if (!drm_dev_enter(dev, &idx))
+		return;
+
 	drm_fb_blit_dstclip(sdev->screen_base, sdev->pitch,
 			    sdev->format->format, vmap, fb);
+	drm_dev_exit(idx);
 }
 
 static void
@@ -658,7 +674,9 @@ simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
 	void *vmap = shadow_plane_state->map[0].vaddr; /* TODO: Use mapping abstraction properly */
 	struct drm_framebuffer *fb = plane_state->fb;
+	struct drm_device *dev = &sdev->dev;
 	struct drm_rect clip;
+	int idx;
 
 	if (!fb)
 		return;
@@ -666,8 +684,13 @@ simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
 	if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &clip))
 		return;
 
+	if (!drm_dev_enter(dev, &idx))
+		return;
+
 	drm_fb_blit_rect_dstclip(sdev->screen_base, sdev->pitch,
 				 sdev->format->format, vmap, fb, &clip);
+
+	drm_dev_exit(idx);
 }
 
 static const struct drm_simple_display_pipe_funcs
@@ -847,7 +870,7 @@ static int simpledrm_remove(struct platform_device *pdev)
 	struct simpledrm_device *sdev = platform_get_drvdata(pdev);
 	struct drm_device *dev = &sdev->dev;
 
-	drm_dev_unregister(dev);
+	drm_dev_unplug(dev);
 
 	return 0;
 }
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
                   ` (8 preceding siblings ...)
  2021-04-16  9:00 ` [PATCH v4 9/9] drm/simpledrm: Acquire memory aperture for framebuffer Thomas Zimmermann
@ 2021-04-19  8:00 ` Geert Uytterhoeven
  2021-04-20  8:46   ` Daniel Vetter
  2021-04-29 10:24 ` Maxime Ripard
  10 siblings, 1 reply; 21+ messages in thread
From: Geert Uytterhoeven @ 2021-04-19  8:00 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Daniel Vetter, David Airlie, Maarten Lankhorst, Maxime Ripard,
	Gerd Hoffmann, Jonathan Corbet, Liam Girdwood, Mark Brown,
	Sam Ravnborg, Rob Herring, Emil Velikov, Hans de Goede,
	bluescreen_avenger, Greg KH, DRI Development,
	open list:DOCUMENTATION, virtualization

Hi Thomas,

On Fri, Apr 16, 2021 at 11:00 AM Thomas Zimmermann <tzimmermann@suse.de> wrote:
> This patchset adds support for simple-framebuffer platform devices and
> a handover mechanism for native drivers to take-over control of the
> hardware.
>
> The new driver, called simpledrm, binds to a simple-frambuffer platform
> device. The kernel's boot code creates such devices for firmware-provided
> framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot
> loader sets up the framebuffers. Description via device tree is also an
> option.

I guess this can be used as a replacement for offb, too...

> Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
> and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During

.... if support for 8-bit frame buffers would be added?

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-19  8:00 ` [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Geert Uytterhoeven
@ 2021-04-20  8:46   ` Daniel Vetter
  2021-04-20  9:16     ` Geert Uytterhoeven
                       ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Daniel Vetter @ 2021-04-20  8:46 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Thomas Zimmermann, Daniel Vetter, David Airlie,
	Maarten Lankhorst, Maxime Ripard, Gerd Hoffmann, Jonathan Corbet,
	Liam Girdwood, Mark Brown, Sam Ravnborg, Rob Herring,
	Emil Velikov, Hans de Goede, bluescreen_avenger, Greg KH,
	DRI Development, open list:DOCUMENTATION, virtualization

On Mon, Apr 19, 2021 at 10:00:56AM +0200, Geert Uytterhoeven wrote:
> Hi Thomas,
> 
> On Fri, Apr 16, 2021 at 11:00 AM Thomas Zimmermann <tzimmermann@suse.de> wrote:
> > This patchset adds support for simple-framebuffer platform devices and
> > a handover mechanism for native drivers to take-over control of the
> > hardware.
> >
> > The new driver, called simpledrm, binds to a simple-frambuffer platform
> > device. The kernel's boot code creates such devices for firmware-provided
> > framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot
> > loader sets up the framebuffers. Description via device tree is also an
> > option.
> 
> I guess this can be used as a replacement for offb, too...
> 
> > Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
> > and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
> 
> .... if support for 8-bit frame buffers would be added?

Is that 8-bit greyscale or 8-bit indexed with 256 entry palette? Former
shouldn't be a big thing, but the latter is only really supported by the
overall drm ecosystem in theory. Most userspace assumes that xrgb8888
works, and we keep that illusion up by emulating it in kernel for hw which
just doesn't support it. But reformatting xrgb8888 to c8 is tricky at
best. The uapis are all there for setting the palette, and C8 is a defined
format even with atomic kms interface, but really there's not much
userspace for it. In other words, it would work as well as current offb
would, but that's at least that.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-20  8:46   ` Daniel Vetter
@ 2021-04-20  9:16     ` Geert Uytterhoeven
  2021-04-20 11:11       ` Daniel Vetter
  2021-04-20  9:22     ` Gerd Hoffmann
  2021-04-26 12:18     ` Thomas Zimmermann
  2 siblings, 1 reply; 21+ messages in thread
From: Geert Uytterhoeven @ 2021-04-20  9:16 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Thomas Zimmermann, David Airlie, Maarten Lankhorst,
	Maxime Ripard, Gerd Hoffmann, Jonathan Corbet, Liam Girdwood,
	Mark Brown, Sam Ravnborg, Rob Herring, Emil Velikov,
	Hans de Goede, bluescreen_avenger, Greg KH, DRI Development,
	open list:DOCUMENTATION, virtualization

Hi Daniel,

On Tue, Apr 20, 2021 at 10:46 AM Daniel Vetter <daniel@ffwll.ch> wrote:
> On Mon, Apr 19, 2021 at 10:00:56AM +0200, Geert Uytterhoeven wrote:
> > On Fri, Apr 16, 2021 at 11:00 AM Thomas Zimmermann <tzimmermann@suse.de> wrote:
> > > This patchset adds support for simple-framebuffer platform devices and
> > > a handover mechanism for native drivers to take-over control of the
> > > hardware.
> > >
> > > The new driver, called simpledrm, binds to a simple-frambuffer platform
> > > device. The kernel's boot code creates such devices for firmware-provided
> > > framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot
> > > loader sets up the framebuffers. Description via device tree is also an
> > > option.
> >
> > I guess this can be used as a replacement for offb, too...
> >
> > > Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
> > > and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
> >
> > .... if support for 8-bit frame buffers would be added?
>
> Is that 8-bit greyscale or 8-bit indexed with 256 entry palette? Former

8-bit indexed with 256 entry palette.

> shouldn't be a big thing, but the latter is only really supported by the
> overall drm ecosystem in theory. Most userspace assumes that xrgb8888
> works, and we keep that illusion up by emulating it in kernel for hw which
> just doesn't support it. But reformatting xrgb8888 to c8 is tricky at
> best. The uapis are all there for setting the palette, and C8 is a defined
> format even with atomic kms interface, but really there's not much
> userspace for it. In other words, it would work as well as current offb
> would, but that's at least that.

Oh, that's good to know!
Does this mean fbdev is not deprecated for anything <= C8? ;-)

A while ago, I was looking into converting an fbdev driver to drm, and
one of the things I ran into is lack of C4, C2, C1, Y8, Y4, Y2, and
monochrome support.  On top of that, lots of internal code seems to
assume pixels are never smaller than a byte (thus ignoring
char_per_block[]/block_w).  The lack of support for planar modes isn't
that bad, combined with the need for copying, as c2p conversion can be
done while copying, thus even making life easier for userspace
applications that can just always work on chunky data.
Then real work kicked in, before I got anything working...

Thanks!

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-20  8:46   ` Daniel Vetter
  2021-04-20  9:16     ` Geert Uytterhoeven
@ 2021-04-20  9:22     ` Gerd Hoffmann
  2021-04-20  9:27       ` Geert Uytterhoeven
  2021-04-26 12:18     ` Thomas Zimmermann
  2 siblings, 1 reply; 21+ messages in thread
From: Gerd Hoffmann @ 2021-04-20  9:22 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Geert Uytterhoeven, Thomas Zimmermann, David Airlie,
	Maarten Lankhorst, Maxime Ripard, Jonathan Corbet, Liam Girdwood,
	Mark Brown, Sam Ravnborg, Rob Herring, Emil Velikov,
	Hans de Goede, bluescreen_avenger, Greg KH, DRI Development,
	open list:DOCUMENTATION, virtualization

  Hi,

> > > Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
> > > and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
> > 
> > .... if support for 8-bit frame buffers would be added?
> 
> Is that 8-bit greyscale or 8-bit indexed with 256 entry palette? Former
> shouldn't be a big thing, but the latter is only really supported by the
> overall drm ecosystem in theory. Most userspace assumes that xrgb8888
> works, and we keep that illusion up by emulating it in kernel for hw which
> just doesn't support it. But reformatting xrgb8888 to c8 is tricky at
> best.

Well.  cirrus converts xrgb8888 on the fly to rgb888 or rgb565
(depending on display resolution).  We could pull off the same trick
here and convert to rgb332 (assuming we can program the palette with the
color cube needed for that).  Wouldn't look pretty, but would probably
work better than expecting userspace know what color palettes are in
2021 ...

take care,
  Gerd


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-20  9:22     ` Gerd Hoffmann
@ 2021-04-20  9:27       ` Geert Uytterhoeven
  2021-04-26 12:22         ` Thomas Zimmermann
  0 siblings, 1 reply; 21+ messages in thread
From: Geert Uytterhoeven @ 2021-04-20  9:27 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: Daniel Vetter, Thomas Zimmermann, David Airlie,
	Maarten Lankhorst, Maxime Ripard, Jonathan Corbet, Liam Girdwood,
	Mark Brown, Sam Ravnborg, Rob Herring, Emil Velikov,
	Hans de Goede, bluescreen_avenger, Greg KH, DRI Development,
	open list:DOCUMENTATION, virtualization

Hi Gerd,

On Tue, Apr 20, 2021 at 11:22 AM Gerd Hoffmann <kraxel@redhat.com> wrote:
> > > > Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
> > > > and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
> > >
> > > .... if support for 8-bit frame buffers would be added?
> >
> > Is that 8-bit greyscale or 8-bit indexed with 256 entry palette? Former
> > shouldn't be a big thing, but the latter is only really supported by the
> > overall drm ecosystem in theory. Most userspace assumes that xrgb8888
> > works, and we keep that illusion up by emulating it in kernel for hw which
> > just doesn't support it. But reformatting xrgb8888 to c8 is tricky at
> > best.
>
> Well.  cirrus converts xrgb8888 on the fly to rgb888 or rgb565
> (depending on display resolution).  We could pull off the same trick
> here and convert to rgb332 (assuming we can program the palette with the
> color cube needed for that).  Wouldn't look pretty, but would probably
> work better than expecting userspace know what color palettes are in
> 2021 ...

Yeah, I already had a similar idea for Amiga HAM ;-)

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-20  9:16     ` Geert Uytterhoeven
@ 2021-04-20 11:11       ` Daniel Vetter
  0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2021-04-20 11:11 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Daniel Vetter, Thomas Zimmermann, David Airlie,
	Maarten Lankhorst, Maxime Ripard, Gerd Hoffmann, Jonathan Corbet,
	Liam Girdwood, Mark Brown, Sam Ravnborg, Rob Herring,
	Emil Velikov, Hans de Goede, bluescreen_avenger, Greg KH,
	DRI Development, open list:DOCUMENTATION, virtualization

On Tue, Apr 20, 2021 at 11:16:09AM +0200, Geert Uytterhoeven wrote:
> Hi Daniel,
> 
> On Tue, Apr 20, 2021 at 10:46 AM Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Mon, Apr 19, 2021 at 10:00:56AM +0200, Geert Uytterhoeven wrote:
> > > On Fri, Apr 16, 2021 at 11:00 AM Thomas Zimmermann <tzimmermann@suse.de> wrote:
> > > > This patchset adds support for simple-framebuffer platform devices and
> > > > a handover mechanism for native drivers to take-over control of the
> > > > hardware.
> > > >
> > > > The new driver, called simpledrm, binds to a simple-frambuffer platform
> > > > device. The kernel's boot code creates such devices for firmware-provided
> > > > framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot
> > > > loader sets up the framebuffers. Description via device tree is also an
> > > > option.
> > >
> > > I guess this can be used as a replacement for offb, too...
> > >
> > > > Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
> > > > and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
> > >
> > > .... if support for 8-bit frame buffers would be added?
> >
> > Is that 8-bit greyscale or 8-bit indexed with 256 entry palette? Former
> 
> 8-bit indexed with 256 entry palette.
> 
> > shouldn't be a big thing, but the latter is only really supported by the
> > overall drm ecosystem in theory. Most userspace assumes that xrgb8888
> > works, and we keep that illusion up by emulating it in kernel for hw which
> > just doesn't support it. But reformatting xrgb8888 to c8 is tricky at
> > best. The uapis are all there for setting the palette, and C8 is a defined
> > format even with atomic kms interface, but really there's not much
> > userspace for it. In other words, it would work as well as current offb
> > would, but that's at least that.
> 
> Oh, that's good to know!
> Does this mean fbdev is not deprecated for anything <= C8? ;-)

Nope. It just means you wont be able to use drm-only userspace with it
most likely, without also investing a ton of effort into porting those
over.

> A while ago, I was looking into converting an fbdev driver to drm, and
> one of the things I ran into is lack of C4, C2, C1, Y8, Y4, Y2, and
> monochrome support.  On top of that, lots of internal code seems to
> assume pixels are never smaller than a byte (thus ignoring
> char_per_block[]/block_w).  The lack of support for planar modes isn't
> that bad, combined with the need for copying, as c2p conversion can be
> done while copying, thus even making life easier for userspace
> applications that can just always work on chunky data.
> Then real work kicked in, before I got anything working...

We support drm_fourcc, so adding more pixel formats is not problem at all.
Anything indexed/paletted will simply not work great with unchanged drm
userspace, because you can't really convert it over from the common
denominator of xrgb888. But if it's just about adding support, adding more
fourcc codes isn't a big deal. The fbdev layer hasn't been taught about
fourcc codes yet, but that's also just for lack of need by anyone.

Also we support abitrary uneven pixel packing too, with some generic
support for anything that's at least somewhat regular. That's been the
case for a while now. It was added for fancy tiling and compression
formats, but works equally well for anything else that's aligned different
than what can be described with simplistic bytes-per-pixel only.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-20  8:46   ` Daniel Vetter
  2021-04-20  9:16     ` Geert Uytterhoeven
  2021-04-20  9:22     ` Gerd Hoffmann
@ 2021-04-26 12:18     ` Thomas Zimmermann
  2021-04-26 15:08       ` Daniel Vetter
  2 siblings, 1 reply; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-26 12:18 UTC (permalink / raw)
  To: Daniel Vetter, Geert Uytterhoeven
  Cc: bluescreen_avenger, Jonathan Corbet, David Airlie, Emil Velikov,
	DRI Development, open list:DOCUMENTATION, Liam Girdwood,
	virtualization, Hans de Goede, Mark Brown, Gerd Hoffmann,
	Greg KH, Sam Ravnborg


[-- Attachment #1.1: Type: text/plain, Size: 2421 bytes --]

Hi

Am 20.04.21 um 10:46 schrieb Daniel Vetter:
> On Mon, Apr 19, 2021 at 10:00:56AM +0200, Geert Uytterhoeven wrote:
>> Hi Thomas,
>>
>> On Fri, Apr 16, 2021 at 11:00 AM Thomas Zimmermann <tzimmermann@suse.de> wrote:
>>> This patchset adds support for simple-framebuffer platform devices and
>>> a handover mechanism for native drivers to take-over control of the
>>> hardware.
>>>
>>> The new driver, called simpledrm, binds to a simple-frambuffer platform
>>> device. The kernel's boot code creates such devices for firmware-provided
>>> framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot
>>> loader sets up the framebuffers. Description via device tree is also an
>>> option.
>>
>> I guess this can be used as a replacement for offb, too...
>>
>>> Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
>>> and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
>>
>> .... if support for 8-bit frame buffers would be added?

Offb doesn't seem to be tied to the simple-framebuffer support. So 
adding a new driver or extending the simple-framebuffer code would be 
required. Not a big deal, though. Patch 3 of this patchset adds the 
ability to create generic drivers within DRM.

> 
> Is that 8-bit greyscale or 8-bit indexed with 256 entry palette? Former
> shouldn't be a big thing, but the latter is only really supported by the
> overall drm ecosystem in theory. Most userspace assumes that xrgb8888
> works, and we keep that illusion up by emulating it in kernel for hw which
> just doesn't support it. But reformatting xrgb8888 to c8 is tricky at
> best. The uapis are all there for setting the palette, and C8 is a defined
> format even with atomic kms interface, but really there's not much
> userspace for it. In other words, it would work as well as current offb
> would, but that's at least that.

I think we can just use a shadow palette in the drm driver: If the drm 
framebuffer is in C8, use the userspace's palette. If the drm 
framebuffer is in XRGB, use a palette that represents RGB332. The driver 
would do on-the-fly conversion; just like cirrus does.

Best regards
Thomas

> -Daniel
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-20  9:27       ` Geert Uytterhoeven
@ 2021-04-26 12:22         ` Thomas Zimmermann
  2021-04-26 19:05           ` Geert Uytterhoeven
  0 siblings, 1 reply; 21+ messages in thread
From: Thomas Zimmermann @ 2021-04-26 12:22 UTC (permalink / raw)
  To: Geert Uytterhoeven, Gerd Hoffmann
  Cc: bluescreen_avenger, Jonathan Corbet, David Airlie, Emil Velikov,
	open list:DOCUMENTATION, Liam Girdwood, virtualization,
	Hans de Goede, Mark Brown, DRI Development, Greg KH,
	Sam Ravnborg


[-- Attachment #1.1: Type: text/plain, Size: 1704 bytes --]

Hi

Am 20.04.21 um 11:27 schrieb Geert Uytterhoeven:
> Hi Gerd,
> 
> On Tue, Apr 20, 2021 at 11:22 AM Gerd Hoffmann <kraxel@redhat.com> wrote:
>>>>> Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
>>>>> and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
>>>>
>>>> .... if support for 8-bit frame buffers would be added?
>>>
>>> Is that 8-bit greyscale or 8-bit indexed with 256 entry palette? Former
>>> shouldn't be a big thing, but the latter is only really supported by the
>>> overall drm ecosystem in theory. Most userspace assumes that xrgb8888
>>> works, and we keep that illusion up by emulating it in kernel for hw which
>>> just doesn't support it. But reformatting xrgb8888 to c8 is tricky at
>>> best.
>>
>> Well.  cirrus converts xrgb8888 on the fly to rgb888 or rgb565
>> (depending on display resolution).  We could pull off the same trick
>> here and convert to rgb332 (assuming we can program the palette with the
>> color cube needed for that).  Wouldn't look pretty, but would probably
>> work better than expecting userspace know what color palettes are in
>> 2021 ...
> 
> Yeah, I already had a similar idea for Amiga HAM ;-)

I vaguely remember that HAM mode uses some crazy format where pixel 
colors depend in the values of their neighbors. (?) How complicated is 
it to write a conversion from RGB to HAM?

Best regards
Thomas

> 
> Gr{oetje,eeting}s,
> 
>                          Geert
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-26 12:18     ` Thomas Zimmermann
@ 2021-04-26 15:08       ` Daniel Vetter
  0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2021-04-26 15:08 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Daniel Vetter, Geert Uytterhoeven, bluescreen_avenger,
	Jonathan Corbet, David Airlie, Emil Velikov, DRI Development,
	open list:DOCUMENTATION, Liam Girdwood, virtualization,
	Hans de Goede, Mark Brown, Gerd Hoffmann, Greg KH, Sam Ravnborg

On Mon, Apr 26, 2021 at 02:18:05PM +0200, Thomas Zimmermann wrote:
> Hi
> 
> Am 20.04.21 um 10:46 schrieb Daniel Vetter:
> > On Mon, Apr 19, 2021 at 10:00:56AM +0200, Geert Uytterhoeven wrote:
> > > Hi Thomas,
> > > 
> > > On Fri, Apr 16, 2021 at 11:00 AM Thomas Zimmermann <tzimmermann@suse.de> wrote:
> > > > This patchset adds support for simple-framebuffer platform devices and
> > > > a handover mechanism for native drivers to take-over control of the
> > > > hardware.
> > > > 
> > > > The new driver, called simpledrm, binds to a simple-frambuffer platform
> > > > device. The kernel's boot code creates such devices for firmware-provided
> > > > framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot
> > > > loader sets up the framebuffers. Description via device tree is also an
> > > > option.
> > > 
> > > I guess this can be used as a replacement for offb, too...
> > > 
> > > > Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
> > > > and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
> > > 
> > > .... if support for 8-bit frame buffers would be added?
> 
> Offb doesn't seem to be tied to the simple-framebuffer support. So adding a
> new driver or extending the simple-framebuffer code would be required. Not a
> big deal, though. Patch 3 of this patchset adds the ability to create
> generic drivers within DRM.
> 
> > 
> > Is that 8-bit greyscale or 8-bit indexed with 256 entry palette? Former
> > shouldn't be a big thing, but the latter is only really supported by the
> > overall drm ecosystem in theory. Most userspace assumes that xrgb8888
> > works, and we keep that illusion up by emulating it in kernel for hw which
> > just doesn't support it. But reformatting xrgb8888 to c8 is tricky at
> > best. The uapis are all there for setting the palette, and C8 is a defined
> > format even with atomic kms interface, but really there's not much
> > userspace for it. In other words, it would work as well as current offb
> > would, but that's at least that.
> 
> I think we can just use a shadow palette in the drm driver: If the drm
> framebuffer is in C8, use the userspace's palette. If the drm framebuffer is
> in XRGB, use a palette that represents RGB332. The driver would do
> on-the-fly conversion; just like cirrus does.

Hm yeah rgb332 palette sounds like a reasonable idea. Could even have that
palette defined/generated in format conversion helpers, and then an
xrgb8888->rgb332 converter.

Lower palettes probably stop making sense as rgb, maybe there we just do
greyscale or something like that for the xrgb8888 emulation.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-26 12:22         ` Thomas Zimmermann
@ 2021-04-26 19:05           ` Geert Uytterhoeven
  0 siblings, 0 replies; 21+ messages in thread
From: Geert Uytterhoeven @ 2021-04-26 19:05 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Gerd Hoffmann, bluescreen_avenger, Jonathan Corbet, David Airlie,
	Emil Velikov, open list:DOCUMENTATION, Liam Girdwood,
	virtualization, Hans de Goede, Mark Brown, DRI Development,
	Greg KH, Sam Ravnborg

Hi Thomas,

On Mon, Apr 26, 2021 at 2:22 PM Thomas Zimmermann <tzimmermann@suse.de> wrote:
> Am 20.04.21 um 11:27 schrieb Geert Uytterhoeven:
> > On Tue, Apr 20, 2021 at 11:22 AM Gerd Hoffmann <kraxel@redhat.com> wrote:
> >>>>> Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
> >>>>> and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
> >>>>
> >>>> .... if support for 8-bit frame buffers would be added?
> >>>
> >>> Is that 8-bit greyscale or 8-bit indexed with 256 entry palette? Former
> >>> shouldn't be a big thing, but the latter is only really supported by the
> >>> overall drm ecosystem in theory. Most userspace assumes that xrgb8888
> >>> works, and we keep that illusion up by emulating it in kernel for hw which
> >>> just doesn't support it. But reformatting xrgb8888 to c8 is tricky at
> >>> best.
> >>
> >> Well.  cirrus converts xrgb8888 on the fly to rgb888 or rgb565
> >> (depending on display resolution).  We could pull off the same trick
> >> here and convert to rgb332 (assuming we can program the palette with the
> >> color cube needed for that).  Wouldn't look pretty, but would probably
> >> work better than expecting userspace know what color palettes are in
> >> 2021 ...
> >
> > Yeah, I already had a similar idea for Amiga HAM ;-)
>
> I vaguely remember that HAM mode uses some crazy format where pixel
> colors depend in the values of their neighbors. (?) How complicated is
> it to write a conversion from RGB to HAM?

Not that complicated, unless you want to do it Good & Fast ;-)

https://en.wikipedia.org/wiki/Hold-And-Modify

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs
  2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
                   ` (9 preceding siblings ...)
  2021-04-19  8:00 ` [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Geert Uytterhoeven
@ 2021-04-29 10:24 ` Maxime Ripard
  10 siblings, 0 replies; 21+ messages in thread
From: Maxime Ripard @ 2021-04-29 10:24 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: daniel, airlied, maarten.lankhorst, kraxel, corbet, lgirdwood,
	broonie, sam, robh, emil.l.velikov, geert+renesas, hdegoede,
	bluescreen_avenger, gregkh, dri-devel, linux-doc, virtualization

[-- Attachment #1: Type: text/plain, Size: 3125 bytes --]

On Fri, Apr 16, 2021 at 11:00:39AM +0200, Thomas Zimmermann wrote:
> This patchset adds support for simple-framebuffer platform devices and
> a handover mechanism for native drivers to take-over control of the
> hardware.
> 
> The new driver, called simpledrm, binds to a simple-frambuffer platform
> device. The kernel's boot code creates such devices for firmware-provided
> framebuffers, such as EFI-GOP or VESA. Typically the BIOS, UEFI or boot
> loader sets up the framebuffers. Description via device tree is also an
> option.
> 
> Simpledrm is small enough to be linked into the kernel. The driver's main
> purpose is to provide graphical output during the early phases of the boot
> process, before the native DRM drivers are available. Native drivers are
> typically loaded from an initrd ram disk. Occationally simpledrm can also
> serve as interim solution on graphics hardware without native DRM driver.
> 
> So far distributions rely on fbdev drivers, such as efifb, vesafb or
> simplefb, for early-boot graphical output. However fbdev is deprecated and
> the drivers do not provide DRM interfaces for modern userspace.
> 
> Patches 1 and 2 prepare the DRM format helpers for simpledrm.
> 
> Patches 4 to 8 add the simpledrm driver. It's build on simple DRM helpers
> and SHMEM. It supports 16-bit, 24-bit and 32-bit RGB framebuffers. During
> pageflips, SHMEM buffers are copied into the framebuffer memory, similar
> to cirrus or mgag200. The code in patches 7 and 8 handles clocks and
> regulators. It's based on the simplefb drivers, but has been modified for
> DRM.
> 
> Patches 3 and 9 add a hand-over mechanism. Simpledrm acquires it's
> framebuffer's I/O-memory range and can be hot-unplugged by a native driver.
> The native driver will remove simpledrm before taking over the hardware.
> The removal is integrated into existing helpers, so existing drivers use
> it automatically.
> 
> I've also been working on fastboot support (i.e., flicker-free booting).
> This requires state-readout from simpledrm via generic interfaces, as
> outlined in [1]. I do have some prototype code, but it will take a while
> to get this ready. Simpledrm will then support it.
> 
> I've tested simpledrm with x86 EFI and VESA framebuffers, which both work
> reliably. The fbdev console and Weston work automatically. Xorg requires
> manual configuration of the device. Xorgs current modesetting driver does
> not work with both, platform and PCI device, for the same physical
> hardware. Once configured, X11 works. I looked into X11, but couldn't see
> an easy way of fixing the problem. With the push towards Wayland+Xwayland
> I expect the problem to become a non-issue soon. Additional testing has
> been reported at [2].
> 
> One cosmetical issue is that simpledrm's device file is card0 and the
> native driver's device file is card1. After simpledrm has been kicked out,
> only card1 is left. This does not seem to be a practical problem however.

Provided that patches 4 to 8 are squashed when merged:
Acked-by: Maxime Ripard <maxime@cerno.tech>

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2021-04-29 10:24 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-16  9:00 [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Thomas Zimmermann
2021-04-16  9:00 ` [PATCH v4 1/9] drm/format-helper: Pass destination pitch to drm_fb_memcpy_dstclip() Thomas Zimmermann
2021-04-16  9:00 ` [PATCH v4 2/9] drm/format-helper: Add blitter functions Thomas Zimmermann
2021-04-16  9:00 ` [PATCH v4 3/9] drm/aperture: Add infrastructure for aperture ownership Thomas Zimmermann
2021-04-16  9:00 ` [PATCH v4 4/9] drm: Add simpledrm driver Thomas Zimmermann
2021-04-16  9:00 ` [PATCH v4 5/9] drm/simpledrm: Add fbdev emulation Thomas Zimmermann
2021-04-16  9:00 ` [PATCH v4 6/9] drm/simpledrm: Initialize framebuffer data from device-tree node Thomas Zimmermann
2021-04-16  9:00 ` [PATCH v4 7/9] drm/simpledrm: Acquire clocks from DT device node Thomas Zimmermann
2021-04-16  9:00 ` [PATCH v4 8/9] drm/simpledrm: Acquire regulators " Thomas Zimmermann
2021-04-16  9:00 ` [PATCH v4 9/9] drm/simpledrm: Acquire memory aperture for framebuffer Thomas Zimmermann
2021-04-19  8:00 ` [PATCH v4 0/9] drm: Support simple-framebuffer devices and firmware fbs Geert Uytterhoeven
2021-04-20  8:46   ` Daniel Vetter
2021-04-20  9:16     ` Geert Uytterhoeven
2021-04-20 11:11       ` Daniel Vetter
2021-04-20  9:22     ` Gerd Hoffmann
2021-04-20  9:27       ` Geert Uytterhoeven
2021-04-26 12:22         ` Thomas Zimmermann
2021-04-26 19:05           ` Geert Uytterhoeven
2021-04-26 12:18     ` Thomas Zimmermann
2021-04-26 15:08       ` Daniel Vetter
2021-04-29 10:24 ` Maxime Ripard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).