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

Commit 4966145a authored by Benet Clark's avatar Benet Clark
Browse files

msm: mdss: Add atomic commit PP support



This change adds support for SSPP postprocessing using the
atomic commit ioctl. The configuration given as part of the
ioctl will be cached in the same pipe res as before, and the
register programming sequence will be called from the pipe
setup as before.

Change-Id: Ida8209f80e55e9d5009b5df4e55f787b4a85ddc0
Signed-off-by: default avatarBenet Clark <benetc@codeaurora.org>
parent 6702b4a9
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -3826,6 +3826,17 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
		for (i = 0; i < layer_count; i++) {
			layer = &layer_list[i];

			if (!(layer->flags & MDP_LAYER_PP)) {
				layer->pp_info = NULL;
			} else {
				ret = mdss_mdp_copy_layer_pp_info(layer);
				if (ret) {
					pr_err("failure to copy pp_info data for layer %d, ret = %d\n",
						i, ret);
					goto err;
				}
			}

			if (!(layer->flags & MDP_LAYER_ENABLE_PIXEL_EXT)) {
				layer->scale = NULL;
				continue;
@@ -3842,8 +3853,10 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
			ret = copy_from_user(scale, layer->scale,
					sizeof(struct mdp_scale_data));
			if (ret) {
				pr_err("layer list copy from user failed\n");
				pr_err("layer list copy from user failed, scale = %p\n",
						layer->scale);
				kfree(scale);
				ret = -EFAULT;
				goto err;
			}
			layer->scale = scale;
@@ -3871,8 +3884,10 @@ static int mdss_fb_atomic_commit_ioctl(struct fb_info *info,
	}

err:
	for (i--; i >= 0; i--)
	for (i--; i >= 0; i--) {
		kfree(layer_list[i].scale);
		mdss_mdp_free_layer_pp_info(&layer_list[i]);
	}
	kfree(layer_list);
	kfree(output_layer);

+2 −0
Original line number Diff line number Diff line
@@ -1084,6 +1084,8 @@ int mdss_mdp_pipe_pp_setup(struct mdss_mdp_pipe *pipe, u32 *op);
void mdss_mdp_pipe_pp_clear(struct mdss_mdp_pipe *pipe);
int mdss_mdp_pipe_sspp_setup(struct mdss_mdp_pipe *pipe, u32 *op);
int mdss_mdp_pp_sspp_config(struct mdss_mdp_pipe *pipe);
int mdss_mdp_copy_layer_pp_info(struct mdp_input_layer *layer);
void mdss_mdp_free_layer_pp_info(struct mdp_input_layer *layer);

int mdss_mdp_smp_setup(struct mdss_data_type *mdata, u32 cnt, u32 size);

+22 −0
Original line number Diff line number Diff line
@@ -441,6 +441,8 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
		pipe->flags |= MDP_DEINTERLACE;
	if (layer->flags & MDP_LAYER_BWC)
		pipe->flags |= MDP_BWC_EN;
	if (layer->flags & MDP_LAYER_PP)
		pipe->flags |= MDP_OVERLAY_PP_CFG_EN;

	pipe->scale.enable_pxl_ext = layer->flags & MDP_LAYER_ENABLE_PIXEL_EXT;
	pipe->is_fg = layer->flags & MDP_LAYER_FORGROUND;
@@ -583,6 +585,16 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
		goto end;
	}

	if (layer->flags & MDP_LAYER_PP) {
		memcpy(&pipe->pp_cfg, layer->pp_info,
				sizeof(struct mdp_overlay_pp_params));
		ret = mdss_mdp_pp_sspp_config(pipe);
		if (ret) {
			pr_err("pp setup failed %d\n", ret);
			goto end;
		}
	}

	if (pipe->type == MDSS_MDP_PIPE_TYPE_CURSOR)
		goto end;

@@ -1095,6 +1107,16 @@ static int __validate_layers(struct msm_fb_data_type *mfd,
				right_plist[right_cnt++] = pipe;
			else
				left_plist[left_cnt++] = pipe;

			if (layer->flags & MDP_LAYER_PP) {
				memcpy(&pipe->pp_cfg, layer->pp_info,
					sizeof(struct mdp_overlay_pp_params));
				ret = mdss_mdp_pp_sspp_config(pipe);
				if (ret)
					pr_err("pp setup failed %d\n", ret);
				else
					pipe->params_changed++;
			}
			continue;
		}

+89 −5
Original line number Diff line number Diff line
@@ -6031,9 +6031,10 @@ int mdss_mdp_pp_sspp_config(struct mdss_mdp_pipe *pipe)
	int ret = 0;

	if (!pipe) {
		pr_err("invalid params %p\n", pipe);
		pr_err("invalid params, pipe %p\n", pipe);
		return -EINVAL;
	}

	cache_res.mdss_pp_res = NULL;
	cache_res.pipe_res = pipe;
	ret = sspp_cache_location(pipe->type, &cache_res.block);
@@ -6042,8 +6043,8 @@ int mdss_mdp_pp_sspp_config(struct mdss_mdp_pipe *pipe)
			ret);
		goto exit_fail;
	}
	len = pipe->pp_cfg.igc_cfg.len;
	if ((pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_IGC_CFG)) {
		len = pipe->pp_cfg.igc_cfg.len;
		if (pp_ops[IGC].pp_set_config) {
			ret = pp_igc_lut_cache_params(&pipe->pp_cfg.igc_cfg,
						      &cache_res, false);
@@ -6106,9 +6107,6 @@ int mdss_mdp_pp_sspp_config(struct mdss_mdp_pipe *pipe)
			}
			pipe->pp_cfg.hist_lut_cfg.data = pipe->pp_res.hist_lut;
		} else {
			cache_res.block = SSPP_VIG;
			cache_res.mdss_pp_res = NULL;
			cache_res.pipe_res = pipe;
			ret = pp_hist_lut_cache_params(
					&pipe->pp_cfg.hist_lut_cfg,
					&cache_res);
@@ -6280,3 +6278,89 @@ static void mdss_mdp_hist_intr_notify(u32 disp)
	mdp5_data->hist_events++;
	sysfs_notify_dirent(mdp5_data->hist_event_sd);
}

int mdss_mdp_copy_layer_pp_info(struct mdp_input_layer *layer)
{
	struct mdp_overlay_pp_params *pp_info = NULL;
	int ret = 0;
	uint32_t ops;

	if (!layer) {
		pr_err("invalid layer pointer passed %p\n", layer);
		return -EFAULT;
	}

	pp_info = kmalloc(sizeof(struct mdp_overlay_pp_params),
			GFP_KERNEL);
	if (!pp_info)
		return -ENOMEM;

	ret = copy_from_user(pp_info, layer->pp_info,
			sizeof(struct mdp_overlay_pp_params));
	if (ret) {
		pr_err("layer list copy from user failed, pp_info = %p\n",
			layer->pp_info);
		ret = -EFAULT;
		goto exit_pp_info;
	}

	ops = pp_info->config_ops;
	if (ops & MDP_OVERLAY_PP_IGC_CFG) {
		ret = pp_copy_layer_igc_payload(pp_info);
		if (ret) {
			pr_err("Failed to copy IGC payload, ret = %d\n", ret);
			goto exit_pp_info;
		}
	}
	if (ops & MDP_OVERLAY_PP_HIST_LUT_CFG) {
		ret = pp_copy_layer_hist_lut_payload(pp_info);
		if (ret) {
			pr_err("Failed to copy Hist LUT payload, ret = %d\n",
				ret);
			goto exit_igc;
		}
	}
	if (ops & MDP_OVERLAY_PP_PA_V2_CFG) {
		ret = pp_copy_layer_pa_payload(pp_info);
		if (ret) {
			pr_err("Failed to copy PA payload, ret = %d\n", ret);
			goto exit_hist_lut;
		}
	}
	if (ops & MDP_OVERLAY_PP_PCC_CFG) {
		ret = pp_copy_layer_pcc_payload(pp_info);
		if (ret) {
			pr_err("Failed to copy PCC payload, ret = %d\n", ret);
			goto exit_pa;
		}
	}

	layer->pp_info = pp_info;

	return ret;

exit_pa:
	kfree(pp_info->pa_v2_cfg_data.cfg_payload);
exit_hist_lut:
	kfree(pp_info->hist_lut_cfg.cfg_payload);
exit_igc:
	kfree(pp_info->igc_cfg.cfg_payload);
exit_pp_info:
	kfree(pp_info);
	return ret;
}

void mdss_mdp_free_layer_pp_info(struct mdp_input_layer *layer)
{
	struct mdp_overlay_pp_params *pp_info =
		(struct mdp_overlay_pp_params *) layer->pp_info;

	if (!pp_info)
		return;

	kfree(pp_info->igc_cfg.cfg_payload);
	kfree(pp_info->hist_lut_cfg.cfg_payload);
	kfree(pp_info->pa_v2_cfg_data.cfg_payload);
	kfree(pp_info->pcc_cfg_data.cfg_payload);
	kfree(pp_info);
}
+254 −115
Original line number Diff line number Diff line
@@ -157,14 +157,14 @@ static int pp_hist_lut_cache_params_pipe_v1_7(struct mdp_hist_lut_data *config,
		return -EINVAL;
	}

	if (copy_from_user(&hist_lut_usr_config,
			   config->cfg_payload,
			   sizeof(struct mdp_hist_lut_data_v1_7))) {
		pr_err("Failed to copy usr cfg_payload\n");
		ret = -EFAULT;
		goto hist_lut_cache_pipe_exit;
	if (!config->cfg_payload) {
		pr_err("Hist LUT config payload invalid\n");
		return -EINVAL;
	}

	memcpy(&hist_lut_usr_config, config->cfg_payload,
		sizeof(struct mdp_hist_lut_data_v1_7));

	hist_lut_cache_data = pipe->pp_res.hist_lut_cfg_payload;
	if (!hist_lut_cache_data) {
		hist_lut_cache_data = kzalloc(
@@ -544,17 +544,20 @@ static int pp_pcc_cache_params_pipe_v1_7(struct mdp_pcc_cfg_data *config,
		pr_debug("disable ops set cleanup payload\n");
		goto cleanup;
	}
	if (copy_from_user(&v17_usr_config, config->cfg_payload,
			   sizeof(v17_usr_config))) {
		pr_err("failed to copy v17 pcc\n");
		return -EFAULT;
	}

	if (config->ops & MDP_PP_OPS_READ) {
		pr_err("read ops not supported\n");
		return -EINVAL;
	}

	if (!config->cfg_payload) {
		pr_err("PCC config payload invalid\n");
		return -EINVAL;
	}

	memcpy(&v17_usr_config, config->cfg_payload,
			sizeof(v17_usr_config));

	if (!(config->ops & MDP_PP_OPS_WRITE)) {
		pr_debug("write ops not set value of flag is %d\n",
			config->ops);
@@ -799,40 +802,27 @@ static int pp_igc_lut_cache_params_pipe_v1_7(struct mdp_igc_lut_data *config,
	if (config->ops & MDP_PP_OPS_READ) {
		pr_err("read op is not supported\n");
		return -EINVAL;
	} else {
		if (!copy_from_kernel) {
			if (copy_from_user(&v17_usr_config,
					   config->cfg_payload,
					   sizeof(v17_usr_config))) {
				pr_err("failed to copy igc config\n");
				ret = -EFAULT;
				goto igc_config_exit;
	}
		} else {

	if (!config->cfg_payload) {
		pr_err("can't copy config info NULL payload\n");
		ret = -EINVAL;
		goto igc_config_exit;
	}

	memcpy(&v17_usr_config, config->cfg_payload,
			sizeof(v17_usr_config));
		}

	if (!(config->ops & MDP_PP_OPS_WRITE)) {
		pr_debug("op for gamut %d\n", config->ops);
		goto igc_config_exit;
	}
		if (v17_usr_config.table_fmt < mdp_igc_rec601 ||
		    v17_usr_config.table_fmt >= mdp_igc_vmax) {
			pr_err("incorrect igc version %d",
				v17_usr_config.table_fmt);
			ret = -EINVAL;
			goto igc_config_exit;
		}

	switch (v17_usr_config.table_fmt) {
	case mdp_igc_custom:
		if (!v17_usr_config.c0_c1_data ||
			    !v17_usr_config.c2_data || v17_usr_config.len !=
			    IGC_LUT_ENTRIES) {
		    !v17_usr_config.c2_data ||
		    v17_usr_config.len != IGC_LUT_ENTRIES) {
			pr_err("invalid c0_c1data %p c2_data %p tbl len %d\n",
					v17_usr_config.c0_c1_data,
					v17_usr_config.c2_data,
@@ -863,11 +853,9 @@ static int pp_igc_lut_cache_params_pipe_v1_7(struct mdp_igc_lut_data *config,
	}
	v17_cache_data = pipe->pp_res.igc_cfg_payload;
	if (!v17_cache_data)
			v17_cache_data = kzalloc(sizeof(
						 struct mdp_igc_lut_data_v1_7),
		v17_cache_data = kzalloc(sizeof(struct mdp_igc_lut_data_v1_7),
					GFP_KERNEL);
	if (!v17_cache_data) {
			pr_err("failed to allocate cache data\n");
		ret = -ENOMEM;
		goto igc_config_exit;
	} else {
@@ -907,7 +895,6 @@ static int pp_igc_lut_cache_params_pipe_v1_7(struct mdp_igc_lut_data *config,
			ret = -EFAULT;
		}
	}
	}
igc_config_exit:
	if (ret || (config->ops & MDP_PP_OPS_DISABLE)) {
		kfree(v17_cache_data);
@@ -1203,14 +1190,14 @@ static int pp_pa_cache_params_pipe_v1_7(struct mdp_pa_v2_cfg_data *config,
		return -EINVAL;
	}

	if (copy_from_user(&pa_usr_config,
			   config->cfg_payload,
			   sizeof(struct mdp_pa_data_v1_7))) {
		ret = -EFAULT;
		pr_err("Failed to copy pa usr cfg_payload\n");
		goto pa_cache_pipe_exit;
	if (!config->cfg_payload) {
		pr_err("invalid PA config payload\n");
		return -EINVAL;
	}

	memcpy(&pa_usr_config, config->cfg_payload,
			sizeof(struct mdp_pa_data_v1_7));

	pa_cache_data = pipe->pp_res.pa_cfg_payload;
	if (!pa_cache_data) {
		pa_cache_data = kzalloc(sizeof(struct mdp_pa_data_v1_7),
@@ -1284,3 +1271,155 @@ int pp_pa_cache_params(struct mdp_pa_v2_cfg_data *config,
	}
	return ret;
}

int pp_copy_layer_igc_payload(struct mdp_overlay_pp_params *pp_info)
{
	void *cfg_payload = NULL;
	int ret = 0;

	switch (pp_info->igc_cfg.version) {
	case mdp_igc_v1_7:
		cfg_payload = kmalloc(
				sizeof(struct mdp_igc_lut_data_v1_7),
				GFP_KERNEL);
		if (!cfg_payload) {
			ret = -ENOMEM;
			goto exit;
		}

		ret = copy_from_user(cfg_payload,
				pp_info->igc_cfg.cfg_payload,
				sizeof(struct mdp_igc_lut_data_v1_7));
		if (ret) {
			pr_err("layer list copy from user failed, IGC cfg payload = %p\n",
				pp_info->igc_cfg.cfg_payload);
			ret = -EFAULT;
			kfree(cfg_payload);
			cfg_payload = NULL;
			goto exit;
		}
		break;
	default:
		pr_debug("No version set, fallback to legacy IGC version\n");
		cfg_payload = NULL;
		break;
	}

exit:
	pp_info->igc_cfg.cfg_payload = cfg_payload;
	return ret;
}

int pp_copy_layer_hist_lut_payload(struct mdp_overlay_pp_params *pp_info)
{
	void *cfg_payload = NULL;
	int ret = 0;

	switch (pp_info->hist_lut_cfg.version) {
	case mdp_hist_lut_v1_7:
		cfg_payload = kmalloc(
				sizeof(struct mdp_hist_lut_data_v1_7),
				GFP_KERNEL);
		if (!cfg_payload) {
			ret = -ENOMEM;
			goto exit;
		}

		ret = copy_from_user(cfg_payload,
				pp_info->hist_lut_cfg.cfg_payload,
				sizeof(struct mdp_hist_lut_data_v1_7));
		if (ret) {
			pr_err("layer list copy from user failed, Hist LUT cfg payload = %p\n",
				pp_info->hist_lut_cfg.cfg_payload);
			ret = -EFAULT;
			kfree(cfg_payload);
			cfg_payload = NULL;
			goto exit;
		}
		break;
	default:
		pr_debug("No version set, fallback to legacy Hist LUT version\n");
		cfg_payload = NULL;
		break;
	}

exit:
	pp_info->hist_lut_cfg.cfg_payload = cfg_payload;
	return ret;
}

int pp_copy_layer_pa_payload(struct mdp_overlay_pp_params *pp_info)
{
	void *cfg_payload = NULL;
	int ret = 0;

	switch (pp_info->pa_v2_cfg_data.version) {
	case mdp_pa_v1_7:
		cfg_payload = kmalloc(
				sizeof(struct mdp_pa_data_v1_7),
				GFP_KERNEL);
		if (!cfg_payload) {
			ret = -ENOMEM;
			goto exit;
		}

		ret = copy_from_user(cfg_payload,
				pp_info->pa_v2_cfg_data.cfg_payload,
				sizeof(struct mdp_pa_data_v1_7));
		if (ret) {
			pr_err("layer list copy from user failed, PA cfg payload = %p\n",
				pp_info->pa_v2_cfg_data.cfg_payload);
			ret = -EFAULT;
			kfree(cfg_payload);
			cfg_payload = NULL;
			goto exit;
		}
		break;
	default:
		pr_debug("No version set, fallback to legacy PA version\n");
		cfg_payload = NULL;
		break;
	}

exit:
	pp_info->pa_v2_cfg_data.cfg_payload = cfg_payload;
	return ret;
}

int pp_copy_layer_pcc_payload(struct mdp_overlay_pp_params *pp_info)
{
	void *cfg_payload = NULL;
	int ret = 0;

	switch (pp_info->pcc_cfg_data.version) {
	case mdp_pcc_v1_7:
		cfg_payload = kmalloc(
				sizeof(struct mdp_pcc_data_v1_7),
				GFP_KERNEL);
		if (!cfg_payload) {
			ret = -ENOMEM;
			goto exit;
		}

		ret = copy_from_user(cfg_payload,
				pp_info->pcc_cfg_data.cfg_payload,
				sizeof(struct mdp_pcc_data_v1_7));
		if (ret) {
			pr_err("layer list copy from user failed, PCC cfg payload = %p\n",
				pp_info->pcc_cfg_data.cfg_payload);
			ret = -EFAULT;
			kfree(cfg_payload);
			cfg_payload = NULL;
			goto exit;
		}
		break;
	default:
		pr_debug("No version set, fallback to legacy PCC version\n");
		cfg_payload = NULL;
		break;
	}

exit:
	pp_info->pcc_cfg_data.cfg_payload = cfg_payload;
	return ret;
}
Loading