drm/sti: atomic crtc/plane update
Better fit STI hardware structure. Planes are no more responsible of updating mixer information such as z-order and status. It is now up to the CRTC atomic flush to do it. Plane actions (enable or disable) are performed atomically. Disabling of a plane is synchronize with the vsync event. Signed-off-by: Vincent Abriou <vincent.abriou@st.com> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
This commit is contained in:

committed by
Benjamin Gaignard

parent
9e1f05b280
commit
29d1dc62e1
@@ -17,20 +17,18 @@
|
||||
#include "sti_compositor.h"
|
||||
#include "sti_crtc.h"
|
||||
#include "sti_drv.h"
|
||||
#include "sti_vid.h"
|
||||
#include "sti_vtg.h"
|
||||
|
||||
static void sti_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("\n");
|
||||
}
|
||||
|
||||
static void sti_crtc_prepare(struct drm_crtc *crtc)
|
||||
static void sti_crtc_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct sti_mixer *mixer = to_sti_mixer(crtc);
|
||||
struct device *dev = mixer->dev;
|
||||
struct sti_compositor *compo = dev_get_drvdata(dev);
|
||||
|
||||
mixer->enabled = true;
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
mixer->status = STI_MIXER_READY;
|
||||
|
||||
/* Prepare and enable the compo IP clock */
|
||||
if (mixer->id == STI_MIXER_MAIN) {
|
||||
@@ -41,31 +39,16 @@ static void sti_crtc_prepare(struct drm_crtc *crtc)
|
||||
DRM_INFO("Failed to prepare/enable compo_aux clk\n");
|
||||
}
|
||||
|
||||
sti_mixer_clear_all_planes(mixer);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
}
|
||||
|
||||
static void sti_crtc_commit(struct drm_crtc *crtc)
|
||||
static void sti_crtc_disabling(struct drm_crtc *crtc)
|
||||
{
|
||||
struct sti_mixer *mixer = to_sti_mixer(crtc);
|
||||
struct device *dev = mixer->dev;
|
||||
struct sti_compositor *compo = dev_get_drvdata(dev);
|
||||
struct sti_plane *plane;
|
||||
|
||||
if ((!mixer || !compo)) {
|
||||
DRM_ERROR("Can't find mixer or compositor)\n");
|
||||
return;
|
||||
}
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
/* get GDP which is reserved to the CRTC FB */
|
||||
plane = to_sti_plane(crtc->primary);
|
||||
if (!plane)
|
||||
DRM_ERROR("Can't find CRTC dedicated plane (GDP0)\n");
|
||||
|
||||
/* Enable plane on mixer */
|
||||
if (sti_mixer_set_plane_status(mixer, plane, true))
|
||||
DRM_ERROR("Cannot enable plane at mixer\n");
|
||||
|
||||
drm_crtc_vblank_on(crtc);
|
||||
mixer->status = STI_MIXER_DISABLING;
|
||||
}
|
||||
|
||||
static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
@@ -133,9 +116,6 @@ static void sti_crtc_disable(struct drm_crtc *crtc)
|
||||
struct device *dev = mixer->dev;
|
||||
struct sti_compositor *compo = dev_get_drvdata(dev);
|
||||
|
||||
if (!mixer->enabled)
|
||||
return;
|
||||
|
||||
DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
|
||||
|
||||
/* Disable Background */
|
||||
@@ -152,13 +132,13 @@ static void sti_crtc_disable(struct drm_crtc *crtc)
|
||||
clk_disable_unprepare(compo->clk_compo_aux);
|
||||
}
|
||||
|
||||
mixer->enabled = false;
|
||||
mixer->status = STI_MIXER_DISABLED;
|
||||
}
|
||||
|
||||
static void
|
||||
sti_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
{
|
||||
sti_crtc_prepare(crtc);
|
||||
sti_crtc_enable(crtc);
|
||||
sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
|
||||
}
|
||||
|
||||
@@ -178,17 +158,79 @@ static void sti_crtc_atomic_begin(struct drm_crtc *crtc)
|
||||
|
||||
static void sti_crtc_atomic_flush(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *drm_dev = crtc->dev;
|
||||
struct sti_mixer *mixer = to_sti_mixer(crtc);
|
||||
struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
|
||||
struct drm_plane *p;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
/* perform plane actions */
|
||||
list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
|
||||
struct sti_plane *plane = to_sti_plane(p);
|
||||
|
||||
switch (plane->status) {
|
||||
case STI_PLANE_UPDATED:
|
||||
/* update planes tag as updated */
|
||||
DRM_DEBUG_DRIVER("update plane %s\n",
|
||||
sti_plane_to_str(plane));
|
||||
|
||||
if (sti_mixer_set_plane_depth(mixer, plane)) {
|
||||
DRM_ERROR("Cannot set plane %s depth\n",
|
||||
sti_plane_to_str(plane));
|
||||
break;
|
||||
}
|
||||
|
||||
if (sti_mixer_set_plane_status(mixer, plane, true)) {
|
||||
DRM_ERROR("Cannot enable plane %s at mixer\n",
|
||||
sti_plane_to_str(plane));
|
||||
break;
|
||||
}
|
||||
|
||||
/* if plane is HQVDP_0 then commit the vid[0] */
|
||||
if (plane->desc == STI_HQVDP_0)
|
||||
sti_vid_commit(compo->vid[0], p->state);
|
||||
|
||||
plane->status = STI_PLANE_READY;
|
||||
|
||||
break;
|
||||
case STI_PLANE_DISABLING:
|
||||
/* disabling sequence for planes tag as disabling */
|
||||
DRM_DEBUG_DRIVER("disable plane %s from mixer\n",
|
||||
sti_plane_to_str(plane));
|
||||
|
||||
if (sti_mixer_set_plane_status(mixer, plane, false)) {
|
||||
DRM_ERROR("Cannot disable plane %s at mixer\n",
|
||||
sti_plane_to_str(plane));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (plane->desc == STI_CURSOR)
|
||||
/* tag plane status for disabled */
|
||||
plane->status = STI_PLANE_DISABLED;
|
||||
else
|
||||
/* tag plane status for flushing */
|
||||
plane->status = STI_PLANE_FLUSHING;
|
||||
|
||||
/* if plane is HQVDP_0 then disable the vid[0] */
|
||||
if (plane->desc == STI_HQVDP_0)
|
||||
sti_vid_disable(compo->vid[0]);
|
||||
|
||||
break;
|
||||
default:
|
||||
/* Other status case are not handled */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
|
||||
.dpms = sti_crtc_dpms,
|
||||
.prepare = sti_crtc_prepare,
|
||||
.commit = sti_crtc_commit,
|
||||
.enable = sti_crtc_enable,
|
||||
.disable = sti_crtc_disabling,
|
||||
.mode_fixup = sti_crtc_mode_fixup,
|
||||
.mode_set = drm_helper_crtc_mode_set,
|
||||
.mode_set_nofb = sti_crtc_mode_set_nofb,
|
||||
.mode_set_base = drm_helper_crtc_mode_set_base,
|
||||
.disable = sti_crtc_disable,
|
||||
.atomic_begin = sti_crtc_atomic_begin,
|
||||
.atomic_flush = sti_crtc_atomic_flush,
|
||||
};
|
||||
@@ -237,6 +279,21 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,
|
||||
}
|
||||
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
|
||||
|
||||
if (compo->mixer[*crtc]->status == STI_MIXER_DISABLING) {
|
||||
struct drm_plane *p;
|
||||
|
||||
/* Disable mixer only if all overlay planes (GDP and VDP)
|
||||
* are disabled */
|
||||
list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
|
||||
struct sti_plane *plane = to_sti_plane(p);
|
||||
|
||||
if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
|
||||
if (plane->status != STI_PLANE_DISABLED)
|
||||
return 0;
|
||||
}
|
||||
sti_crtc_disable(&compo->mixer[*crtc]->drm_crtc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -259,9 +316,9 @@ int sti_crtc_enable_vblank(struct drm_device *dev, int crtc)
|
||||
}
|
||||
EXPORT_SYMBOL(sti_crtc_enable_vblank);
|
||||
|
||||
void sti_crtc_disable_vblank(struct drm_device *dev, int crtc)
|
||||
void sti_crtc_disable_vblank(struct drm_device *drm_dev, int crtc)
|
||||
{
|
||||
struct sti_private *priv = dev->dev_private;
|
||||
struct sti_private *priv = drm_dev->dev_private;
|
||||
struct sti_compositor *compo = priv->compo;
|
||||
struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
|
||||
|
||||
@@ -273,7 +330,7 @@ void sti_crtc_disable_vblank(struct drm_device *dev, int crtc)
|
||||
|
||||
/* free the resources of the pending requests */
|
||||
if (compo->mixer[crtc]->pending_event) {
|
||||
drm_vblank_put(dev, crtc);
|
||||
drm_vblank_put(drm_dev, crtc);
|
||||
compo->mixer[crtc]->pending_event = NULL;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user