static inline int maven_compute_timming()

in fbdev/matrox/matroxfb_maven.c [755:987]


static inline int maven_compute_timming(struct maven_data* md,
		struct my_timming* mt,
		struct mavenregs* m) {
	unsigned int tmpi;
	unsigned int a, bv, c;
	struct matrox_fb_info *minfo = md->primary_head;

	m->mode = minfo->outputs[1].mode;
	if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) {
		unsigned int lmargin;
		unsigned int umargin;
		unsigned int vslen;
		unsigned int hcrt;
		unsigned int slen;

		maven_init_TVdata(md, m);

		if (maven_find_exact_clocks(mt->HTotal, mt->VTotal, m) == 0)
			return -EINVAL;

		lmargin = mt->HTotal - mt->HSyncEnd;
		slen = mt->HSyncEnd - mt->HSyncStart;
		hcrt = mt->HTotal - slen - mt->delay;
		umargin = mt->VTotal - mt->VSyncEnd;
		vslen = mt->VSyncEnd - mt->VSyncStart;

		if (m->hcorr < mt->HTotal)
			hcrt += m->hcorr;
		if (hcrt > mt->HTotal)
			hcrt -= mt->HTotal;
		if (hcrt + 2 > mt->HTotal)
			hcrt = 0;	/* or issue warning? */

		/* last (first? middle?) line in picture can have different length */
		/* hlen - 2 */
		m->regs[0x96] = m->hcorr;
		m->regs[0x97] = m->hcorr >> 8;
		/* ... */
		m->regs[0x98] = 0x00; m->regs[0x99] = 0x00;
		/* hblanking end */
		m->regs[0x9A] = lmargin;	/* 100% */
		m->regs[0x9B] = lmargin >> 8;	/* 100% */
		/* who knows */
		m->regs[0x9C] = 0x04;
		m->regs[0x9D] = 0x00;
		/* htotal - 2 */
		m->regs[0xA0] = m->htotal;
		m->regs[0xA1] = m->htotal >> 8;
		/* vblanking end */
		m->regs[0xA2] = mt->VTotal - mt->VSyncStart - 1;	/* stop vblanking */
		m->regs[0xA3] = (mt->VTotal - mt->VSyncStart - 1) >> 8;
		/* something end... [A6]+1..[A8] */
		if (md->version == MGATVO_B) {
			m->regs[0xA4] = 0x04;
			m->regs[0xA5] = 0x00;
		} else {
			m->regs[0xA4] = 0x01;
			m->regs[0xA5] = 0x00;
		}
		/* something start... 0..[A4]-1 */
		m->regs[0xA6] = 0x00;
		m->regs[0xA7] = 0x00;
		/* vertical line count - 1 */
		m->regs[0xA8] = mt->VTotal - 1;
		m->regs[0xA9] = (mt->VTotal - 1) >> 8;
		/* horizontal vidrst pos */
		m->regs[0xAA] = hcrt;		/* 0 <= hcrt <= htotal - 2 */
		m->regs[0xAB] = hcrt >> 8;
		/* vertical vidrst pos */
		m->regs[0xAC] = mt->VTotal - 2;
		m->regs[0xAD] = (mt->VTotal - 2) >> 8;
		/* moves picture up/down and so on... */
		m->regs[0xAE] = 0x01; /* Fix this... 0..VTotal */
		m->regs[0xAF] = 0x00;
		{
			int hdec;
			int hlen;
			unsigned int ibmin = 4 + lmargin + mt->HDisplay;
			unsigned int ib;
			int i;

			/* Verify! */
			/* Where 94208 came from? */
			if (mt->HTotal)
				hdec = 94208 / (mt->HTotal);
			else
				hdec = 0x81;
			if (hdec > 0x81)
				hdec = 0x81;
			if (hdec < 0x41)
				hdec = 0x41;
			hdec--;
			hlen = 98304 - 128 - ((lmargin + mt->HDisplay - 8) * hdec);
			if (hlen < 0)
				hlen = 0;
			hlen = hlen >> 8;
			if (hlen > 0xFF)
				hlen = 0xFF;
			/* Now we have to compute input buffer length.
			   If you want any picture, it must be between
			     4 + lmargin + xres
			   and
			     94208 / hdec
			   If you want perfect picture even on the top
			   of screen, it must be also
			     0x3C0000 * i / hdec + Q - R / hdec
			   where
			        R      Qmin   Qmax
			     0x07000   0x5AE  0x5BF
			     0x08000   0x5CF  0x5FF
			     0x0C000   0x653  0x67F
			     0x10000   0x6F8  0x6FF
			 */
			i = 1;
			do {
				ib = ((0x3C0000 * i - 0x8000)/ hdec + 0x05E7) >> 8;
				i++;
			} while (ib < ibmin);
			if (ib >= m->htotal + 2) {
				ib = ibmin;
			}

			m->regs[0x90] = hdec;	/* < 0x40 || > 0x80 is bad... 0x80 is questionable */
			m->regs[0xC2] = hlen;
			/* 'valid' input line length */
			m->regs[0x9E] = ib;
			m->regs[0x9F] = ib >> 8;
		}
		{
			int vdec;
			int vlen;

#define MATROX_USE64BIT_DIVIDE
			if (mt->VTotal) {
#ifdef MATROX_USE64BIT_DIVIDE
				u64 f1;
				u32 a;
				u32 b;

				a = m->vlines * (m->htotal + 2);
				b = (mt->VTotal - 1) * (m->htotal + 2) + m->hcorr + 2;

				f1 = ((u64)a) << 15;	/* *32768 */
				do_div(f1, b);
				vdec = f1;
#else
				vdec = m->vlines * 32768 / mt->VTotal;
#endif
			} else
				vdec = 0x8000;
			if (vdec > 0x8000)
				vdec = 0x8000;
			vlen = (vslen + umargin + mt->VDisplay) * vdec;
			vlen = (vlen >> 16) - 146; /* FIXME: 146?! */
			if (vlen < 0)
				vlen = 0;
			if (vlen > 0xFF)
				vlen = 0xFF;
			vdec--;
			m->regs[0x91] = vdec;
			m->regs[0x92] = vdec >> 8;
			m->regs[0xBE] = vlen;
		}
		m->regs[0xB0] = 0x08;	/* output: SVideo/Composite */
		return 0;
	}

	DAC1064_calcclock(mt->pixclock, 450000, &a, &bv, &c);
	m->regs[0x80] = a;
	m->regs[0x81] = bv;
	m->regs[0x82] = c | 0x80;

	m->regs[0xB3] = 0x01;
	m->regs[0x94] = 0xB2;

	/* htotal... */
	m->regs[0x96] = mt->HTotal;
	m->regs[0x97] = mt->HTotal >> 8;
	/* ?? */
	m->regs[0x98] = 0x00;
	m->regs[0x99] = 0x00;
	/* hsync len */
	tmpi = mt->HSyncEnd - mt->HSyncStart;
	m->regs[0x9A] = tmpi;
	m->regs[0x9B] = tmpi >> 8;
	/* hblank end */
	tmpi = mt->HTotal - mt->HSyncStart;
	m->regs[0x9C] = tmpi;
	m->regs[0x9D] = tmpi >> 8;
	/* hblank start */
	tmpi += mt->HDisplay;
	m->regs[0x9E] = tmpi;
	m->regs[0x9F] = tmpi >> 8;
	/* htotal + 1 */
	tmpi = mt->HTotal + 1;
	m->regs[0xA0] = tmpi;
	m->regs[0xA1] = tmpi >> 8;
	/* vsync?! */
	tmpi = mt->VSyncEnd - mt->VSyncStart - 1;
	m->regs[0xA2] = tmpi;
	m->regs[0xA3] = tmpi >> 8;
	/* ignored? */
	tmpi = mt->VTotal - mt->VSyncStart;
	m->regs[0xA4] = tmpi;
	m->regs[0xA5] = tmpi >> 8;
	/* ignored? */
	tmpi = mt->VTotal - 1;
	m->regs[0xA6] = tmpi;
	m->regs[0xA7] = tmpi >> 8;
	/* vtotal - 1 */
	m->regs[0xA8] = tmpi;
	m->regs[0xA9] = tmpi >> 8;
	/* hor vidrst */
	tmpi = mt->HTotal - mt->delay;
	m->regs[0xAA] = tmpi;
	m->regs[0xAB] = tmpi >> 8;
	/* vert vidrst */
	tmpi = mt->VTotal - 2;
	m->regs[0xAC] = tmpi;
	m->regs[0xAD] = tmpi >> 8;
	/* ignored? */
	m->regs[0xAE] = 0x00;
	m->regs[0xAF] = 0x00;

	m->regs[0xB0] = 0x03;	/* output: monitor */
	m->regs[0xB1] = 0xA0;	/* ??? */
	m->regs[0x8C] = 0x20;	/* must be set... */
	m->regs[0x8D] = 0x04;	/* defaults to 0x10: test signal */
	m->regs[0xB9] = 0x1A;	/* defaults to 0x2C: too bright */
	m->regs[0xBF] = 0x22;	/* makes picture stable */

	return 0;
}