diff mbox series

[5/6] drm/mipi-dbi: Add device property functions

Message ID 20211124150757.17929-6-noralf@tronnes.org (mailing list archive)
State Awaiting Upstream
Headers show
Series drm/tiny/st7735r: Match up with staging/fbtft driver | expand

Commit Message

Noralf Trønnes Nov. 24, 2021, 3:07 p.m. UTC
Add helper functions for configuring a MIPI DBI controller from device
properties.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_mipi_dbi.c | 139 +++++++++++++++++++++++++++++++++
 include/drm/drm_mipi_dbi.h     |   3 +
 2 files changed, 142 insertions(+)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 71b646c4131f..41362e1d4231 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -137,6 +137,24 @@  int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val)
 }
 EXPORT_SYMBOL(mipi_dbi_command_read);
 
+/**
+ * mipi_dbi_set_writeonly - Set the controller write only state
+ * @dbi: MIPI DBI structure
+ * @writeonly: If true the controller is not readable
+ *
+ * This function sets whether the controller can be read from or not (ie. MISO connected or not).
+ * It also checks the 'write-only' device property which overrides @writeonly.
+ * The controller is assumed to be readable by default.
+ */
+void mipi_dbi_set_writeonly(struct mipi_dbi *dbi, bool writeonly)
+{
+	struct device *dev = &dbi->spi->dev;
+
+	if (writeonly || device_property_present(dev, "write-only"))
+		dbi->read_commands = NULL;
+}
+EXPORT_SYMBOL(mipi_dbi_set_writeonly);
+
 /**
  * mipi_dbi_command_buf - MIPI DCS command with parameter(s) in an array
  * @dbi: MIPI DBI structure
@@ -186,6 +204,40 @@  int mipi_dbi_command_stackbuf(struct mipi_dbi *dbi, u8 cmd, const u8 *data,
 }
 EXPORT_SYMBOL(mipi_dbi_command_stackbuf);
 
+/**
+ * mipi_dbi_command_from_property - MIPI DCS command with parameter(s) from a device property
+ * @dbi: MIPI DBI structure
+ * @cmd: Command
+ * @propname: Name of the device property
+ * @len: Data length
+ *
+ * This function will execute @cmd with parameters from @propname if it exist.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_command_from_property(struct mipi_dbi *dbi, u8 cmd, const char *propname, size_t len)
+{
+	struct device *dev = &dbi->spi->dev;
+	u8 data[64];
+	int ret;
+
+	if (WARN_ON_ONCE(len > sizeof(data)))
+		return -EINVAL;
+
+	if (!device_property_present(dev, propname))
+		return 0;
+
+	ret = device_property_read_u8_array(dev, propname, data, len);
+	if (ret) {
+		dev_err(dev, "Failed to read property '%s', error=%d\n", propname, ret);
+		return ret;
+	}
+
+	return mipi_dbi_command_stackbuf(dbi, cmd, data, len);
+}
+EXPORT_SYMBOL(mipi_dbi_command_from_property);
+
 /**
  * mipi_dbi_buf_copy - Copy a framebuffer, transforming it if necessary
  * @dst: The destination buffer
@@ -571,6 +623,93 @@  int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev,
 }
 EXPORT_SYMBOL(mipi_dbi_dev_init);
 
+static int mipi_dbi_property_read_u32(struct device *dev, const char *propname,
+				      unsigned int *retval, bool required)
+{
+	u32 val32;
+	int ret;
+
+	if (!device_property_present(dev, propname)) {
+		if (required) {
+			dev_err(dev, "Missing required property '%s'\n", propname);
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	ret = device_property_read_u32(dev, propname, &val32);
+	if (ret) {
+		dev_err(dev, "Error reading property '%s', error=%d\n", propname, ret);
+		return ret;
+	}
+
+	*retval = val32;
+
+	return 0;
+}
+
+static void mipi_dbi_simple_mode(struct drm_display_mode *mode,
+				 unsigned int width, unsigned int height,
+				 unsigned int width_mm, unsigned int height_mm)
+{
+	struct drm_display_mode simple_mode = { DRM_SIMPLE_MODE(width, height, width_mm, height_mm) };
+
+	*mode = simple_mode;
+}
+
+/**
+ * mipi_dbi_read_device_properties - Read device properties
+ * @dbidev: MIPI DBI device structure
+ * @mode: Returned display mode
+ *
+ * This function reads device properties 'width', 'height', 'width_mm', 'height_mm'
+ * and returns them as a display mode in @mode.
+ * It also reads 'x-offset' and 'y-offset' whose values are set on @dbidev.
+ *
+ * The returned @mode can be passed on to mipi_dbi_dev_init().
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_read_device_properties(struct mipi_dbi_dev *dbidev, struct drm_display_mode *mode)
+{
+	unsigned int width, height, width_mm = 0, height_mm = 0;
+	struct device *dev = dbidev->drm.dev;
+	int ret;
+
+	ret = mipi_dbi_property_read_u32(dev, "width", &width, true);
+	if (ret)
+		return ret;
+
+	ret = mipi_dbi_property_read_u32(dev, "height", &height, true);
+	if (ret)
+		return ret;
+
+	if (device_property_present(dev, "width_mm") || device_property_present(dev, "height_mm")) {
+		ret = mipi_dbi_property_read_u32(dev, "width_mm", &width_mm, true);
+		if (ret)
+			return ret;
+
+		ret = mipi_dbi_property_read_u32(dev, "height_mm", &height_mm, true);
+		if (ret)
+			return ret;
+	}
+
+	mipi_dbi_simple_mode(mode, width, height, width_mm, height_mm);
+
+	ret = mipi_dbi_property_read_u32(dev, "x-offset", &dbidev->left_offset, false);
+	if (ret)
+		return ret;
+
+	ret = mipi_dbi_property_read_u32(dev, "y-offset", &dbidev->top_offset, false);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(mipi_dbi_read_device_properties);
+
 /**
  * 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 05e194958265..c75f760d6de5 100644
--- a/include/drm/drm_mipi_dbi.h
+++ b/include/drm/drm_mipi_dbi.h
@@ -147,6 +147,7 @@  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 mipi_dbi_read_device_properties(struct mipi_dbi_dev *dbidev, struct drm_display_mode *mode);
 void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
 			  struct drm_plane_state *old_state);
 void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev,
@@ -163,9 +164,11 @@  int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz,
 			  u8 bpw, const void *buf, size_t len);
 
 int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val);
+void mipi_dbi_set_writeonly(struct mipi_dbi *dbi, bool writeonly);
 int mipi_dbi_command_buf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len);
 int mipi_dbi_command_stackbuf(struct mipi_dbi *dbi, u8 cmd, const u8 *data,
 			      size_t len);
+int mipi_dbi_command_from_property(struct mipi_dbi *dbi, u8 cmd, const char *propname, size_t len);
 int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
 		      struct drm_rect *clip, bool swap);
 /**