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

Commit 7731318d authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: add support for HDR10+"

parents a1617a1a 1c41480d
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -636,6 +636,18 @@ static int _sde_connector_update_dirty_properties(
	return 0;
}

struct sde_connector_dyn_hdr_metadata *sde_connector_get_dyn_hdr_meta(
		struct drm_connector *connector)
{
	struct sde_connector_state *c_state;

	if (!connector)
		return NULL;

	c_state = to_sde_connector_state(connector->state);
	return &c_state->dyn_hdr_meta;
}

int sde_connector_pre_kickoff(struct drm_connector *connector)
{
	struct sde_connector *c_conn;
@@ -927,6 +939,12 @@ sde_connector_atomic_duplicate_state(struct drm_connector *connector)
	if (c_state->out_fb)
		drm_framebuffer_get(c_state->out_fb);

	/* clear dynamic HDR metadata from prev state */
	if (c_state->dyn_hdr_meta.dynamic_hdr_update) {
		c_state->dyn_hdr_meta.dynamic_hdr_update = false;
		c_state->dyn_hdr_meta.dynamic_hdr_payload_size = 0;
	}

	return &c_state->base;
}

@@ -1069,6 +1087,8 @@ static int _sde_connector_set_ext_hdr_info(
	int rc = 0;
	struct drm_connector *connector;
	struct drm_msm_ext_hdr_metadata *hdr_meta;
	size_t payload_size = 0;
	u8 *payload = NULL;
	int i;

	if (!c_conn || !c_state) {
@@ -1102,6 +1122,37 @@ static int _sde_connector_set_ext_hdr_info(

	hdr_meta = &c_state->hdr_meta;

	/* dynamic metadata support */
	if (!hdr_meta->hdr_plus_payload_size || !hdr_meta->hdr_plus_payload)
		goto skip_dhdr;

	if (!connector->hdr_plus_app_ver) {
		SDE_ERROR_CONN(c_conn, "sink doesn't support dynamic HDR\n");
		rc = -ENOTSUPP;
		goto end;
	}

	payload_size = hdr_meta->hdr_plus_payload_size;
	if (payload_size > sizeof(c_state->dyn_hdr_meta.dynamic_hdr_payload)) {
		SDE_ERROR_CONN(c_conn, "payload size exceeds limit\n");
		rc = -EINVAL;
		goto end;
	}

	payload = c_state->dyn_hdr_meta.dynamic_hdr_payload;
	if (copy_from_user(payload,
			(void __user *)c_state->hdr_meta.hdr_plus_payload,
			payload_size)) {
		SDE_ERROR_CONN(c_conn, "failed to copy dhdr metadata\n");
		rc = -EFAULT;
		goto end;
	}

	c_state->dyn_hdr_meta.dynamic_hdr_update = true;

skip_dhdr:
	c_state->dyn_hdr_meta.dynamic_hdr_payload_size = payload_size;

	SDE_DEBUG_CONN(c_conn, "hdr_state %d\n", hdr_meta->hdr_state);
	SDE_DEBUG_CONN(c_conn, "hdr_supported %d\n", hdr_meta->hdr_supported);
	SDE_DEBUG_CONN(c_conn, "eotf %d\n", hdr_meta->eotf);
@@ -1119,6 +1170,9 @@ static int _sde_connector_set_ext_hdr_info(
		SDE_DEBUG_CONN(c_conn, "display_primaries_y [%d]\n",
				   hdr_meta->display_primaries_y[i]);
	}
	SDE_DEBUG_CONN(c_conn, "hdr_plus payload%s updated, size %d\n",
			c_state->dyn_hdr_meta.dynamic_hdr_update ? "" : " NOT",
			c_state->dyn_hdr_meta.dynamic_hdr_payload_size);

end:
	return rc;
@@ -1335,6 +1389,7 @@ static void sde_connector_update_hdr_props(struct drm_connector *connector)
		connector->hdr_max_luminance,
		connector->hdr_avg_luminance,
		connector->hdr_min_luminance,
		connector->hdr_plus_app_ver,
	};

	msm_property_set_blob(&c_conn->property_info, &c_conn->blob_ext_hdr,
+19 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "sde_fence.h"

#define SDE_CONNECTOR_NAME_SIZE	16
#define SDE_CONNECTOR_DHDR_MEMPOOL_MAX_SIZE	SZ_2K

struct sde_connector;
struct sde_connector_state;
@@ -330,6 +331,12 @@ struct sde_connector_evt {
	void *usr;
};

struct sde_connector_dyn_hdr_metadata {
	u8 dynamic_hdr_payload[SDE_CONNECTOR_DHDR_MEMPOOL_MAX_SIZE];
	int dynamic_hdr_payload_size;
	bool dynamic_hdr_update;
};

/**
 * struct sde_connector - local sde connector structure
 * @base: Base drm connector structure
@@ -372,6 +379,7 @@ struct sde_connector_evt {
 * @qsync_updated: Qsync settings were updated
 * last_cmd_tx_sts: status of the last command transfer
 * @hdr_capable: external hdr support present
 * @core_clk_rate: MDP core clk rate used for dynamic HDR packet calculation
 */
struct sde_connector {
	struct drm_connector base;
@@ -491,6 +499,7 @@ struct sde_connector {
 * @property_blobs: blob properties
 * @mode_info: local copy of msm_mode_info struct
 * @hdr_meta: HDR metadata info passed from userspace
 * @dyn_hdr_meta: Dynamic HDR metadata payload and state tracking
 * @old_topology_name: topology of previous atomic state. remove this in later
 *	kernel versions which provide drm_atomic_state old_state pointers
 */
@@ -504,6 +513,7 @@ struct sde_connector_state {
	struct drm_property_blob *property_blobs[CONNECTOR_PROP_BLOBCOUNT];
	struct msm_mode_info mode_info;
	struct drm_msm_ext_hdr_metadata hdr_meta;
	struct sde_connector_dyn_hdr_metadata dyn_hdr_meta;
	enum sde_rm_topology_name old_topology_name;
};

@@ -697,6 +707,15 @@ int sde_connector_get_dpms(struct drm_connector *connector);
 */
void sde_connector_set_qsync_params(struct drm_connector *connector);

/**
* sde_connector_get_dyn_hdr_meta - returns pointer to connector state's dynamic
*				   HDR metadata info
* @connector: pointer to drm connector
*/

struct sde_connector_dyn_hdr_metadata *sde_connector_get_dyn_hdr_meta(
		struct drm_connector *connector);

/**
 * sde_connector_trigger_event - indicate that an event has occurred
 *	Any callbacks that have been registered against this event will
+1 −0
Original line number Diff line number Diff line
@@ -4988,6 +4988,7 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,

	sde_kms_info_add_keyint(info, "has_src_split", catalog->has_src_split);
	sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr);
	sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus);
	if (catalog->perf.max_bw_low)
		sde_kms_info_add_keyint(info, "max_bandwidth_low",
				catalog->perf.max_bw_low * 1000LL);
+42 −6
Original line number Diff line number Diff line
@@ -214,6 +214,7 @@ enum sde_enc_rc_states {
 * @idle_pc_restore:		flag to indicate idle_pc_restore happened
 * @frame_trigger_mode:		frame trigger mode indication for command
 *				mode display
 * @dynamic_hdr_updated:	flag to indicate if mempool was programmed
 * @rsc_config:			rsc configuration for display vtotal, fps, etc.
 * @cur_conn_roi:		current connector roi
 * @prv_conn_roi:		previous connector roi to optimize if unchanged
@@ -271,6 +272,7 @@ struct sde_encoder_virt {
	bool vblank_enabled;
	bool idle_pc_restore;
	enum frame_trigger_mode_type frame_trigger_mode;
	bool dynamic_hdr_updated;

	struct sde_rsc_cmd_config rsc_config;
	struct sde_rect cur_conn_roi;
@@ -3775,13 +3777,20 @@ static inline void _sde_encoder_trigger_flush(struct drm_encoder *drm_enc,

	pend_ret_fence_cnt = atomic_read(&phys->pending_retire_fence_cnt);

	/* perform peripheral flush on every frame update for dp dsc */
	if (phys->hw_intf && phys->hw_intf->cap->type == INTF_DP &&
			phys->comp_type == MSM_DISPLAY_COMPRESSION_DSC &&
			phys->comp_ratio && ctl->ops.update_bitmask_periph &&
			c_conn->ops.update_pps) {
		c_conn->ops.update_pps(phys->connector, NULL, c_conn->display);
		ctl->ops.update_bitmask_periph(ctl, phys->hw_intf->idx, 1);
			ctl->ops.update_bitmask_periph) {
		/* perform peripheral flush on every frame update for dp dsc */
		if (phys->comp_type == MSM_DISPLAY_COMPRESSION_DSC &&
				phys->comp_ratio && c_conn->ops.update_pps) {
			c_conn->ops.update_pps(phys->connector, NULL,
					c_conn->display);
			ctl->ops.update_bitmask_periph(ctl,
					phys->hw_intf->idx, 1);
		}

		if (sde_enc->dynamic_hdr_updated)
			ctl->ops.update_bitmask_periph(ctl,
					phys->hw_intf->idx, 1);
	}

	if ((extra_flush && extra_flush->pending_flush_mask)
@@ -4603,6 +4612,31 @@ static void _helper_flush_dsc(struct sde_encoder_virt *sde_enc)
		sde_enc->dirty_dsc_ids[i] = DSC_NONE;
	}
}
static void _sde_encoder_helper_hdr_plus_mempool_update(
		struct sde_encoder_virt *sde_enc)
{
	struct sde_connector_dyn_hdr_metadata *dhdr_meta = NULL;
	struct sde_hw_mdp *mdptop = NULL;

	sde_enc->dynamic_hdr_updated = false;
	if (sde_enc->cur_master) {
		mdptop = sde_enc->cur_master->hw_mdptop;
		dhdr_meta = sde_connector_get_dyn_hdr_meta(
				sde_enc->cur_master->connector);
	}

	if (!mdptop || !dhdr_meta || !dhdr_meta->dynamic_hdr_update)
		return;

	if (mdptop->ops.set_hdr_plus_metadata) {
		sde_enc->dynamic_hdr_updated = true;
		mdptop->ops.set_hdr_plus_metadata(
				mdptop, dhdr_meta->dynamic_hdr_payload,
				dhdr_meta->dynamic_hdr_payload_size,
				sde_enc->cur_master->intf_idx == INTF_0 ?
				0 : 1);
	}
}

static void _sde_encoder_needs_hw_reset(struct drm_encoder *drm_enc,
	int ln_cnt1)
@@ -4668,6 +4702,8 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
			sde_enc->cur_master->connector->state,
			CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE);

	_sde_encoder_helper_hdr_plus_mempool_update(sde_enc);

	/* prepare for next kickoff, may include waiting on previous kickoff */
	SDE_ATRACE_BEGIN("sde_encoder_prepare_for_kickoff");
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
+4 −0
Original line number Diff line number Diff line
@@ -3753,6 +3753,8 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->has_wb_ubwc = true;
		sde_cfg->has_qsync = true;
		sde_cfg->has_hdr = true;
		sde_cfg->has_hdr_plus = true;
		set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features);
		sde_cfg->has_vig_p010 = true;
		sde_cfg->perf.min_prefill_lines = 24;
		sde_cfg->vbif_qos_nlvl = 8;
@@ -3824,6 +3826,8 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_hdr = true;
		sde_cfg->has_hdr_plus = true;
		set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features);
		sde_cfg->has_vig_p010 = true;
		sde_cfg->true_inline_rot_rev = SDE_INLINE_ROT_VERSION_1_0_0;
		sde_cfg->true_inline_dwnscale_rt =
Loading