Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6954f245 authored by Mihail Atanassov's avatar Mihail Atanassov Committed by Liviu Dudau
Browse files

drm: mali-dp: Add CTM support



All DPs have a COLORADJ matrix which is applied prior to output gamma.
Attach that to the CTM property. Also, ensure the input CTM's coefficients
can fit in the DP registers' Q3.12 format.

Signed-off-by: default avatarMihail Atanassov <mihail.atanassov@arm.com>
Signed-off-by: default avatarLiviu Dudau <Liviu.Dudau@arm.com>
parent 02725d31
Loading
Loading
Loading
Loading
+61 −3
Original line number Diff line number Diff line
@@ -195,6 +195,58 @@ static int malidp_crtc_atomic_check_gamma(struct drm_crtc *crtc,
	return 0;
}

/*
 * Check if there is a new CTM and if it contains valid input. Valid here means
 * that the number is inside the representable range for a Q3.12 number,
 * excluding truncating the fractional part of the input data.
 *
 * The COLORADJ registers can be changed atomically.
 */
static int malidp_crtc_atomic_check_ctm(struct drm_crtc *crtc,
					struct drm_crtc_state *state)
{
	struct malidp_crtc_state *mc = to_malidp_crtc_state(state);
	struct drm_color_ctm *ctm;
	int i;

	if (!state->color_mgmt_changed)
		return 0;

	if (!state->ctm)
		return 0;

	if (crtc->state->ctm && (crtc->state->ctm->base.id ==
				 state->ctm->base.id))
		return 0;

	/*
	 * The size of the ctm is checked in
	 * drm_atomic_replace_property_blob_from_id.
	 */
	ctm = (struct drm_color_ctm *)state->ctm->data;
	for (i = 0; i < ARRAY_SIZE(ctm->matrix); ++i) {
		/* Convert from S31.32 to Q3.12. */
		s64 val = ctm->matrix[i];
		u32 mag = ((((u64)val) & ~BIT_ULL(63)) >> 20) &
			  GENMASK_ULL(14, 0);

		/*
		 * Convert to 2s complement and check the destination's top bit
		 * for overflow. NB: Can't check before converting or it'd
		 * incorrectly reject the case:
		 * sign == 1
		 * mag == 0x2000
		 */
		if (val & BIT_ULL(63))
			mag = ~mag + 1;
		if (!!(val & BIT_ULL(63)) != !!(mag & BIT(14)))
			return -EINVAL;
		mc->coloradj_coeffs[i] = mag;
	}

	return 0;
}

static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
				    struct drm_crtc_state *state)
{
@@ -204,6 +256,7 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
	const struct drm_plane_state *pstate;
	u32 rot_mem_free, rot_mem_usable;
	int rotated_planes = 0;
	int ret;

	/*
	 * check if there is enough rotation memory available for planes
@@ -270,7 +323,10 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
		}
	}

	return malidp_crtc_atomic_check_gamma(crtc, state);
	ret = malidp_crtc_atomic_check_gamma(crtc, state);
	ret = ret ? ret : malidp_crtc_atomic_check_ctm(crtc, state);

	return ret;
}

static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = {
@@ -295,6 +351,8 @@ static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc *crtc)
	__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
	memcpy(state->gamma_coeffs, old_state->gamma_coeffs,
	       sizeof(state->gamma_coeffs));
	memcpy(state->coloradj_coeffs, old_state->coloradj_coeffs,
	       sizeof(state->coloradj_coeffs));

	return &state->base;
}
@@ -392,8 +450,8 @@ int malidp_crtc_init(struct drm_device *drm)

	drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs);
	drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE);
	/* No inverse-gamma and color adjustments yet. */
	drm_crtc_enable_color_mgmt(&malidp->crtc, 0, false, MALIDP_GAMMA_LUT_SIZE);
	/* No inverse-gamma: it is per-plane */
	drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE);

	return 0;

+34 −1
Original line number Diff line number Diff line
@@ -79,6 +79,37 @@ static void malidp_atomic_commit_update_gamma(struct drm_crtc *crtc,
	}
}

static
void malidp_atomic_commit_update_coloradj(struct drm_crtc *crtc,
					  struct drm_crtc_state *old_state)
{
	struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
	struct malidp_hw_device *hwdev = malidp->dev;
	int i;

	if (!crtc->state->color_mgmt_changed)
		return;

	if (!crtc->state->ctm) {
		malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_CADJ,
				    MALIDP_DE_DISPLAY_FUNC);
	} else {
		struct malidp_crtc_state *mc =
			to_malidp_crtc_state(crtc->state);

		if (!old_state->ctm || (crtc->state->ctm->base.id !=
					old_state->ctm->base.id))
			for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; ++i)
				malidp_hw_write(hwdev,
						mc->coloradj_coeffs[i],
						hwdev->map.coeffs_base +
						MALIDP_COLOR_ADJ_COEF + 4 * i);

		malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_CADJ,
				  MALIDP_DE_DISPLAY_FUNC);
	}
}

/*
 * set the "config valid" bit and wait until the hardware acts on it
 */
@@ -145,8 +176,10 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state)

	drm_atomic_helper_commit_modeset_disables(drm, state);

	for_each_crtc_in_state(state, crtc, old_crtc_state, i)
	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
		malidp_atomic_commit_update_gamma(crtc, old_crtc_state);
		malidp_atomic_commit_update_coloradj(crtc, old_crtc_state);
	}

	drm_atomic_helper_commit_planes(drm, state, 0);

+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ struct malidp_plane_state {
struct malidp_crtc_state {
	struct drm_crtc_state base;
	u32 gamma_coeffs[MALIDP_COEFFTAB_NUM_COEFFS];
	u32 coloradj_coeffs[MALIDP_COLORADJ_NUM_COEFFS];
};

#define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base)
+1 −0
Original line number Diff line number Diff line
@@ -259,6 +259,7 @@ static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev,
#define MALIDP_BGND_COLOR_G		0x000
#define MALIDP_BGND_COLOR_B		0x000

#define MALIDP_COLORADJ_NUM_COEFFS	12
#define MALIDP_COEFFTAB_NUM_COEFFS	64

#define MALIDP_GAMMA_LUT_SIZE		4096
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@
/* bit masks that are common between products */
#define   MALIDP_CFG_VALID		(1 << 0)
#define   MALIDP_DISP_FUNC_GAMMA	(1 << 0)
#define   MALIDP_DISP_FUNC_CADJ		(1 << 4)
#define   MALIDP_DISP_FUNC_ILACED	(1 << 8)

/* register offsets for IRQ management */