static int calc_gamma(struct dynamic_aid_info d_aid, int ibr, int *result)
{
	int ret, iv, c;
	int numerator, denominator;
	s64 t1, t2;
	int *vd, *mtp, *res;
	struct rgb_t (*offset_color)[d_aid.iv_max];
	struct rgb64_t *m_voltage;

	offset_color = (struct rgb_t(*)[])d_aid.param.offset_color;
	m_voltage = d_aid.m_voltage;
	iv = d_aid.iv_max - 1;
	ret = 0;

	/* iv == (IV_MAX - 1) ~ 1; */
	for (; iv > 0; iv--) {
		mtp = &d_aid.mtp[iv*CI_MAX];
		res = &result[iv*CI_MAX];
		numerator = d_aid.param.formular[iv].numerator;
		denominator = d_aid.param.formular[iv].denominator;
		for (c = 0; c < CI_MAX; c++) {
			if (iv == 1) {
				t1 = d_aid.vreg - m_voltage[iv].rgb[c];
				t2 = d_aid.vreg - m_voltage[iv+1].rgb[c];
			} else if (iv == d_aid.iv_max - 1) {
				t1 = d_aid.vreg - m_voltage[iv].rgb[c];
				t2 = d_aid.vreg;
			} else {
				t1 = m_voltage[0].rgb[c] - m_voltage[iv].rgb[c];
				t2 = m_voltage[0].rgb[c] - m_voltage[iv+1].rgb[c];
			}
			res[c] = div64_s64((t1 + 1) * denominator, t2) - numerator;
			res[c] -= mtp[c];

			if (offset_color)
				res[c] += offset_color[ibr][iv].rgb[c];

			if ((res[c] > 255) && (iv != d_aid.iv_max - 1))
				res[c] = 255;
		}
	}

	/* iv == 0; */
	vd = (int *)&d_aid.param.gamma_default[0];
	res = &result[0];
	for (c = 0; c < CI_MAX; c++)
		res[c] = vd[c];

#ifdef DYNAMIC_AID_DEBUG
	aid_dbg("Gamma (%d) =\n", d_aid.ibr_tbl[ibr]);
	for (iv = 0; iv < d_aid.iv_max; iv++) {
		aid_dbg("[%d] = ", iv);
		for (c = 0; c < CI_MAX; c++)
			aid_dbg("%X ", result[iv*CI_MAX+c]);
		aid_dbg("\n");
	}
#endif

	return ret;
}
static int calc_gamma_table(struct dynamic_aid_info d_aid, int **gamma)
{
	int ibr;
#ifdef DYNAMIC_AID_DEBUG
	int iv, c;
#endif

	init_l_lookup_table(d_aid);

	/* ibr == 0 ~ (IBRIGHTNESS_MAX - 1); */
	for (ibr = 0; ibr < d_aid.ibr_max; ibr++) {
		calc_l_values(d_aid, ibr);
		calc_m_gray_values(d_aid, ibr);
		calc_m_rgb_voltages(d_aid, ibr);
		calc_gamma(d_aid, ibr, gamma[ibr]);
	}

#ifdef DYNAMIC_AID_DEBUG
	for (ibr = 0; ibr < d_aid.ibr_max; ibr++) {
		aid_dbg("Gamma [%03d] = ", d_aid.ibr_tbl[ibr]);
		for (iv = 1; iv < d_aid.iv_max; iv++) {
			for (c = 0; c < CI_MAX; c++)
				aid_dbg("%04d ", gamma[ibr][iv*CI_MAX+c]);
		}
		for (c = 0; c < CI_MAX; c++)
			aid_dbg("%d ", gamma[ibr][c]);
		aid_dbg("\n");
	}
#endif

	return 0;
}
static int calc_m_gray_values(struct dynamic_aid_info d_aid, int ibr)
{
	int iv;
	int (*offset_gra)[d_aid.iv_max];
	int *l_lookup_table;
	int *l_value;
	int *m_gray;

	offset_gra = (int(*)[])d_aid.param.offset_gra;
	l_lookup_table = d_aid.l_lookup_table;
	l_value = d_aid.l_value;
	m_gray = d_aid.m_gray;
	iv = d_aid.iv_max - 1;

	/* iv == (IV_MAX - 1) ~ 0; */
	for (; iv >= 0; iv--) {
		m_gray[iv] = min_diff_gray(l_value[iv], l_lookup_table, d_aid.iv_top);
		if (offset_gra)
			m_gray[iv] += offset_gra[ibr][iv];
	}

#ifdef DYNAMIC_AID_DEBUG
	aid_dbg("M-Gray value[%d] = ", d_aid.ibr_tbl[ibr]);
	for (iv = 0; iv < d_aid.iv_max; iv++)
		aid_dbg("%d ", d_aid.m_gray[iv]);
	aid_dbg("\n");
#endif

	return 0;
}
static int calc_l_values(struct dynamic_aid_info d_aid, int ibr)
{
	int iv;
	int *gamma_curve;
	int *br_base;
	int *l_value;

	gamma_curve = (int *)d_aid.param.gc_tbls[ibr];
	br_base = (int *)d_aid.param.br_base;
	l_value = d_aid.l_value;
	iv = d_aid.iv_max - 1;

	/* iv == (IV_MAX - 1) ~ 0; */
	for (; iv >= 0; iv--) {
		if (iv == d_aid.iv_max - 1)
			l_value[iv] = MUL_10000(br_base[ibr]);
		else
			l_value[iv] = DIV_100(br_base[ibr]*gamma_curve[d_aid.iv_tbl[iv]]);
	}

#ifdef DYNAMIC_AID_DEBUG
	aid_dbg("L value (%d) = ", d_aid.ibr_tbl[ibr]);
	for (iv = 0; iv < d_aid.iv_max; iv++)
		aid_dbg("%d ", l_value[iv]);
	aid_dbg("\n");
#endif
	return 0;
}
static int calc_output_voltages(struct dynamic_aid_info d_aid)
{
	int iv, i, c;
	int v_idx, v_cnt;
	struct rgb_t v, v_diff;
	struct rgb64_t *output_voltages;
	struct rgb64_t *point_voltages;

	output_voltages = d_aid.output_voltages;
	point_voltages = d_aid.point_voltages;
	iv = d_aid.iv_max - 1;

	/* iv == (IV_MAX-1) ~ 0; */
	for (; iv > 0; iv--) {
		v_cnt = d_aid.iv_tbl[iv] - d_aid.iv_tbl[iv-1];
		v_idx = d_aid.iv_tbl[iv];

		for (c = 0; c < CI_MAX; c++) {
			v.rgb[c] = point_voltages[iv].rgb[c];
			v_diff.rgb[c] =
				point_voltages[iv-1].rgb[c] -
				point_voltages[iv].rgb[c];
		}

		if (iv == 1)
			for (c = 0; c < CI_MAX; c++)
				v_diff.rgb[c] = d_aid.vreg -
				point_voltages[iv].rgb[c];

		for (i = 0; i < v_cnt; i++, v_idx--) {
			for (c = 0; c < CI_MAX; c++)
				output_voltages[v_idx].rgb[c] = v.rgb[c]
				+ v_diff.rgb[c]*i/v_cnt;
		}
	}

	for (c = 0; c < CI_MAX; c++)
		output_voltages[0].rgb[c] = d_aid.vreg;

#ifdef DYNAMIC_AID_DEBUG
	for (iv = 0; iv <= d_aid.iv_top; iv++) {
		aid_dbg("Output Voltage[%d] = ", iv);
		for (c = 0; c < CI_MAX; c++)
			aid_dbg("%lld ", output_voltages[iv].rgb[c]);
		aid_dbg("\n");
	}
#endif

	return 0;
}
static int calc_m_rgb_voltages(struct dynamic_aid_info d_aid, int ibr)
{
	int iv, c;
	struct rgb64_t *output_voltages;
	struct rgb64_t *point_voltages;
	int *m_gray;
	struct rgb64_t *m_voltage;

	output_voltages = d_aid.output_voltages;
	point_voltages = d_aid.point_voltages;
	m_gray = d_aid.m_gray;
	m_voltage = d_aid.m_voltage;
	iv = d_aid.iv_max - 1;

	/* iv == (IV_MAX - 1) ~ 1; */
	for (; iv > 0; iv--) {
		for (c = 0; c < CI_MAX; c++)
			m_voltage[iv].rgb[c] =
			output_voltages[m_gray[iv]].rgb[c];
	}

	/* iv == 0; */
	for (c = 0; c < CI_MAX; c++)
		m_voltage[iv].rgb[c] = point_voltages[0].rgb[c];

#ifdef DYNAMIC_AID_DEBUG
	aid_dbg("M-RGB voltage (%d) =\n", d_aid.ibr_tbl[ibr]);
	for (iv = 0; iv < d_aid.iv_max; iv++) {
		aid_dbg("[%d] = ", iv);
		for (c = 0; c < CI_MAX; c++)
			aid_dbg("%lld ", d_aid.m_voltage[iv].rgb[c]);
		aid_dbg("\n");
	}
#endif

	return 0;
}
static int init_l_lookup_table(struct dynamic_aid_info d_aid)
{
	int iv;
	int *gamma_curve;
	int *l_lookup_table;

	gamma_curve = (int *)d_aid.param.gc_lut;
	l_lookup_table = d_aid.l_lookup_table;

	for (iv = 0; iv <= d_aid.iv_top; iv++)
		l_lookup_table[iv] = DIV_100(d_aid.ibr_top*gamma_curve[iv]);

#ifdef DYNAMIC_AID_DEBUG
	for (iv = 0; iv <= d_aid.iv_top; iv++)
		aid_dbg("L lookup table[%d] = %d\n", iv, l_lookup_table[iv]);
#endif
	return 0;
}
static int calc_point_voltages(struct dynamic_aid_info d_aid)
{
	int ret, iv, c;
	struct rgb64_t *vt, *vp;
	int *vd, *mtp;
	int numerator, denominator;
	s64 v0;
	s64 t1, t2;
	struct rgb64_t *point_voltages;

	point_voltages = d_aid.point_voltages;
	v0 = d_aid.vreg;
	ret = 0;

	/* iv == 0; */
	{
		vd = (int *)&d_aid.param.gamma_default[0];
		mtp = &d_aid.mtp[0];

		numerator = d_aid.param.formular[0].numerator;
		denominator = d_aid.param.formular[0].denominator;

		for (c = 0; c < CI_MAX; c++) {
			t1 = v0;
			t2 = v0*d_aid.param.vt_voltage_value[vd[c] + mtp[c]];
			point_voltages[0].rgb[c] = t1 - div_s64(t2, denominator);
		}
	}

	iv = d_aid.iv_max - 1;

	/* iv == (IV_MAX-1) ~ 1; */
	for (; iv > 0; iv--) {
		vt = &point_voltages[0];
		vp = &point_voltages[iv+1];
		vd = (int *)&d_aid.param.gamma_default[iv*CI_MAX];
		mtp = &d_aid.mtp[iv*CI_MAX];

		numerator = d_aid.param.formular[iv].numerator;
		denominator = d_aid.param.formular[iv].denominator;

		for (c = 0; c < CI_MAX; c++) {
			if (iv == 1) {
				t1 = v0;
				t2 = v0 - vp->rgb[c];
			} else if (iv == d_aid.iv_max - 1) {
				t1 = v0;
				t2 = v0;
			} else {
				t1 = vt->rgb[c];
				t2 = vt->rgb[c] - vp->rgb[c];
			}
			t2 *= vd[c] + mtp[c] + numerator;
			point_voltages[iv].rgb[c] = (t1 - div_s64(t2, denominator));
		}
	}

#ifdef DYNAMIC_AID_DEBUG
	for (iv = 0; iv < d_aid.iv_max; iv++) {
		aid_dbg("Point Voltage[%d] = ", iv);
		for (c = 0; c < CI_MAX; c++)
			aid_dbg("%lld ", point_voltages[iv].rgb[c]);
		aid_dbg("\n");
	}
#endif

	return ret;
}