/*
 * linux/drivers/video/omap2/dss/fifothreshold.c
 *
 * Copyright (C) 2011 Texas Instruments
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <linux/kernel.h>
#include <video/omapdss.h>
#include "dss.h"

#define YUV422_UYVY     10
#define YUV422_YUV2     11

struct sa_struct {
	u32 min_sa;
	u32 max_lt;
	u32 min_lt;
};

struct ddma_config {
	u16 twomode;
	u16 antifckr;
	u16 double_stride;
	u16 bpp;
	u16 bitmap;
	u16 pixel_inc;
	u16 max_burst;
	u16 gballoc;
	u16 vballoc;
	u16 yuv420;
	u32 rowincr;
	u32 ba;
	u32 size_x;
	u32 size_y;
};

/*
 * bitpk : used to return partial bit vectors of bigger
 * bit vector, as and when required in algorithm.
 * Ex: bitpk(BaseAddress,28,27) = BaseAddress[28:27]
 */
static inline u32 bitpk(unsigned long a, u32 left, u32 right)
{
	return (a >> right) & ((2 << (left - right)) - 1);
}

/*
 * dispc_reg_to_ddma converts the DISPC register values into information
 * used by the DDMA. Ex: format=15 => BytesPerPixel = 3
 * dispcRegConfig :: Dispc register information
 * ChannelNo      :: ChannelNo
 * y_nuv          :: 1->Luma frame parameters, calculation ;
 *		     0->Chroma frame parameters and calculation
 * bh_config       :: Output struct having information useful for the algorithm
 */
static void dispc_reg_to_ddma(struct dispc_config *dispc_reg_config,
	u32 channel_no, u32 y_nuv, struct ddma_config *bh_config)
{
	u16 i;
	/* GFX pipe specific conversions */
	if (channel_no == 0) {
		/*
		 * For bitmap formats the pixcel information is stored in bits.
		 * This needs to be divided by 8 to convert into bytes.
		 */
		bh_config->bitmap = (dispc_reg_config->format <= 2) ? 8 : 1;
		/*
		 * In case of GFX there is no YUV420 mode:
		 * yuv420: 1->nonYUV420 2-> YUV420
		 */
		bh_config->yuv420 = 1;
		bh_config->pixel_inc = dispc_reg_config->pixelinc;
		switch (dispc_reg_config->format) {
		/* LUT for format<-->Bytesper pixel */
		case 0:
		case 3:
			i = 1;
			break;
		case 1:
		case 4:
		case 5:
		case 6:
		case 7:
		case 10:
		case 11:
		case 15:
			i = 2;
			break;
		case 9:
			i = 3;
			break;
		default:
			i = 4;
			break;
		}
		bh_config->bpp = i;
		i = 0;
		/*
		 * Chroma double_stride value of DISPC registers is invalid
		 * for GFX  where there is np YUV420 format.
		 */
		bh_config->double_stride = 0;
		bh_config->antifckr = dispc_reg_config->antiflicker;
		bh_config->ba = dispc_reg_config->ba;
		bh_config->size_x = dispc_reg_config->sizex;
	} else {
		/*
		 * For all Video channels
		 *
		 * In Video there is no bitmap format, All format pixcel is
		 * stored in multiples of bytes.
		 */
		bh_config->bitmap = 1;
		/* No antiflicker mode for Video channels */
		bh_config->antifckr = 0;
		/*
		 * 1->nonYUV420 2-> YUV420 : Used in breaking up the buffer
		 * allocation:: Top:Luma, Bottom:Chroma
		 */
		bh_config->yuv420 = (dispc_reg_config->format == 0) ? 2 : 1;

		switch (dispc_reg_config->format) {
		/* LUT for format<-->Bytesper pixel */
		/* bpp:1 for Luma bpp:2 for Chroma */
		case 0:
			i = (y_nuv ? 1 : 2);
			break;
		case 1:
		case 2:
		case 4:
		case 5:
		case 6:
		case 7:
		case 15:
			i = 2;
			break;
		case 9:
			i = 3;
			break;
		case 10:
		case 11:
			i = (dispc_reg_config->rotation == 1 ||
				dispc_reg_config->rotation == 3) ? 4 : 2;
			break;

		/* Format 10,11 => YUV422. YUV422+No rotation : bpp =bpp/2 */
		default:
			i = 4;
			break;
		}

		/*
		 * PixcelIncrement = numberOfPixcelsInterleaving*BytesPerPixcel
		 * + 1. For Chroma pixcelincrement should be doubled to leave
		 * same number of Chroma pixels and Luma.
		 */
		bh_config->pixel_inc =
			(dispc_reg_config->format == 0 && y_nuv == 0) ?
			(dispc_reg_config->pixelinc - 1) * 2 + 1 :
			dispc_reg_config->pixelinc;

		/*
		 * for YUV422+No rotation : bpp =bpp/2:: To correct Pixcel
		 * increment accordingly use in stride calculation.
		 */
		bh_config->pixel_inc =
			((dispc_reg_config->format == YUV422_UYVY ||
			  dispc_reg_config->format == YUV422_YUV2) &&
			 (dispc_reg_config->rotation == 0 ||
			  dispc_reg_config->rotation == 2)) ?
				(dispc_reg_config->pixelinc - 1) / 2 + 1 :
				bh_config->pixel_inc;
		bh_config->bpp = i;
		bh_config->double_stride =
			(dispc_reg_config->format == 0 && y_nuv == 0) ?
				dispc_reg_config->doublestride : 0;

		/* Conditions in which SizeY is halfed = i; */
		i = (((dispc_reg_config->rotation == 1 ||
		       dispc_reg_config->rotation == 3) &&
		      (dispc_reg_config->format == YUV422_UYVY ||
		       dispc_reg_config->format == YUV422_YUV2)) ||
		     ((dispc_reg_config->rotation == 1 ||
		       dispc_reg_config->rotation == 3 ||
		       bh_config->double_stride == 1) &&
		      dispc_reg_config->format == 0 && y_nuv == 0)) ? 1 : 0;

		/* Choosing between BA_Y and BA_CbCr */
		bh_config->ba =
			(dispc_reg_config->format == 0 && y_nuv == 0) ?
			dispc_reg_config->bacbcr :
			dispc_reg_config->ba;

		/* SizeX halfed for Chroma frame */
		bh_config->size_x =
			(dispc_reg_config->format == 0 && y_nuv == 0) ?
			(dispc_reg_config->sizex + 1) / 2 - 1 :
			dispc_reg_config->sizex;
	}

	bh_config->twomode = dispc_reg_config->bursttype;
	bh_config->size_y = ((dispc_reg_config->sizey + 1) >> i) - 1;
	bh_config->rowincr = dispc_reg_config->rowinc;
	bh_config->max_burst = 1 << (dispc_reg_config->burstsize + 1);

	/* Decoding the burstSize to be used in BH calculation algorithm */
	bh_config->gballoc =
		(dispc_reg_config->gfx_bottom_buffer == channel_no) +
		(dispc_reg_config->gfx_top_buffer == channel_no);
	bh_config->vballoc =
		(dispc_reg_config->vid1_bottom_buffer == channel_no) +
		(dispc_reg_config->vid1_top_buffer == channel_no) +
		(dispc_reg_config->vid2_bottom_buffer == channel_no) +
		(dispc_reg_config->vid2_top_buffer == channel_no) +
		(dispc_reg_config->vid3_bottom_buffer == channel_no) +
		(dispc_reg_config->vid3_top_buffer == channel_no) +
		(dispc_reg_config->wb_bottom_buffer == channel_no) +
		(dispc_reg_config->wb_top_buffer == channel_no);
}

/*
 * sa_calc calculates SA and LT values for one set of DISPC reg inputs
 * dispc_reg_config :: Dispc register information
 * channel_no      :: channel_no
 * y_nuv          :: 1->Luma frame parameters, calculation
 *		     0->Chroma frame parameters and calculation
 * sa_info         :: Output struct having information of SA and LT values
 */
static void sa_calc(struct dispc_config *dispc_reg_config, u32 channel_no,
			u32 y_nuv, struct sa_struct *sa_info)
{
	u32 Sorientation, mode, mode_0, mode_1;
	int blkh_opt;
	int pagemode;
	long int sizeX_nopred, sizeX_pred;
	u32 pict_16word;
	long int pict_16word_ceil;
	long int stride;
	int stride_8k;
	int stride_16k;
	int stride_32k;
	int stride_64k;
	int stride_ok, stride_val;
	int linesRem;
	u32 BA_bhbit, bh_max;
	int burstHeight;
	int i;
	int bh2d_cond;
	int C1, c1flag, C2;
	long int Tot_mem;
	struct ddma_config bh_config;

	dispc_reg_to_ddma(dispc_reg_config, channel_no, y_nuv, &bh_config);

	mode         = bitpk(bh_config.ba, 28, 27);
	mode_1       = bitpk(bh_config.ba, 28, 28);
	mode_0       = bitpk(bh_config.ba, 27, 27);
	Sorientation = bitpk(bh_config.ba, 31, 31);

	pagemode = (mode == 3);
	blkh_opt = mode_1 ? 2 : 4;

	bh_config.double_stride = (bh_config.double_stride == 1
				&& bh_config.twomode == 1) ? 2 : 1;

	/* SizeX in frame = number of pixels * BytesPerPixel */
	sizeX_nopred = ((bh_config.size_x + 1) * bh_config.bpp) /
			bh_config.bitmap;
	/* Size including skipped pixels */
	sizeX_pred = ((bh_config.size_x + 1) *
		(bh_config.pixel_inc - 1 + bh_config.bpp)) / bh_config.bitmap;
	stride = ((bh_config.rowincr - 1) + sizeX_pred) *
						bh_config.double_stride;
	stride_8k = stride == 8192 && mode_1 == 0 && Sorientation;
	stride_16k = stride == 16384 && !(mode_0 != mode_1 && !Sorientation);
	stride_32k = stride == 32768 && (mode_1 == 1 || !Sorientation);
	stride_64k = stride == 65536 && !(mode_0 == mode_1) && !Sorientation;
	stride_ok = (stride_8k || stride_16k || stride_32k || stride_64k);
	stride_val = stride_64k ? 16 : stride_32k ? 15 : stride_16k ? 14 : 13;

	linesRem = bh_config.size_y + 1;

	/* Condition than enables 2D fetch of OCP */
	bh2d_cond = (bh_config.twomode && (pagemode == 0)
			&& stride_ok && (linesRem > 0));

	/*
	 * BH calculation algorithm depending on stride,NumberofLinesInFrame,
	 * other parameters of Tiler alignment of base address.
	 */
	C1 = C2 = c1flag = 0;
	for (i = 1; i <= 5 && linesRem > 0 && c1flag == 0; i++) {
		if (bh2d_cond) {
			/* 2D transfer */
			BA_bhbit = bitpk(bh_config.ba,
					stride_val + (mode_1 == 0),
					stride_val);
			bh_max = blkh_opt - BA_bhbit;

			burstHeight = min(linesRem,
				min((int) bh_config.max_burst, (int) bh_max));

			if (burstHeight == 3 ||
			    (burstHeight == 4 && bh_config.antifckr == 1))
				burstHeight = 2;
		} else {
			burstHeight = 1;
		}
		if ((C1 + burstHeight) <= 4 && c1flag == 0) {
			/*
			 * C1 incremented until its >= 4. ensures howmany
			 * full lines are requested just before SA reaches
			 */
			C1 += burstHeight;
		} else {
			if (c1flag == 0)
				/*
				 * After C1 saturated to 4, next burstHeight
				 * decides C2: the number of partially filled
				 * lines when SA condition is reached
				 */
				C2 = burstHeight;
			c1flag = 1;
		}
		linesRem -= burstHeight;
		bh_config.ba += stride * burstHeight;
	}

	/*
	 * Total line buffer memory GFXBuffers+Vid/WB bufers allocated in terms
	 * of 16Byte Word locations
	 */
	Tot_mem = (640 * bh_config.gballoc + 1024 * bh_config.vballoc) /
				(4 * bh_config.yuv420);
	/*
	 * Ceil(rounded to higher integer) of Number of 16Byte Word locations
	 * used by single line of frame.
	 */
	pict_16word_ceil = DIV_ROUND_UP(sizeX_nopred, 16);

	/* Exact Number of 16Byte Word locations used by single line of frame */
	pict_16word = sizeX_nopred / 16;

	/*
	 * Number of sets of 4 lines that can fully fit into the  memory
	 * buffers allocated.
	 */
	i = Tot_mem / pict_16word_ceil;

	if (i == 0) {
		/* LineSize > MemoryLineBufferSize (Valid only for 1D) */
		sa_info->min_sa = Tot_mem - 8;
	} else if (i == 1) {
		/*
		 * When MemoryLineBufferSize > LineSize >
		 * (MemoryLineBufferSize/2)
		 */
		sa_info->min_sa = pict_16word + C2 * (Tot_mem -
						pict_16word_ceil - 8);
	} else {
		/* All other cases */
		sa_info->min_sa = 4 * pict_16word_ceil;
	}

	/* C2=0:: no partialy filed lines:: Then minLT = 0 */
	if (C2 == 0) {
		sa_info->min_lt = 0;
	} else if (bh_config.antifckr == 1) {
		if (C1 == 3)
			sa_info->min_lt = 3 * pict_16word_ceil + C2 * (Tot_mem -
						(pict_16word_ceil*i));
		else if (C1 == 4)
			sa_info->min_lt = 2 * pict_16word_ceil + C2 * (Tot_mem -
						(pict_16word_ceil*i));
	} else {
		sa_info->min_lt = (C2 - 1) * (Tot_mem - (pict_16word_ceil*i));
	}

	sa_info->max_lt = max(sa_info->min_sa - 8, sa_info->min_lt + 1);
}

/*
 * sa_calc calculates SA and LT values for one set of DISPC reg inputs
 * This takes care of calling the actual sa_calc function once/twice
 *  as per nonYUV420/YUV420 format and gives final value of output
 * dispc_reg_config :: Dispc register information
 * channel_no      :: channel_no
 * y_nuv          :: 1->Luma frame parameters, calculation;
 *		     0->Chroma frame parameters and calculation
 * sa_info         :: Output struct having information of SA and LT values
 */
u32 sa_calc_wrap(struct dispc_config *dispc_reg_config, u32 channel_no)
{
	struct sa_struct sa_info_y;
	struct sa_struct sa_info_uv;

	/* SA values calculated for Luma frame */
	sa_calc(dispc_reg_config, channel_no, 1, &sa_info_y);

	/* Going into this looop only for YUV420 Format and Channel != GFX */
	if (dispc_reg_config->format == 0 && channel_no > 0) {
		/* SA values calculated for Chroma Frame */
		sa_calc(dispc_reg_config, channel_no, 0, &sa_info_uv);
		return 2 * max(min(sa_info_y.min_sa, sa_info_uv.min_sa) - 8,
			       max(sa_info_y.min_lt, sa_info_uv.min_lt) + 1);
	} else {
		return sa_info_y.max_lt;
	}
}
