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@xxxxxxxxxxx> --- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel