Skip to content

Commit

Permalink
drm/mediatek: update cursors by using async atomic update
Browse files Browse the repository at this point in the history
Support to async updates of cursors by using the new atomic
interface for that.

Signed-off-by: Bibby Hsieh <bibby.hsieh@mediatek.com>
Signed-off-by: CK Hu <ck.hu@mediatek.com>
  • Loading branch information
Bibby Hsieh authored and CK Hu committed Dec 20, 2019
1 parent 411f5c1 commit 920fffc
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 21 deletions.
98 changes: 77 additions & 21 deletions drivers/gpu/drm/mediatek/mtk_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,15 @@ struct mtk_drm_crtc {
struct drm_plane *planes;
unsigned int layer_nr;
bool pending_planes;
bool pending_async_planes;

void __iomem *config_regs;
struct mtk_disp_mutex *mutex;
unsigned int ddp_comp_nr;
struct mtk_ddp_comp **ddp_comp;

/* lock for display hardware access */
struct mutex hw_lock;
};

struct mtk_crtc_state {
Expand Down Expand Up @@ -404,6 +408,63 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
}
mtk_crtc->pending_planes = false;
}

if (mtk_crtc->pending_async_planes) {
for (i = 0; i < mtk_crtc->layer_nr; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
struct mtk_plane_state *plane_state;

plane_state = to_mtk_plane_state(plane->state);

if (!plane_state->pending.async_config)
continue;

comp = mtk_drm_ddp_comp_for_plane(crtc, plane,
&local_layer);

if (comp)
mtk_ddp_comp_layer_config(comp, local_layer,
plane_state);
plane_state->pending.async_config = false;
}
mtk_crtc->pending_async_planes = false;
}
}

static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc)
{
struct drm_crtc *crtc = &mtk_crtc->base;
struct mtk_drm_private *priv = crtc->dev->dev_private;
unsigned int pending_planes = 0, pending_async_planes = 0;
int i;

mutex_lock(&mtk_crtc->hw_lock);
for (i = 0; i < mtk_crtc->layer_nr; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
struct mtk_plane_state *plane_state;

plane_state = to_mtk_plane_state(plane->state);
if (plane_state->pending.dirty) {
plane_state->pending.config = true;
plane_state->pending.dirty = false;
pending_planes |= BIT(i);
} else if (plane_state->pending.async_dirty) {
plane_state->pending.async_config = true;
plane_state->pending.async_dirty = false;
pending_async_planes |= BIT(i);
}
}
if (pending_planes)
mtk_crtc->pending_planes = true;
if (pending_async_planes)
mtk_crtc->pending_async_planes = true;

if (priv->data->shadow_register) {
mtk_disp_mutex_acquire(mtk_crtc->mutex);
mtk_crtc_ddp_config(crtc);
mtk_disp_mutex_release(mtk_crtc->mutex);
}
mutex_unlock(&mtk_crtc->hw_lock);
}

int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
Expand All @@ -418,6 +479,20 @@ int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
return 0;
}

void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
struct drm_plane_state *new_state)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
const struct drm_plane_helper_funcs *plane_helper_funcs =
plane->helper_private;

if (!mtk_crtc->enabled)
return;

plane_helper_funcs->atomic_update(plane, new_state);
mtk_drm_crtc_hw_config(mtk_crtc);
}

static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
Expand Down Expand Up @@ -496,34 +571,14 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_drm_private *priv = crtc->dev->dev_private;
unsigned int pending_planes = 0;
int i;

if (mtk_crtc->event)
mtk_crtc->pending_needs_vblank = true;
for (i = 0; i < mtk_crtc->layer_nr; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
struct mtk_plane_state *plane_state;

plane_state = to_mtk_plane_state(plane->state);
if (plane_state->pending.dirty) {
plane_state->pending.config = true;
plane_state->pending.dirty = false;
pending_planes |= BIT(i);
}
}
if (pending_planes)
mtk_crtc->pending_planes = true;
if (crtc->state->color_mgmt_changed)
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);

if (priv->data->shadow_register) {
mtk_disp_mutex_acquire(mtk_crtc->mutex);
mtk_crtc_ddp_config(crtc);
mtk_disp_mutex_release(mtk_crtc->mutex);
}
mtk_drm_crtc_hw_config(mtk_crtc);
}

static const struct drm_crtc_funcs mtk_crtc_funcs = {
Expand Down Expand Up @@ -714,6 +769,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE);
drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE);
priv->num_pipes++;
mutex_init(&mtk_crtc->hw_lock);

return 0;
}
2 changes: 2 additions & 0 deletions drivers/gpu/drm/mediatek/mtk_drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
unsigned int path_len);
int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
struct mtk_plane_state *state);
void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
struct drm_plane_state *plane_state);

#endif /* MTK_DRM_CRTC_H */
47 changes: 47 additions & 0 deletions drivers/gpu/drm/mediatek/mtk_drm_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>

Expand Down Expand Up @@ -76,6 +77,50 @@ static void mtk_drm_plane_destroy_state(struct drm_plane *plane,
kfree(to_mtk_plane_state(state));
}

static int mtk_plane_atomic_async_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
struct drm_crtc_state *crtc_state;

if (plane != state->crtc->cursor)
return -EINVAL;

if (!plane->state)
return -EINVAL;

if (!plane->state->fb)
return -EINVAL;

if (state->state)
crtc_state = drm_atomic_get_existing_crtc_state(state->state,
state->crtc);
else /* Special case for asynchronous cursor updates. */
crtc_state = state->crtc->state;

return drm_atomic_helper_check_plane_state(plane->state, crtc_state,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
true, true);
}

static void mtk_plane_atomic_async_update(struct drm_plane *plane,
struct drm_plane_state *new_state)
{
struct mtk_plane_state *state = to_mtk_plane_state(plane->state);

plane->state->crtc_x = new_state->crtc_x;
plane->state->crtc_y = new_state->crtc_y;
plane->state->crtc_h = new_state->crtc_h;
plane->state->crtc_w = new_state->crtc_w;
plane->state->src_x = new_state->src_x;
plane->state->src_y = new_state->src_y;
plane->state->src_h = new_state->src_h;
plane->state->src_w = new_state->src_w;
state->pending.async_dirty = true;

mtk_drm_crtc_async_update(new_state->crtc, plane, new_state);
}

static const struct drm_plane_funcs mtk_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
Expand Down Expand Up @@ -164,6 +209,8 @@ static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
.atomic_check = mtk_plane_atomic_check,
.atomic_update = mtk_plane_atomic_update,
.atomic_disable = mtk_plane_atomic_disable,
.atomic_async_update = mtk_plane_atomic_async_update,
.atomic_async_check = mtk_plane_atomic_async_check,
};

int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/mediatek/mtk_drm_plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ struct mtk_plane_pending_state {
unsigned int height;
unsigned int rotation;
bool dirty;
bool async_dirty;
bool async_config;
};

struct mtk_plane_state {
Expand Down

0 comments on commit 920fffc

Please sign in to comment.