@@ -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
@@ -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);
/**
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(+)