drm/panel: add .prepare() and .unprepare() functions
authorAjay Kumar <ajaykumar.rs@samsung.com>
Thu, 17 Jul 2014 20:43:48 +0000 (02:13 +0530)
committerThierry Reding <treding@nvidia.com>
Wed, 6 Aug 2014 14:44:09 +0000 (16:44 +0200)
Panels often require an initialization sequence that consists of three
steps: a) powering up the panel, b) starting transmission of video data
and c) enabling the panel (e.g. turn on backlight). This is usually
necessary to avoid visual glitches at the beginning of video data
transmission.

Similarly, the shutdown sequence is typically done in three steps as
well: a) disable the panel (e.g. turn off backlight), b) cease video
data transmission and c) power down the panel.

Currently drivers can only implement .enable() and .disable() functions,
which is not enough to implement the above sequences. This commit adds a
second pair of functions, .prepare() and .unprepare() to allow more
fine-grained control over when the above steps are performed.

Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
[treding: rewrite changelog, add kerneldoc]
Signed-off-by: Thierry Reding <treding@nvidia.com>
include/drm/drm_panel.h

index c2ab77a..29e3daf 100644 (file)
@@ -30,8 +30,42 @@ struct drm_connector;
 struct drm_device;
 struct drm_panel;
 
+/**
+ * struct drm_panel_funcs - perform operations on a given panel
+ * @disable: disable panel (turn off back light, etc.)
+ * @unprepare: turn off panel
+ * @prepare: turn on panel and perform set up
+ * @enable: enable panel (turn on back light, etc.)
+ * @get_modes: add modes to the connector that the panel is attached to and
+ * return the number of modes added
+ *
+ * The .prepare() function is typically called before the display controller
+ * starts to transmit video data. Panel drivers can use this to turn the panel
+ * on and wait for it to become ready. If additional configuration is required
+ * (via a control bus such as I2C, SPI or DSI for example) this is a good time
+ * to do that.
+ *
+ * After the display controller has started transmitting video data, it's safe
+ * to call the .enable() function. This will typically enable the backlight to
+ * make the image on screen visible. Some panels require a certain amount of
+ * time or frames before the image is displayed. This function is responsible
+ * for taking this into account before enabling the backlight to avoid visual
+ * glitches.
+ *
+ * Before stopping video transmission from the display controller it can be
+ * necessary to turn off the panel to avoid visual glitches. This is done in
+ * the .disable() function. Analogously to .enable() this typically involves
+ * turning off the backlight and waiting for some time to make sure no image
+ * is visible on the panel. It is then safe for the display controller to
+ * cease transmission of video data.
+ *
+ * To save power when no video data is transmitted, a driver can power down
+ * the panel. This is the job of the .unprepare() function.
+ */
 struct drm_panel_funcs {
        int (*disable)(struct drm_panel *panel);
+       int (*unprepare)(struct drm_panel *panel);
+       int (*prepare)(struct drm_panel *panel);
        int (*enable)(struct drm_panel *panel);
        int (*get_modes)(struct drm_panel *panel);
 };
@@ -46,6 +80,14 @@ struct drm_panel {
        struct list_head list;
 };
 
+static inline int drm_panel_unprepare(struct drm_panel *panel)
+{
+       if (panel && panel->funcs && panel->funcs->unprepare)
+               return panel->funcs->unprepare(panel);
+
+       return panel ? -ENOSYS : -EINVAL;
+}
+
 static inline int drm_panel_disable(struct drm_panel *panel)
 {
        if (panel && panel->funcs && panel->funcs->disable)
@@ -54,6 +96,14 @@ static inline int drm_panel_disable(struct drm_panel *panel)
        return panel ? -ENOSYS : -EINVAL;
 }
 
+static inline int drm_panel_prepare(struct drm_panel *panel)
+{
+       if (panel && panel->funcs && panel->funcs->prepare)
+               return panel->funcs->prepare(panel);
+
+       return panel ? -ENOSYS : -EINVAL;
+}
+
 static inline int drm_panel_enable(struct drm_panel *panel)
 {
        if (panel && panel->funcs && panel->funcs->enable)