Add helper functions for configuring a MIPI DBI controller from device properties. Signed-off-by: Noralf Trønnes <noralf@xxxxxxxxxxx> --- drivers/gpu/drm/drm_mipi_dbi.c | 139 +++++++++++++++++++++++++++++++++ include/drm/drm_mipi_dbi.h | 3 + 2 files changed, 142 insertions(+) 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); /** -- 2.33.0