static void Ti3026_restore(struct matrox_fb_info *minfo)
{
	int i;
	unsigned char progdac[6];
	struct matrox_hw_state *hw = &minfo->hw;
	CRITFLAGS

	DBG(__func__)

#ifdef DEBUG
;
	for (i = 0; i < 6; i++)
;
;
#endif

	CRITBEGIN

	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);

	CRITEND

	matroxfb_vgaHWrestore(minfo);

	CRITBEGIN

	minfo->crtc1.panpos = -1;
	for (i = 0; i < 6; i++)
		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);

	for (i = 0; i < 21; i++) {
		outTi3026(minfo, DACseq[i], hw->DACreg[i]);
	}

	outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
	progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
	progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
	outTi3026(minfo, TVP3026_XPLLADDR, 0x15);
	progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
	progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
	outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
	progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
	progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);

	CRITEND
	if (memcmp(hw->DACclk, progdac, 6)) {
		/* agrhh... setting up PLL is very slow on Millennium... */
		/* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */
		/* Maybe even we should call schedule() ? */

		CRITBEGIN
		outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
		outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
		outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0);
		outTi3026(minfo, TVP3026_XPIXPLLDATA, 0);

		outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
		for (i = 0; i < 3; i++)
			outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]);
		/* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
		if (hw->MiscOutReg & 0x08) {
			int tmout;
			outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
			for (tmout = 500000; tmout; --tmout) {
				if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
					break;
				udelay(10);
			}

			CRITEND

			if (!tmout)
;
			else
;
			CRITBEGIN
		}
static void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout)
{
	unsigned int f_pll;
	unsigned int pclk_m, pclk_n, pclk_p;
	unsigned int mclk_m, mclk_n, mclk_p;
	unsigned int rfhcnt, mclk_ctl;
	int tmout;

	DBG(__func__)

	f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p);

	/* save pclk */
	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
	pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA);
	outTi3026(minfo, TVP3026_XPLLADDR, 0xFD);
	pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA);
	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
	pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA);

	/* stop pclk */
	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);

	/* set pclk to new mclk */
	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0);
	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m);
	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0);

	/* wait for PLL to lock */
	for (tmout = 500000; tmout; tmout--) {
		if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
			break;
		udelay(10);
	};
	if (!tmout)
;

	/* output pclk on mclk pin */
	mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL);
	outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7);
	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4);

	/* stop MCLK */
	outTi3026(minfo, TVP3026_XPLLADDR, 0xFB);
	outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00);

	/* set mclk to new freq */
	outTi3026(minfo, TVP3026_XPLLADDR, 0xF3);
	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0);
	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m);
	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0);

	/* wait for PLL to lock */
	for (tmout = 500000; tmout; tmout--) {
		if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40)
			break;
		udelay(10);
	}
	if (!tmout)
;

	f_pll = f_pll * 333 / (10000 << mclk_p);
	if (isMilleniumII(minfo)) {
		rfhcnt = (f_pll - 128) / 256;
		if (rfhcnt > 15)
			rfhcnt = 15;
	} else {
		rfhcnt = (f_pll - 64) / 128;
		if (rfhcnt > 15)
			rfhcnt = 0;
	}
	minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);

	/* output MCLK to MCLK pin */
	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl       ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4);

	/* stop PCLK */
	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);

	/* restore pclk */
	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n);
	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m);
	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p);

	/* wait for PLL to lock */
	for (tmout = 500000; tmout; tmout--) {
		if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
			break;
		udelay(10);
	}
	if (!tmout)
;
}
Beispiel #3
0
static void Ti3026_restore(WPMINFO2) {
    int i;
    unsigned char progdac[6];
    struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
    CRITFLAGS

    DBG(__func__)

#ifdef DEBUG
    dprintk(KERN_INFO "EXTVGA regs: ");
    for (i = 0; i < 6; i++)
        dprintk("%02X:", hw->CRTCEXT[i]);
    dprintk("\n");
#endif

    CRITBEGIN

    pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);

    CRITEND

    matroxfb_vgaHWrestore(PMINFO2);

    CRITBEGIN

    ACCESS_FBINFO(crtc1.panpos) = -1;
    for (i = 0; i < 6; i++)
        mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);

    for (i = 0; i < 21; i++) {
        outTi3026(PMINFO DACseq[i], hw->DACreg[i]);
    }

    outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
    progdac[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
    progdac[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
    outTi3026(PMINFO TVP3026_XPLLADDR, 0x15);
    progdac[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
    progdac[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
    outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
    progdac[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
    progdac[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);

    CRITEND
    if (memcmp(hw->DACclk, progdac, 6)) {
        /* agrhh... setting up PLL is very slow on Millennium... */
        /* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */
        /* Maybe even we should call schedule() ? */

        CRITBEGIN
        outTi3026(PMINFO TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
        outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
        outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0);
        outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0);

        outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
        for (i = 0; i < 3; i++)
            outTi3026(PMINFO TVP3026_XPIXPLLDATA, hw->DACclk[i]);
        /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
        if (hw->MiscOutReg & 0x08) {
            int tmout;
            outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F);
            for (tmout = 500000; tmout; --tmout) {
                if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40)
                    break;
                udelay(10);
            }

            CRITEND

            if (!tmout)
                printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
            else
                dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
            CRITBEGIN
        }
Beispiel #4
0
static void ti3026_setMCLK(WPMINFO int fout){
    unsigned int f_pll;
    unsigned int pclk_m, pclk_n, pclk_p;
    unsigned int mclk_m, mclk_n, mclk_p;
    unsigned int rfhcnt, mclk_ctl;
    int tmout;

    DBG(__func__)

    f_pll = Ti3026_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &mclk_n, &mclk_m, &mclk_p);

    /* save pclk */
    outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC);
    pclk_n = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
    outTi3026(PMINFO TVP3026_XPLLADDR, 0xFD);
    pclk_m = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
    outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE);
    pclk_p = inTi3026(PMINFO TVP3026_XPIXPLLDATA);

    /* stop pclk */
    outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE);
    outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00);

    /* set pclk to new mclk */
    outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC);
    outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_n | 0xC0);
    outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_m);
    outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_p | 0xB0);

    /* wait for PLL to lock */
    for (tmout = 500000; tmout; tmout--) {
        if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40)
            break;
        udelay(10);
    };
    if (!tmout)
        printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n");

    /* output pclk on mclk pin */
    mclk_ctl = inTi3026(PMINFO TVP3026_XMEMPLLCTRL);
    outTi3026(PMINFO TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7);
    outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4);

    /* stop MCLK */
    outTi3026(PMINFO TVP3026_XPLLADDR, 0xFB);
    outTi3026(PMINFO TVP3026_XMEMPLLDATA, 0x00);

    /* set mclk to new freq */
    outTi3026(PMINFO TVP3026_XPLLADDR, 0xF3);
    outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_n | 0xC0);
    outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_m);
    outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_p | 0xB0);

    /* wait for PLL to lock */
    for (tmout = 500000; tmout; tmout--) {
        if (inTi3026(PMINFO TVP3026_XMEMPLLDATA) & 0x40)
            break;
        udelay(10);
    }
    if (!tmout)
        printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n");

    f_pll = f_pll * 333 / (10000 << mclk_p);
    if (isMilleniumII(MINFO)) {
        rfhcnt = (f_pll - 128) / 256;
        if (rfhcnt > 15)
            rfhcnt = 15;
    } else {
        rfhcnt = (f_pll - 64) / 128;
        if (rfhcnt > 15)
            rfhcnt = 0;
    }
    ACCESS_FBINFO(hw).MXoptionReg = (ACCESS_FBINFO(hw).MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
    pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);

    /* output MCLK to MCLK pin */
    outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
    outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl       ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4);

    /* stop PCLK */
    outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE);
    outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00);

    /* restore pclk */
    outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC);
    outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_n);
    outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_m);
    outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_p);

    /* wait for PLL to lock */
    for (tmout = 500000; tmout; tmout--) {
        if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40)
            break;
        udelay(10);
    }
    if (!tmout)
        printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
}
Beispiel #5
0
bool DacTVP3026::SetPixPLL( long vTargetFrequency, int nDepth )
{
	short nN, nM, nP;
	short nLm, nLn, nLp, nLq;
	int i;
	short nMiscCtrl = 0, nLatchCtrl = 0, nTcolCtrl = 0, nMulCtrl = 0;
	bool bRet = false;

	bRet = CalcPixPLL( vTargetFrequency/1000, TI_MAX_PCLK_FREQ, &nN, &nM, &nP );
	if( bRet )
	{
		dbprintf("Got N=%i M=%i P=%i for target frequency of %li\n", nN, nM, nP, (long)vTargetFrequency );

		m_nDacClk[ 0 ] = ( nN & 0x3f ) | 0xc0;
		m_nDacClk[ 1 ] = ( nM & 0x3f );
		m_nDacClk[ 2 ] = ( nP & 0x03 ) | 0xb0;

		// Now that the pixel clock PLL is setup,
		// the loop clock PLL must be setup.
		bRet = CalcLoopPLL( (double)vTargetFrequency/1000, nDepth, &nLn, &nLm, &nLp, &nLq );
		if( bRet )
		{
			dbprintf("Got N=%i M=%i P=%i Q=%i for target frequency of %li\n", nLn, nLm, nLp, nLq, (long)vTargetFrequency );

			// Values for the loop clock PLL registers
			if ( nDepth == 24 )
			{
				// Packed pixel mode values
				m_nDacClk[ 3 ] = ( nLn & 0x3f ) | 0x80;
				m_nDacClk[ 4 ] = ( nLm & 0x3f ) | 0x80;
				m_nDacClk[ 5 ] = ( nLp & 0x03 ) | 0xf8;
			}
			else
			{
				// Non-packed pixel mode values
				m_nDacClk[ 3 ] = ( nLn & 0x3f ) | 0xc0;
				m_nDacClk[ 4 ] = ( nLm & 0x3f );
				m_nDacClk[ 5 ] = ( nLp & 0x03 ) | 0xf0;
			}
			m_nDacClk[ 7 ] = nLq | 0x38;	// pReg->DacRegs[ 18 ]
		}
		else
		{
			dbprintf("Unable to get Loop PLL timing values fortarget frequency %li\n", (long int)vTargetFrequency );
			return( false );
		}
	}
	else
	{
		dbprintf("Unable to get Pix PLL timing values for target frequency %li\n", (long int)vTargetFrequency );
		return( false );
	}

	// Now program the Pixel & Loop PLL with the values we have calculated
	//
	// Set loop and pixel clock PLL PLLEN bits to 0
	outTi3026(TVP3026_PLL_ADDR, 0, 0x2A);
	outTi3026(TVP3026_LOAD_CLK_DATA, 0, 0);
	outTi3026(TVP3026_PIX_CLK_DATA, 0, 0);

	// Program pixel clock PLL
	outTi3026(TVP3026_PLL_ADDR, 0, 0x00);
	for (i = 0; i < 3; i++)
		outTi3026(TVP3026_PIX_CLK_DATA, 0, m_nDacClk[i]);

	// Poll until pixel clock PLL LOCK bit is set
	outTi3026(TVP3026_PLL_ADDR, 0, 0x3F);
	while ( ! (inTi3026(TVP3026_PIX_CLK_DATA) & 0x40) );

	dbprintf("Pixel Clock PLL locked\n");

	// Select pixel clock PLL as clock source
	switch( nDepth )
	{
		case 15:
		case 16:
			outTi3026(TVP3026_CLK_SEL, 0, 0x15);	// Dot Clock / 2, select PIX PLL as source
			break;

		case 24:
			outTi3026(TVP3026_CLK_SEL, 0, 0x25);	// Dot Clock / 4, select PIX PLL as source
			break;

		case 32:
			outTi3026(TVP3026_CLK_SEL, 0, 0x05);	// Dot Clock / 0, select PIX PLL as source
			break;
	}

	// Set Q divider for loop clock PLL
	outTi3026(TVP3026_MCLK_CTL, 0, m_nDacClk[7]);

	// Program loop PLL
	outTi3026(TVP3026_PLL_ADDR, 0, 0x00);
	for (i = 3; i < 6; i++)
		outTi3026(TVP3026_LOAD_CLK_DATA, 0, m_nDacClk[i]);

	// Poll until loop PLL LOCK bit is set
	outTi3026(TVP3026_PLL_ADDR, 0, 0x3F);
	while ( ! (inTi3026(TVP3026_LOAD_CLK_DATA) & 0x40) );

	dbprintf("Loop Clock PLL locked\n");

	SetMemPLL( vTargetFrequency/1000 );

	// Set the correct values for the Misc, Latch, True Color Control &
	// Multiplex Control registers
	//
	// Consult Table 2-17 of the TVP3026 manual for the TCOLCTRL & MULCTRL
	// values

	switch( nDepth )
	{
		case 15:
		{
			nMiscCtrl = 0x20;		// Set PSEL to select True Color
			nLatchCtrl = 0x06;	// 1:1. 2:1, 8:1 & 16:1 multiplex modes
			nTcolCtrl = 0x44;		// 16bit X-R-G-B
			nMulCtrl = 0x54;		// 32bit Pixel Bus, interlaced

			break;
		}

		case 16:
		{
			nMiscCtrl = 0x20;		// Set PSEL to select True Color
			nLatchCtrl = 0x06;	// 1:1. 2:1, 8:1 & 16:1 multiplex modes
			nTcolCtrl = 0x45;		// 16bit R-G-B
			nMulCtrl = 0x54;		// 32bit Pixel Bus, interlaced

			break;
		}

		case 24:
		{
			nMiscCtrl = 0x20;		// Set PSEL to select True Color
			nLatchCtrl = 0x07;	// 2:1 multiplex mode or 8:3 Packed 24bit or 4:3 packed 24bit
			nTcolCtrl = 0x56;		// 24bit R-G-B
			nMulCtrl = 0x5c;		// 32bit Pixel Bus, interlaced

			break;
		}

		case 32:
		{
			nMiscCtrl = 0x20;		// Set PSEL to select True Color
			nLatchCtrl = 0x07;	// 2:1 multiplex mode or 8:3 Packed 24bit or 4:3 packed 24bit
			nTcolCtrl = 0x46;		// 32bit X-R-G-B
			nMulCtrl = 0x5c;		// 32bit Pixel Bus, interlaced

			break;
		}
	}

	outTi3026( TVP3026_MISCCTRL, 0, nMiscCtrl );			// Misc. Control
	outTi3026( TVP3026_LATCHCTRL, 0, nLatchCtrl  );		// Latch Control
	outTi3026( TVP3026_TCOLCTRL, 0, nTcolCtrl );			// True Color Control
	outTi3026( TVP3026_MULCTRL, 0, nMulCtrl );			// Multiplex Control

	dbprintf("DacTVP3026::SetPixPLL has completed\n");
	return( bRet );
}
Beispiel #6
0
bool DacTVP3026::SetMemPLL( long vTarget )
{
	double f_pll;
	int mclk_m, mclk_n, mclk_p;
	int pclk_m, pclk_n, pclk_p;
	int mclk_ctl;

	f_pll = (double)vTarget;
	CalcPixPLL( vTarget, TI_MAX_MCLK_FREQ, (short*)&mclk_m, (short*)&mclk_n, (short*)&mclk_p );

	/* Save PCLK settings */
	outTi3026( TVP3026_PLL_ADDR, 0, 0xfc );
	pclk_n = inTi3026( TVP3026_PIX_CLK_DATA );
	outTi3026( TVP3026_PLL_ADDR, 0, 0xfd );
	pclk_m = inTi3026( TVP3026_PIX_CLK_DATA );
	outTi3026( TVP3026_PLL_ADDR, 0, 0xfe );
	pclk_p = inTi3026( TVP3026_PIX_CLK_DATA );
	
	/* Stop PCLK (PLLEN = 0, PCLKEN = 0) */
	outTi3026( TVP3026_PLL_ADDR, 0, 0xfe );
	outTi3026( TVP3026_PIX_CLK_DATA, 0, 0x00 );
	
	/* Set PCLK to the new MCLK frequency (PLLEN = 1, PCLKEN = 0 ) */
	outTi3026( TVP3026_PLL_ADDR, 0, 0xfc );
	outTi3026( TVP3026_PIX_CLK_DATA, 0, ( mclk_n & 0x3f ) | 0xc0 );
	outTi3026( TVP3026_PIX_CLK_DATA, 0, mclk_m & 0x3f );
	outTi3026( TVP3026_PIX_CLK_DATA, 0, ( mclk_p & 0x03 ) | 0xb0 );
	
	/* Wait for PCLK PLL to lock on frequency */
	while (( inTi3026( TVP3026_PIX_CLK_DATA ) & 0x40 ) == 0 );
	
	/* Output PCLK on MCLK pin */
	mclk_ctl = inTi3026( TVP3026_MCLK_CTL );
	outTi3026( TVP3026_MCLK_CTL, 0, mclk_ctl & 0xe7 ); 
	outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x08 );
	
	/* Stop MCLK (PLLEN = 0 ) */
	outTi3026( TVP3026_PLL_ADDR, 0, 0xfb );
	outTi3026( TVP3026_MEM_CLK_DATA, 0, 0x00 );
	
	/* Set MCLK to the new frequency (PLLEN = 1) */
	outTi3026( TVP3026_PLL_ADDR, 0, 0xf3 );
	outTi3026( TVP3026_MEM_CLK_DATA, 0, ( mclk_n & 0x3f ) | 0xc0 );
	outTi3026( TVP3026_MEM_CLK_DATA, 0, mclk_m & 0x3f );
	outTi3026( TVP3026_MEM_CLK_DATA, 0, ( mclk_p & 0x03 ) | 0xb0 );
	
	/* Wait for MCLK PLL to lock on frequency */
	while (( inTi3026( TVP3026_MEM_CLK_DATA ) & 0x40 ) == 0 );

	/* Output MCLK PLL on MCLK pin */
	outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x10 );
	outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x18 );
	
	/* Stop PCLK (PLLEN = 0, PCLKEN = 0 ) */
	outTi3026( TVP3026_PLL_ADDR, 0, 0xfe );
	outTi3026( TVP3026_PIX_CLK_DATA, 0, 0x00 );
	
	/* Restore PCLK (PLLEN = ?, PCLKEN = ?) */
	outTi3026( TVP3026_PLL_ADDR, 0, 0xfc );
	outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_n );
	outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_m );
	outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_p );
	
	/* Wait for PCLK PLL to lock on frequency */
	while (( inTi3026( TVP3026_PIX_CLK_DATA ) & 0x40 ) == 0 );

	return( true );
}