[RFC 3/4] drm/mipi-dbi: Support command mode panel drivers

Noralf Trønnes noralf at tronnes.org
Mon Jul 29 19:55:25 UTC 2019


This adds a function that registers a DRM driver for use with MIPI DBI
panels in command mode. That is, framebuffer upload over DBI.

Signed-off-by: Noralf Trønnes <noralf at tronnes.org>
---
 drivers/gpu/drm/drm_mipi_dbi.c | 110 +++++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dbi.h     |   8 +++
 2 files changed, 118 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 1961f713aaab..ef6b843eaf31 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -10,6 +10,7 @@
 #include <linux/dma-buf.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
+#include <linux/property.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 
@@ -17,11 +18,13 @@
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_helper.h>
 #include <drm/drm_format_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_mipi_dbi.h>
 #include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_rect.h>
 #include <drm/drm_vblank.h>
@@ -597,6 +600,113 @@ void mipi_dbi_release(struct drm_device *drm)
 }
 EXPORT_SYMBOL(mipi_dbi_release);
 
+static void drm_mipi_dbi_panel_pipe_enable(struct drm_simple_display_pipe *pipe,
+					   struct drm_crtc_state *crtc_state,
+					   struct drm_plane_state *plane_state)
+{
+	struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+	struct drm_panel *panel = dbidev->panel;
+	int ret, idx;
+
+	if (!drm_dev_enter(pipe->crtc.dev, &idx))
+		return;
+
+	DRM_DEBUG_KMS("\n");
+
+	ret = drm_panel_prepare(panel);
+	if (ret)
+		goto out_exit;
+
+	mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+
+	drm_panel_enable(panel);
+out_exit:
+	drm_dev_exit(idx);
+}
+
+static void drm_mipi_dbi_panel_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+	struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+	struct drm_panel *panel = dbidev->panel;
+
+	if (!dbidev->enabled)
+		return;
+
+	DRM_DEBUG_KMS("\n");
+
+	dbidev->enabled = false;
+	drm_panel_disable(panel);
+	drm_panel_unprepare(panel);
+}
+
+static const struct drm_simple_display_pipe_funcs drm_mipi_dbi_pipe_funcs = {
+	.enable = drm_mipi_dbi_panel_pipe_enable,
+	.disable = drm_mipi_dbi_panel_pipe_disable,
+	.update = mipi_dbi_pipe_update,
+	.prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(drm_mipi_dbi_fops);
+
+static struct drm_driver drm_mipi_dbi_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+	.fops			= &drm_mipi_dbi_fops,
+	.release		= mipi_dbi_release,
+	DRM_GEM_CMA_VMAP_DRIVER_OPS,
+	.debugfs_init		= mipi_dbi_debugfs_init,
+	.name			= "drm_mipi_dbi",
+	.desc			= "DRM MIPI DBI",
+	.date			= "20190729",
+	.major			= 1,
+	.minor			= 0,
+};
+
+/**
+ * drm_mipi_dbi_panel_register - Register a MIPI DBI DRM driver
+ * @panel: DRM Panel
+ * @dbidev: MIPI DBI device structure to initialize
+ * @mode: Display mode
+ *
+ * This function registeres a DRM driver with @panel attached.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int drm_mipi_dbi_panel_register(struct drm_panel *panel, struct mipi_dbi_dev *dbidev,
+				const struct drm_display_mode *mode)
+{
+	struct device *dev = panel->dev;
+	struct drm_device *drm;
+	u32 rotation = 0;
+	int ret;
+
+	dbidev->panel = panel;
+
+	drm = &dbidev->drm;
+	ret = devm_drm_dev_init(dev, drm, &drm_mipi_dbi_driver);
+	if (ret) {
+		kfree(dbidev);
+		return ret;
+	}
+
+	drm_mode_config_init(drm);
+
+	device_property_read_u32(dev, "rotation", &rotation);
+
+	ret = mipi_dbi_dev_init(dbidev, &drm_mipi_dbi_pipe_funcs, mode, rotation);
+
+	drm_mode_config_reset(drm);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		return ret;
+
+	drm_fbdev_generic_setup(drm, 16);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_mipi_dbi_panel_register);
+
 /**
  * mipi_dbi_hw_reset - Hardware reset of controller
  * @dbi: MIPI DBI structure
diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
index 67c66f5ee591..e5047208ffb8 100644
--- a/include/drm/drm_mipi_dbi.h
+++ b/include/drm/drm_mipi_dbi.h
@@ -12,6 +12,7 @@
 #include <drm/drm_device.h>
 #include <drm/drm_simple_kms_helper.h>
 
+struct drm_panel;
 struct drm_rect;
 struct spi_device;
 struct gpio_desc;
@@ -123,6 +124,11 @@ struct mipi_dbi_dev {
 	 * @dbi: MIPI DBI interface
 	 */
 	struct mipi_dbi dbi;
+
+	/**
+	 * @panel: Attached DRM panel. See drm_mipi_dbi_panel_register().
+	 */
+	struct drm_panel *panel;
 };
 
 static inline struct mipi_dbi_dev *drm_to_mipi_dbi_dev(struct drm_device *drm)
@@ -140,6 +146,8 @@ int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev,
 int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev,
 		      const struct drm_simple_display_pipe_funcs *funcs,
 		      const struct drm_display_mode *mode, unsigned int rotation);
+int drm_mipi_dbi_panel_register(struct drm_panel *panel, struct mipi_dbi_dev *dbidev,
+				const struct drm_display_mode *mode);
 void mipi_dbi_release(struct drm_device *drm);
 void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
 			  struct drm_plane_state *old_state);
-- 
2.20.1



More information about the dri-devel mailing list