// SPDX-License-Identifier: GPL-2.0
/*
* (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
* Author: James.Qian.Wang <james.qian.wang@arm.com>
*
*/
#include <drm/drm_print.h>
#include <linux/clk.h>
#include "komeda_dev.h"
#include "komeda_kms.h"
#include "komeda_pipeline.h"
#include "komeda_framebuffer.h"
static inline bool is_switching_user(void *old, void *new)
{
if (!old || !new)
return false;
return old != new;
}
static struct komeda_pipeline_state *
komeda_pipeline_get_state(struct komeda_pipeline *pipe,
struct drm_atomic_state *state)
{
struct drm_private_state *priv_st;
priv_st = drm_atomic_get_private_obj_state(state, &pipe->obj);
if (IS_ERR(priv_st))
return ERR_CAST(priv_st);
return priv_to_pipe_st(priv_st);
}
struct komeda_pipeline_state *
komeda_pipeline_get_old_state(struct komeda_pipeline *pipe,
struct drm_atomic_state *state)
{
struct drm_private_state *priv_st;
priv_st = drm_atomic_get_old_private_obj_state(state, &pipe->obj);
if (priv_st)
return priv_to_pipe_st(priv_st);
return NULL;
}
static struct komeda_pipeline_state *
komeda_pipeline_get_new_state(struct komeda_pipeline *pipe,
struct drm_atomic_state *state)
{
struct drm_private_state *priv_st;
priv_st = drm_atomic_get_new_private_obj_state(state, &pipe->obj);
if (priv_st)
return priv_to_pipe_st(priv_st);
return NULL;
}
/* Assign pipeline for crtc */
static struct komeda_pipeline_state *
komeda_pipeline_get_state_and_set_crtc(struct komeda_pipeline *pipe,
struct drm_atomic_state *state,
struct drm_crtc *crtc)
{
struct komeda_pipeline_state *st;
st = komeda_pipeline_get_state(pipe, state);
if (IS_ERR(st))
return st;
if (is_switching_user(crtc, st->crtc)) {
DRM_DEBUG_ATOMIC("CRTC%d required pipeline%d is busy.\n",
drm_crtc_index(crtc), pipe->id);
return ERR_PTR(-EBUSY);
}
/* pipeline only can be disabled when the it is free or unused */
if (!crtc && st->active_comps) {
DRM_DEBUG_ATOMIC("Disabling a busy pipeline:%d.\n", pipe->id);
return ERR_PTR(-EBUSY);
}
st->crtc = crtc;
if (crtc) {
struct komeda_crtc_state *kcrtc_st;
kcrtc_st = to_kcrtc_st(drm_atomic_get_new_crtc_state(state,
crtc));
kcrtc_st->active_pipes |= BIT(pipe->id);
kcrtc_st->affected_pipes |= BIT(pipe->id);
}
return st;
}
static struct komeda_component_state *
komeda_component_get_state(struct komeda_component *c,
struct drm_atomic_state *state)
{
struct drm_private_state *priv_st;
WARN_ON(!drm_modeset_is_locked(&c->pipeline->obj.lock));
priv_st = drm_atomic_get_priv