Commit 63498e30 authored by Gustavo Padovan's avatar Gustavo Padovan Committed by Inki Dae

drm/exynos: atomic dpms support

Run dpms operations through the atomic intefaces. This basically removes
the .dpms() callback from econders and crtcs and use .disable() and
.enable() to turn the crtc on and off.

v2: Address comments by Joonyoung:
	- make hdmi code call ->disable() instead of ->dpms()
	- do not use WARN_ON on crtc enable/disable

v3: - Fix build failure after the hdmi change in v2
    - Change dpms helper of ptn3460 bridge

v4: - remove win_commit() call from .enable()

v5: - move .atomic_check() to the atomic PageFlip patch, and transform it
in .atomic_begin()
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
Reviewed-by: default avatarJoonyoung Shim <jy0922.shim@samsung.com>
Tested-by: default avatarTobias Jakobi <tjakobi@math.uni-bielefeld.de>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent d6562a29
...@@ -500,7 +500,7 @@ static void ps8622_connector_destroy(struct drm_connector *connector) ...@@ -500,7 +500,7 @@ static void ps8622_connector_destroy(struct drm_connector *connector)
} }
static const struct drm_connector_funcs ps8622_connector_funcs = { static const struct drm_connector_funcs ps8622_connector_funcs = {
.dpms = drm_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.detect = ps8622_detect, .detect = ps8622_detect,
.destroy = ps8622_connector_destroy, .destroy = ps8622_connector_destroy,
......
...@@ -259,7 +259,7 @@ static void ptn3460_connector_destroy(struct drm_connector *connector) ...@@ -259,7 +259,7 @@ static void ptn3460_connector_destroy(struct drm_connector *connector)
} }
static struct drm_connector_funcs ptn3460_connector_funcs = { static struct drm_connector_funcs ptn3460_connector_funcs = {
.dpms = drm_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.detect = ptn3460_detect, .detect = ptn3460_detect,
.destroy = ptn3460_connector_destroy, .destroy = ptn3460_connector_destroy,
......
...@@ -953,7 +953,7 @@ static void exynos_dp_connector_destroy(struct drm_connector *connector) ...@@ -953,7 +953,7 @@ static void exynos_dp_connector_destroy(struct drm_connector *connector)
} }
static struct drm_connector_funcs exynos_dp_connector_funcs = { static struct drm_connector_funcs exynos_dp_connector_funcs = {
.dpms = drm_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.detect = exynos_dp_detect, .detect = exynos_dp_detect,
.destroy = exynos_dp_connector_destroy, .destroy = exynos_dp_connector_destroy,
......
...@@ -22,40 +22,41 @@ ...@@ -22,40 +22,41 @@
#include "exynos_drm_encoder.h" #include "exynos_drm_encoder.h"
#include "exynos_drm_plane.h" #include "exynos_drm_plane.h"
static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) static void exynos_drm_crtc_enable(struct drm_crtc *crtc)
{ {
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); if (exynos_crtc->enabled)
if (exynos_crtc->dpms == mode) {
DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
return; return;
}
if (mode > DRM_MODE_DPMS_ON) {
/* wait for the completion of page flip. */
if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
(exynos_crtc->event == NULL), HZ/20))
exynos_crtc->event = NULL;
drm_crtc_vblank_off(crtc);
}
if (exynos_crtc->ops->dpms) if (exynos_crtc->ops->dpms)
exynos_crtc->ops->dpms(exynos_crtc, mode); exynos_crtc->ops->dpms(exynos_crtc, DRM_MODE_DPMS_ON);
exynos_crtc->dpms = mode; exynos_crtc->enabled = true;
if (mode == DRM_MODE_DPMS_ON) drm_crtc_vblank_on(crtc);
drm_crtc_vblank_on(crtc);
} }
static void exynos_drm_crtc_disable(struct drm_crtc *crtc) static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
{ {
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct drm_plane *plane; struct drm_plane *plane;
int ret; int ret;
exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); if (!exynos_crtc->enabled)
return;
/* wait for the completion of page flip. */
if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
(exynos_crtc->event == NULL), HZ/20))
exynos_crtc->event = NULL;
drm_crtc_vblank_off(crtc);
if (exynos_crtc->ops->dpms)
exynos_crtc->ops->dpms(exynos_crtc, DRM_MODE_DPMS_OFF);
exynos_crtc->enabled = false;
drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) { drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) {
if (plane->crtc != crtc) if (plane->crtc != crtc)
...@@ -67,17 +68,6 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc) ...@@ -67,17 +68,6 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
} }
} }
static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
{
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct exynos_drm_plane *exynos_plane = to_exynos_plane(crtc->primary);
exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
if (exynos_crtc->ops->win_commit)
exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
}
static bool static bool
exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
...@@ -116,9 +106,8 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc) ...@@ -116,9 +106,8 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc)
} }
static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
.dpms = exynos_drm_crtc_dpms, .enable = exynos_drm_crtc_enable,
.disable = exynos_drm_crtc_disable, .disable = exynos_drm_crtc_disable,
.commit = exynos_drm_crtc_commit,
.mode_fixup = exynos_drm_crtc_mode_fixup, .mode_fixup = exynos_drm_crtc_mode_fixup,
.mode_set_nofb = exynos_drm_crtc_mode_set_nofb, .mode_set_nofb = exynos_drm_crtc_mode_set_nofb,
.atomic_begin = exynos_crtc_atomic_begin, .atomic_begin = exynos_crtc_atomic_begin,
...@@ -163,7 +152,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, ...@@ -163,7 +152,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
init_waitqueue_head(&exynos_crtc->pending_flip_queue); init_waitqueue_head(&exynos_crtc->pending_flip_queue);
exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
exynos_crtc->pipe = pipe; exynos_crtc->pipe = pipe;
exynos_crtc->type = type; exynos_crtc->type = type;
exynos_crtc->ops = ops; exynos_crtc->ops = ops;
...@@ -194,7 +182,7 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) ...@@ -194,7 +182,7 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
struct exynos_drm_crtc *exynos_crtc = struct exynos_drm_crtc *exynos_crtc =
to_exynos_crtc(private->crtc[pipe]); to_exynos_crtc(private->crtc[pipe]);
if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) if (!exynos_crtc->enabled)
return -EPERM; return -EPERM;
if (exynos_crtc->ops->enable_vblank) if (exynos_crtc->ops->enable_vblank)
...@@ -209,7 +197,7 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe) ...@@ -209,7 +197,7 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
struct exynos_drm_crtc *exynos_crtc = struct exynos_drm_crtc *exynos_crtc =
to_exynos_crtc(private->crtc[pipe]); to_exynos_crtc(private->crtc[pipe]);
if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) if (!exynos_crtc->enabled)
return; return;
if (exynos_crtc->ops->disable_vblank) if (exynos_crtc->ops->disable_vblank)
......
...@@ -60,7 +60,7 @@ static void exynos_dpi_connector_destroy(struct drm_connector *connector) ...@@ -60,7 +60,7 @@ static void exynos_dpi_connector_destroy(struct drm_connector *connector)
} }
static struct drm_connector_funcs exynos_dpi_connector_funcs = { static struct drm_connector_funcs exynos_dpi_connector_funcs = {
.dpms = drm_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.detect = exynos_dpi_detect, .detect = exynos_dpi_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = exynos_dpi_connector_destroy, .destroy = exynos_dpi_connector_destroy,
......
...@@ -201,7 +201,7 @@ struct exynos_drm_crtc_ops { ...@@ -201,7 +201,7 @@ struct exynos_drm_crtc_ops {
* drm framework doesn't support multiple irq yet. * drm framework doesn't support multiple irq yet.
* we can refer to the crtc to current hardware interrupt occurred through * we can refer to the crtc to current hardware interrupt occurred through
* this pipe value. * this pipe value.
* @dpms: store the crtc dpms value * @enabled: if the crtc is enabled or not
* @event: vblank event that is currently queued for flip * @event: vblank event that is currently queued for flip
* @ops: pointer to callbacks for exynos drm specific functionality * @ops: pointer to callbacks for exynos drm specific functionality
* @ctx: A pointer to the crtc's implementation specific context * @ctx: A pointer to the crtc's implementation specific context
...@@ -210,7 +210,7 @@ struct exynos_drm_crtc { ...@@ -210,7 +210,7 @@ struct exynos_drm_crtc {
struct drm_crtc base; struct drm_crtc base;
enum exynos_drm_output_type type; enum exynos_drm_output_type type;
unsigned int pipe; unsigned int pipe;
unsigned int dpms; bool enabled;
wait_queue_head_t pending_flip_queue; wait_queue_head_t pending_flip_queue;
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
const struct exynos_drm_crtc_ops *ops; const struct exynos_drm_crtc_ops *ops;
......
...@@ -1458,7 +1458,7 @@ static void exynos_dsi_connector_destroy(struct drm_connector *connector) ...@@ -1458,7 +1458,7 @@ static void exynos_dsi_connector_destroy(struct drm_connector *connector)
} }
static struct drm_connector_funcs exynos_dsi_connector_funcs = { static struct drm_connector_funcs exynos_dsi_connector_funcs = {
.dpms = drm_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.detect = exynos_dsi_detect, .detect = exynos_dsi_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = exynos_dsi_connector_destroy, .destroy = exynos_dsi_connector_destroy,
......
...@@ -32,17 +32,6 @@ struct exynos_drm_encoder { ...@@ -32,17 +32,6 @@ struct exynos_drm_encoder {
struct exynos_drm_display *display; struct exynos_drm_display *display;
}; };
static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
{
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
struct exynos_drm_display *display = exynos_encoder->display;
DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
if (display->ops->dpms)
display->ops->dpms(display, mode);
}
static bool static bool
exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
...@@ -76,7 +65,7 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, ...@@ -76,7 +65,7 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
display->ops->mode_set(display, adjusted_mode); display->ops->mode_set(display, adjusted_mode);
} }
static void exynos_drm_encoder_commit(struct drm_encoder *encoder) static void exynos_drm_encoder_enable(struct drm_encoder *encoder)
{ {
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
struct exynos_drm_display *display = exynos_encoder->display; struct exynos_drm_display *display = exynos_encoder->display;
...@@ -90,10 +79,13 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder) ...@@ -90,10 +79,13 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
static void exynos_drm_encoder_disable(struct drm_encoder *encoder) static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
{ {
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
struct exynos_drm_display *display = exynos_encoder->display;
struct drm_plane *plane; struct drm_plane *plane;
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); if (display->ops->dpms)
display->ops->dpms(display, DRM_MODE_DPMS_OFF);
/* all planes connected to this encoder should be also disabled. */ /* all planes connected to this encoder should be also disabled. */
drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
...@@ -103,10 +95,9 @@ static void exynos_drm_encoder_disable(struct drm_encoder *encoder) ...@@ -103,10 +95,9 @@ static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
} }
static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = { static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
.dpms = exynos_drm_encoder_dpms,
.mode_fixup = exynos_drm_encoder_mode_fixup, .mode_fixup = exynos_drm_encoder_mode_fixup,
.mode_set = exynos_drm_encoder_mode_set, .mode_set = exynos_drm_encoder_mode_set,
.commit = exynos_drm_encoder_commit, .enable = exynos_drm_encoder_enable,
.disable = exynos_drm_encoder_disable, .disable = exynos_drm_encoder_disable,
}; };
......
...@@ -385,7 +385,7 @@ static void vidi_connector_destroy(struct drm_connector *connector) ...@@ -385,7 +385,7 @@ static void vidi_connector_destroy(struct drm_connector *connector)
} }
static struct drm_connector_funcs vidi_connector_funcs = { static struct drm_connector_funcs vidi_connector_funcs = {
.dpms = drm_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.detect = vidi_detect, .detect = vidi_detect,
.destroy = vidi_connector_destroy, .destroy = vidi_connector_destroy,
......
...@@ -1051,7 +1051,7 @@ static void hdmi_connector_destroy(struct drm_connector *connector) ...@@ -1051,7 +1051,7 @@ static void hdmi_connector_destroy(struct drm_connector *connector)
} }
static struct drm_connector_funcs hdmi_connector_funcs = { static struct drm_connector_funcs hdmi_connector_funcs = {
.dpms = drm_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.detect = hdmi_detect, .detect = hdmi_detect,
.destroy = hdmi_connector_destroy, .destroy = hdmi_connector_destroy,
...@@ -2127,8 +2127,8 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode) ...@@ -2127,8 +2127,8 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode)
*/ */
if (crtc) if (crtc)
funcs = crtc->helper_private; funcs = crtc->helper_private;
if (funcs && funcs->dpms) if (funcs && funcs->disable)
(*funcs->dpms)(crtc, mode); (*funcs->disable)(crtc);
hdmi_poweroff(hdata); hdmi_poweroff(hdata);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment