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

Commit 59a06057 authored by Benjamin Chan's avatar Benjamin Chan Committed by Narendra Muppalla
Browse files

msm: sde: Provide better error logging in SDE rotator



During streamon, sde rotator needs to perform a final input and output
format validation. If the validation fails during streamon, it is better
to provide error logging. However, during V4L2 parameters setup phase,
the driver should not report error message because it is normal to have
invalid setting and client can retry with other setting. This change
will separate those two scenarios and only generate error logging
during streamon. Also add additional logging during rotator timeout
and VBIF registers dump in ramdump.

Change-Id: I938a46ba3fd967ba4ccddb923c001996fddba9eb
Signed-off-by: default avatarBenjamin Chan <bkchan@codeaurora.org>
Signed-off-by: default avatarNarendra Muppalla <NarendraM@codeaurora.org>
parent e7ca72e7
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -96,6 +96,7 @@ enum sde_bus_clients {
enum sde_rot_regdump_access {
enum sde_rot_regdump_access {
	SDE_ROT_REGDUMP_READ,
	SDE_ROT_REGDUMP_READ,
	SDE_ROT_REGDUMP_WRITE,
	SDE_ROT_REGDUMP_WRITE,
	SDE_ROT_REGDUMP_VBIF,
	SDE_ROT_REGDUMP_MAX
	SDE_ROT_REGDUMP_MAX
};
};


+121 −47
Original line number Original line Diff line number Diff line
@@ -1523,20 +1523,20 @@ static bool sde_rotator_verify_format(struct sde_rot_mgr *mgr,
	u8 out_v_subsample, out_h_subsample;
	u8 out_v_subsample, out_h_subsample;


	if (!sde_rotator_is_valid_pixfmt(mgr, in_fmt->format, true)) {
	if (!sde_rotator_is_valid_pixfmt(mgr, in_fmt->format, true)) {
		SDEROT_DBG("Invalid input format %x\n", in_fmt->format);
		SDEROT_ERR("Invalid input format %x\n", in_fmt->format);
		return false;
		goto verify_error;
	}
	}


	if (!sde_rotator_is_valid_pixfmt(mgr, out_fmt->format, false)) {
	if (!sde_rotator_is_valid_pixfmt(mgr, out_fmt->format, false)) {
		SDEROT_DBG("Invalid output format %x\n", out_fmt->format);
		SDEROT_ERR("Invalid output format %x\n", out_fmt->format);
		return false;
		goto verify_error;
	}
	}


	if ((in_fmt->is_yuv != out_fmt->is_yuv) ||
	if ((in_fmt->is_yuv != out_fmt->is_yuv) ||
		(in_fmt->pixel_mode != out_fmt->pixel_mode) ||
		(in_fmt->pixel_mode != out_fmt->pixel_mode) ||
		(in_fmt->unpack_tight != out_fmt->unpack_tight)) {
		(in_fmt->unpack_tight != out_fmt->unpack_tight)) {
		SDEROT_DBG("Rotator does not support CSC\n");
		SDEROT_ERR("Rotator does not support CSC\n");
		return false;
		goto verify_error;
	}
	}


	/* Forcing same pixel depth */
	/* Forcing same pixel depth */
@@ -1546,8 +1546,8 @@ static bool sde_rotator_verify_format(struct sde_rot_mgr *mgr,
			(in_fmt->bits[C2_R_Cr] != out_fmt->bits[C2_R_Cr]) ||
			(in_fmt->bits[C2_R_Cr] != out_fmt->bits[C2_R_Cr]) ||
			(in_fmt->bits[C0_G_Y] != out_fmt->bits[C0_G_Y]) ||
			(in_fmt->bits[C0_G_Y] != out_fmt->bits[C0_G_Y]) ||
			(in_fmt->bits[C1_B_Cb] != out_fmt->bits[C1_B_Cb])) {
			(in_fmt->bits[C1_B_Cb] != out_fmt->bits[C1_B_Cb])) {
			SDEROT_DBG("Bit format does not match\n");
			SDEROT_ERR("Bit format does not match\n");
			return false;
			goto verify_error;
		}
		}
	}
	}


@@ -1560,86 +1560,160 @@ static bool sde_rotator_verify_format(struct sde_rot_mgr *mgr,


		if ((in_v_subsample != out_h_subsample) ||
		if ((in_v_subsample != out_h_subsample) ||
				(in_h_subsample != out_v_subsample)) {
				(in_h_subsample != out_v_subsample)) {
			SDEROT_DBG("Rotation has invalid subsampling\n");
			SDEROT_ERR("Rotation has invalid subsampling\n");
			return false;
			goto verify_error;
		}
		}
	} else {
	} else {
		if (in_fmt->chroma_sample != out_fmt->chroma_sample) {
		if (in_fmt->chroma_sample != out_fmt->chroma_sample) {
			SDEROT_DBG("Format subsampling mismatch\n");
			SDEROT_ERR("Format subsampling mismatch\n");
			return false;
			goto verify_error;
		}
		}
	}
	}


	SDEROT_DBG("in_fmt=%0d, out_fmt=%d\n", in_fmt->format, out_fmt->format);
	return true;
	return true;

verify_error:
	SDEROT_ERR("in_fmt=0x%x, out_fmt=0x%x\n",
			in_fmt->format, out_fmt->format);
	return false;
}
}


int sde_rotator_verify_config(struct sde_rot_mgr *mgr,
static struct sde_mdp_format_params *__verify_input_config(
		struct sde_rot_mgr *mgr,
		struct sde_rotation_config *config)
		struct sde_rotation_config *config)
{
{
	struct sde_mdp_format_params *in_fmt, *out_fmt;
	struct sde_mdp_format_params *in_fmt;
	u8 in_v_subsample, in_h_subsample;
	u8 in_v_subsample, in_h_subsample;
	u8 out_v_subsample, out_h_subsample;
	u32 input;
	u32 input, output;
	bool rotation;
	int verify_input_only;
	int verify_input_only;


	if (!mgr || !config) {
	if (!mgr || !config) {
		SDEROT_ERR("null parameters\n");
		SDEROT_ERR("null parameters\n");
		return -EINVAL;
		return NULL;
	}
	}


	input = config->input.format;
	input = config->input.format;
	output = config->output.format;
	rotation = (config->flags & SDE_ROTATION_90) ? true : false;
	verify_input_only =
	verify_input_only =
		(config->flags & SDE_ROTATION_VERIFY_INPUT_ONLY) ? 1 : 0;
		(config->flags & SDE_ROTATION_VERIFY_INPUT_ONLY) ? 1 : 0;


	in_fmt = sde_get_format_params(input);
	in_fmt = sde_get_format_params(input);
	if (!in_fmt) {
	if (!in_fmt) {
		SDEROT_DBG("Unrecognized input format:%u\n", input);
		if (!verify_input_only)
		return -EINVAL;
			SDEROT_ERR("Unrecognized input format:0x%x\n", input);
	}
		return NULL;

	out_fmt = sde_get_format_params(output);
	if (!out_fmt) {
		SDEROT_DBG("Unrecognized output format:%u\n", output);
		return -EINVAL;
	}
	}


	sde_mdp_get_v_h_subsample_rate(in_fmt->chroma_sample,
	sde_mdp_get_v_h_subsample_rate(in_fmt->chroma_sample,
		&in_v_subsample, &in_h_subsample);
		&in_v_subsample, &in_h_subsample);
	sde_mdp_get_v_h_subsample_rate(out_fmt->chroma_sample,
		&out_v_subsample, &out_h_subsample);


	/* Dimension of image needs to be divisible by subsample rate  */
	/* Dimension of image needs to be divisible by subsample rate  */
	if ((config->input.height % in_v_subsample) ||
	if ((config->input.height % in_v_subsample) ||
			(config->input.width % in_h_subsample)) {
			(config->input.width % in_h_subsample)) {
		SDEROT_DBG(
		if (!verify_input_only)
			SDEROT_ERR(
				"In ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n",
				"In ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n",
					config->input.width,
					config->input.width,
					config->input.height,
					config->input.height,
					in_v_subsample, in_h_subsample);
					in_v_subsample, in_h_subsample);
		return -EINVAL;
		return NULL;
	}
	}


	return in_fmt;
}

static struct sde_mdp_format_params *__verify_output_config(
		struct sde_rot_mgr *mgr,
		struct sde_rotation_config *config)
{
	struct sde_mdp_format_params *out_fmt;
	u8 out_v_subsample, out_h_subsample;
	u32 output;
	int verify_input_only;

	if (!mgr || !config) {
		SDEROT_ERR("null parameters\n");
		return NULL;
	}

	output = config->output.format;
	verify_input_only =
		(config->flags & SDE_ROTATION_VERIFY_INPUT_ONLY) ? 1 : 0;

	out_fmt = sde_get_format_params(output);
	if (!out_fmt) {
		if (!verify_input_only)
			SDEROT_ERR("Unrecognized output format:0x%x\n", output);
		return NULL;
	}

	sde_mdp_get_v_h_subsample_rate(out_fmt->chroma_sample,
		&out_v_subsample, &out_h_subsample);

	/* Dimension of image needs to be divisible by subsample rate  */
	if ((config->output.height % out_v_subsample) ||
	if ((config->output.height % out_v_subsample) ||
			(config->output.width % out_h_subsample)) {
			(config->output.width % out_h_subsample)) {
		SDEROT_DBG(
		if (!verify_input_only)
			SDEROT_ERR(
				"Out ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n",
				"Out ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n",
					config->output.width,
					config->output.width,
					config->output.height,
					config->output.height,
					out_v_subsample, out_h_subsample);
					out_v_subsample, out_h_subsample);
		if (!verify_input_only)
		return NULL;
	}

	return out_fmt;
}

int sde_rotator_verify_config_input(struct sde_rot_mgr *mgr,
		struct sde_rotation_config *config)
{
	struct sde_mdp_format_params *in_fmt;

	in_fmt = __verify_input_config(mgr, config);
	if (!in_fmt)
		return -EINVAL;
		return -EINVAL;

	return 0;
}
}


	if (!sde_rotator_verify_format(mgr, in_fmt,
int sde_rotator_verify_config_output(struct sde_rot_mgr *mgr,
			out_fmt, rotation)) {
		struct sde_rotation_config *config)
		SDEROT_DBG(
{
			"Rot format pairing invalid, in_fmt:%d, out_fmt:%d\n",
	struct sde_mdp_format_params *out_fmt;
					input, output);

		if (!verify_input_only)
	out_fmt = __verify_output_config(mgr, config);
	if (!out_fmt)
		return -EINVAL;

	return 0;
}

int sde_rotator_verify_config_all(struct sde_rot_mgr *mgr,
	struct sde_rotation_config *config)
{
	struct sde_mdp_format_params *in_fmt, *out_fmt;
	bool rotation;

	if (!mgr || !config) {
		SDEROT_ERR("null parameters\n");
		return -EINVAL;
	}

	rotation = (config->flags & SDE_ROTATION_90) ? true : false;

	in_fmt = __verify_input_config(mgr, config);
	if (!in_fmt)
		return -EINVAL;

	out_fmt = __verify_output_config(mgr, config);
	if (!out_fmt)
		return -EINVAL;

	if (!sde_rotator_verify_format(mgr, in_fmt, out_fmt, rotation)) {
		SDEROT_ERR(
			"Rot format pairing invalid, in_fmt:0x%x, out_fmt:0x%x\n",
					config->input.format,
					config->output.format);
		return -EINVAL;
		return -EINVAL;
	}
	}


@@ -2049,7 +2123,7 @@ static int sde_rotator_config_session(struct sde_rot_mgr *mgr,
	int ret = 0;
	int ret = 0;
	struct sde_rot_perf *perf;
	struct sde_rot_perf *perf;


	ret = sde_rotator_verify_config(mgr, config);
	ret = sde_rotator_verify_config_all(mgr, config);
	if (ret) {
	if (ret) {
		SDEROT_ERR("Rotator verify format failed\n");
		SDEROT_ERR("Rotator verify format failed\n");
		return ret;
		return ret;
+8 −2
Original line number Original line Diff line number Diff line
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -413,7 +413,13 @@ void sde_rotator_remove_request(struct sde_rot_mgr *mgr,
	struct sde_rot_file_private *private,
	struct sde_rot_file_private *private,
	struct sde_rot_entry_container *req);
	struct sde_rot_entry_container *req);


int sde_rotator_verify_config(struct sde_rot_mgr *rot_dev,
int sde_rotator_verify_config_all(struct sde_rot_mgr *rot_dev,
	struct sde_rotation_config *config);

int sde_rotator_verify_config_input(struct sde_rot_mgr *rot_dev,
	struct sde_rotation_config *config);

int sde_rotator_verify_config_output(struct sde_rot_mgr *rot_dev,
	struct sde_rotation_config *config);
	struct sde_rotation_config *config);


int sde_rotator_validate_request(struct sde_rot_mgr *rot_dev,
int sde_rotator_validate_request(struct sde_rot_mgr *rot_dev,
+16 −6
Original line number Original line Diff line number Diff line
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -246,11 +246,13 @@ static void sde_rot_dump_vbif_debug_bus(u32 bus_dump_flag,
 * sde_rot_dump_reg - helper function for dumping rotator register set content
 * sde_rot_dump_reg - helper function for dumping rotator register set content
 * @dump_name - register set name
 * @dump_name - register set name
 * @reg_dump_flag - dumping flag controlling in-log/memory dump location
 * @reg_dump_flag - dumping flag controlling in-log/memory dump location
 * @access - access type, sde registers or vbif registers
 * @addr - starting address offset for dumping
 * @addr - starting address offset for dumping
 * @len - range of the register set
 * @len - range of the register set
 * @dump_mem - output buffer for memory dump location option
 * @dump_mem - output buffer for memory dump location option
 */
 */
void sde_rot_dump_reg(const char *dump_name, u32 reg_dump_flag, u32 addr,
void sde_rot_dump_reg(const char *dump_name, u32 reg_dump_flag,
	enum sde_rot_regdump_access access, u32 addr,
	int len, u32 **dump_mem)
	int len, u32 **dump_mem)
{
{
	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
@@ -258,6 +260,7 @@ void sde_rot_dump_reg(const char *dump_name, u32 reg_dump_flag, u32 addr,
	u32 *dump_addr = NULL;
	u32 *dump_addr = NULL;
	phys_addr_t phys = 0;
	phys_addr_t phys = 0;
	int i;
	int i;
	void __iomem *base;


	in_log = (reg_dump_flag & SDE_ROT_DBG_DUMP_IN_LOG);
	in_log = (reg_dump_flag & SDE_ROT_DBG_DUMP_IN_LOG);
	in_mem = (reg_dump_flag & SDE_ROT_DBG_DUMP_IN_MEM);
	in_mem = (reg_dump_flag & SDE_ROT_DBG_DUMP_IN_MEM);
@@ -285,14 +288,20 @@ void sde_rot_dump_reg(const char *dump_name, u32 reg_dump_flag, u32 addr,
		}
		}
	}
	}


	base = mdata->sde_io.base;
	/*
	 * VBIF NRT base handling
	 */
	if (access == SDE_ROT_REGDUMP_VBIF)
		base = mdata->vbif_nrt_io.base;


	for (i = 0; i < len; i++) {
	for (i = 0; i < len; i++) {
		u32 x0, x4, x8, xc;
		u32 x0, x4, x8, xc;


		x0 = readl_relaxed(mdata->sde_io.base + addr+0x0);
		x0 = readl_relaxed(base + addr+0x0);
		x4 = readl_relaxed(mdata->sde_io.base + addr+0x4);
		x4 = readl_relaxed(base + addr+0x4);
		x8 = readl_relaxed(mdata->sde_io.base + addr+0x8);
		x8 = readl_relaxed(base + addr+0x8);
		xc = readl_relaxed(mdata->sde_io.base + addr+0xc);
		xc = readl_relaxed(base + addr+0xc);


		if (in_log)
		if (in_log)
			pr_info("0x%08X : %08x %08x %08x %08x\n",
			pr_info("0x%08X : %08x %08x %08x %08x\n",
@@ -338,6 +347,7 @@ static void sde_rot_dump_reg_all(void)
		} else {
		} else {
			sde_rot_dump_reg(head->name,
			sde_rot_dump_reg(head->name,
					sde_rot_dbg_evtlog.enable_reg_dump,
					sde_rot_dbg_evtlog.enable_reg_dump,
					head->access,
					head->offset, head->len,
					head->offset, head->len,
					&sde_rot_dbg_evtlog.reg_dump_array[i]);
					&sde_rot_dbg_evtlog.reg_dump_array[i]);
		}
		}
+7 −5
Original line number Original line Diff line number Diff line
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -1216,7 +1216,8 @@ static int sde_rotator_try_fmt_vid_cap(struct file *file,
	config.output.format = f->fmt.pix.pixelformat;
	config.output.format = f->fmt.pix.pixelformat;
	config.output.width = f->fmt.pix.width;
	config.output.width = f->fmt.pix.width;
	config.output.height = f->fmt.pix.height;
	config.output.height = f->fmt.pix.height;
	ret = sde_rotator_verify_config(rot_dev->mgr, &config);
	config.flags |= SDE_ROTATION_VERIFY_INPUT_ONLY;
	ret = sde_rotator_verify_config_output(rot_dev->mgr, &config);
	sde_rot_mgr_unlock(rot_dev->mgr);
	sde_rot_mgr_unlock(rot_dev->mgr);
	if (ret) {
	if (ret) {
		if ((config.output.width == f->fmt.pix.width) &&
		if ((config.output.width == f->fmt.pix.width) &&
@@ -1233,7 +1234,7 @@ static int sde_rotator_try_fmt_vid_cap(struct file *file,
	}
	}


	sde_rotator_format_recalc(f);
	sde_rotator_format_recalc(f);
	return 0;
	return ret;
}
}


/*
/*
@@ -1263,7 +1264,7 @@ static int sde_rotator_try_fmt_vid_out(struct file *file,
	config.input.width = f->fmt.pix.width;
	config.input.width = f->fmt.pix.width;
	config.input.height = f->fmt.pix.height;
	config.input.height = f->fmt.pix.height;
	config.flags |= SDE_ROTATION_VERIFY_INPUT_ONLY;
	config.flags |= SDE_ROTATION_VERIFY_INPUT_ONLY;
	ret = sde_rotator_verify_config(rot_dev->mgr, &config);
	ret = sde_rotator_verify_config_input(rot_dev->mgr, &config);
	sde_rot_mgr_unlock(rot_dev->mgr);
	sde_rot_mgr_unlock(rot_dev->mgr);
	if (ret) {
	if (ret) {
		if ((config.input.width == f->fmt.pix.width) &&
		if ((config.input.width == f->fmt.pix.width) &&
@@ -1280,7 +1281,7 @@ static int sde_rotator_try_fmt_vid_out(struct file *file,
	}
	}


	sde_rotator_format_recalc(f);
	sde_rotator_format_recalc(f);
	return 0;
	return ret;
}
}


/*
/*
@@ -1510,6 +1511,7 @@ static int sde_rotator_streamon(struct file *file,
	if (vb2_is_streaming(vq)) {
	if (vb2_is_streaming(vq)) {
		sde_rot_mgr_lock(rot_dev->mgr);
		sde_rot_mgr_lock(rot_dev->mgr);
		sde_rotator_get_config_from_ctx(ctx, &config);
		sde_rotator_get_config_from_ctx(ctx, &config);
		config.flags &= ~SDE_ROTATION_VERIFY_INPUT_ONLY;
		ret = sde_rotator_session_config(rot_dev->mgr, ctx->private,
		ret = sde_rotator_session_config(rot_dev->mgr, ctx->private,
				&config);
				&config);
		sde_rot_mgr_unlock(rot_dev->mgr);
		sde_rot_mgr_unlock(rot_dev->mgr);
Loading