@@ -622,6 +622,63 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
* CRTC Functions
*/
+static bool rcar_du_crtc_is_ctm_updated(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ return (state->color_mgmt_changed && state->ctm &&
+ crtc->state->ctm &&
+ (crtc->state->ctm->base.id != state->ctm->base.id));
+}
+
+static bool rcar_du_crtc_is_gamma_updated(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ return (state->color_mgmt_changed && state->gamma_lut &&
+ crtc->state->gamma_lut &&
+ (crtc->state->gamma_lut->base.id != state->gamma_lut->base.id));
+}
+
+static int rcar_du_crtc_cmm_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ int ret = 0;
+ struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+
+ /*Check gamma update and allocate memory*/
+ if (rcar_du_crtc_is_gamma_updated(crtc, state) &&
+ !rcrtc->lut_handle) {
+ ret = rcar_du_cmm_lut_valid((crtc->state->gamma_lut->length /
+ sizeof(struct drm_color_lut)));
+ if (ret >= 0) {
+ rcrtc->lut_handle =
+ rcar_du_cmm_alloc_lut(rcrtc->cmm_handle);
+ if (!rcrtc->lut_handle)
+ ret = -ENOMEM;
+ }
+ }
+
+ /*Check update of ctm and allocate memory*/
+ if (ret >= 0 && rcar_du_crtc_is_ctm_updated(crtc, state) &&
+ !rcrtc->clu_handle) {
+ rcrtc->clu_handle = rcar_du_cmm_alloc_clu(rcrtc->cmm_handle);
+ if (!rcrtc->clu_handle) {
+ if (!rcrtc->lut_handle) {
+ rcar_du_cmm_free_lut(rcrtc->lut_handle);
+ rcrtc->lut_handle = NULL;
+ }
+ ret = -ENOMEM;
+ }
+ }
+
+ return ret;
+}
+
+static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ return rcar_du_crtc_cmm_atomic_check(crtc, state);
+}
+
static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
@@ -708,6 +765,7 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.atomic_flush = rcar_du_crtc_atomic_flush,
.atomic_enable = rcar_du_crtc_atomic_enable,
.atomic_disable = rcar_du_crtc_atomic_disable,
+ .atomic_check = rcar_du_crtc_atomic_check,
};
static struct drm_crtc_state *
@@ -70,7 +70,8 @@ struct rcar_du_crtc {
int lvds_ch;
void *cmm_handle;
-
+ void *lut_handle;
+ void *clu_handle;
};
#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)