Re: [PATCH 05/28] gpu: ipu-v3: Add units required for video capture

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am Donnerstag, den 31.07.2014, 17:27 +0200 schrieb Philipp Zabel:
> > +static void init_csc_rgb2ycbcr(u32 __iomem *base)
> > +{
> > +	/*
> > +	 * Y = R *  .299 + G *  .587 + B *  .114;
> > +	 * U = R * -.169 + G * -.332 + B *  .500 + 128.;
> > +	 * V = R *  .500 + G * -.419 + B * -.0813 + 128.;
> > +	 */
> > +	const u32 coeff[4][3] = {
> > +		{0x004D, 0x0096, 0x001D},
> > +		{0x01D5, 0x01AB, 0x0080},
> > +		{0x0080, 0x0195, 0x01EB},
> > +		{0x0000, 0x0200, 0x0200},	/* A0, A1, A2 */
> > +	};
> > +	u32 param;
> > +
> > +	param = (coeff[3][0] << 27) | (coeff[0][0] << 18) |
> > +		(coeff[1][1] << 9) | coeff[2][2];
> > +	writel(param, base++);
> > +
> > +	/* scale = 1, sat = 0 */
> > +	param = (coeff[3][0] >> 5) | (1UL << 8);
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][1] << 27) | (coeff[0][1] << 18) |
> > +		(coeff[1][0] << 9) | coeff[2][0];
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][1] >> 5);
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][2] << 27) | (coeff[0][2] << 18) |
> > +		(coeff[1][2] << 9) | coeff[2][1];
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][2] >> 5);
> > +	writel(param, base++);
> > +}
> > +
> > +static void init_csc_rgb2rgb(u32 __iomem *base)
> > +{
> > +	/* transparent RGB->RGB matrix for graphics combining */
> > +	const u32 coeff[4][3] = {
> > +		{0x0080, 0x0000, 0x0000},
> > +		{0x0000, 0x0080, 0x0000},
> > +		{0x0000, 0x0000, 0x0080},
> > +		{0x0000, 0x0000, 0x0000},	/* A0, A1, A2 */
> > +	};
> > +	u32 param;
> > +
> > +	param = (coeff[3][0] << 27) | (coeff[0][0] << 18) |
> > +		(coeff[1][1] << 9) | coeff[2][2];
> > +	writel(param, base++);
> > +
> > +	/* scale = 2, sat = 0 */
> > +	param = (coeff[3][0] >> 5) | (2UL << 8);
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][1] << 27) | (coeff[0][1] << 18) |
> > +		(coeff[1][0] << 9) | coeff[2][0];
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][1] >> 5);
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][2] << 27) | (coeff[0][2] << 18) |
> > +		(coeff[1][2] << 9) | coeff[2][1];
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][2] >> 5);
> > +	writel(param, base++);
> > +}
> > +
> > +static void init_csc_ycbcr2rgb(u32 __iomem *base)
> > +{
> > +	/*
> > +	 * R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
> > +	 * G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
> > +	 * B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128);
> > +	 */
> > +	const u32 coeff[4][3] = {
> > +		{149, 0, 204},
> > +		{149, 462, 408},
> > +		{149, 255, 0},
> > +		{8192 - 446, 266, 8192 - 554},	/* A0, A1, A2 */
> > +	};
> > +	u32 param;
> > +
> > +	param = (coeff[3][0] << 27) | (coeff[0][0] << 18) |
> > +		(coeff[1][1] << 9) | coeff[2][2];
> > +	writel(param, base++);
> > +
> > +	/* scale = 2, sat = 0 */
> > +	param = (coeff[3][0] >> 5) | (2L << (40 - 32));
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][1] << 27) | (coeff[0][1] << 18) |
> > +		(coeff[1][0] << 9) | coeff[2][0];
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][1] >> 5);
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][2] << 27) | (coeff[0][2] << 18) |
> > +		(coeff[1][2] << 9) | coeff[2][1];
> > +	writel(param, base++);
> > +
> > +	param = (coeff[3][2] >> 5);
> > +	writel(param, base++);
> > +}

Instead of repeating the same code three times, we could have three
global static const arrays for coefficients and scaling factors, and
only one function to apply any of them (or merge the code into
init_csc).

[...]
> > +static int calc_resize_coeffs(struct ipu_ic *ic,
> > +			      u32 in_size, u32 out_size,
> > +			      u32 *resize_coeff,
> > +			      u32 *downsize_coeff)
> > +{
> > +	struct ipu_ic_priv *priv = ic->priv;
> > +	struct ipu_soc *ipu = priv->ipu;
> > +	u32 temp_size, temp_downsize;
> > +
> > +	/*
> > +	 * Input size cannot be more than 4096, and output size cannot
> > +	 * be more than 1024
> > +	 */
> > +	if (in_size > 4096) {
> > +		dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
> > +		return -EINVAL;
> > +	}
> > +	if (out_size > 1024) {
> > +		dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* Cannot downsize more than 8:1 */
> > +	if ((out_size << 3) < in_size) {
> > +		dev_err(ipu->dev, "Unsupported downsize\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* Compute downsizing coefficient */
> > +	temp_downsize = 0;
> > +	temp_size = in_size;
> > +	while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
> > +	       (temp_downsize < 2)) {
> > +		temp_size >>= 1;
> > +		temp_downsize++;
> > +	}
> > +	*downsize_coeff = temp_downsize;
> > +
> > +	/*
> > +	 * compute resizing coefficient using the following equation:
> > +	 * resize_coeff = M * (SI - 1) / (SO - 1)
> > +	 * where M = 2^13, SI = input size, SO = output size
> > +	 */
> > +	*resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
> > +	if (*resize_coeff >= 16384L) {
> > +		dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
> > +		*resize_coeff = 0x3FFF;
> > +	}
> > +
> > +	return 0;
> > +}

This is fine for now, but to support tiled mem2mem scaling we will have
to make the scaling coefficient calculation independent from the tile
size.

[...]

regards
Philipp

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux