All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jim Ramsay <jim.ramsay@gmail.com>
To: James Simmons <jsimmons@infradead.org>
Cc: yhlu <yhlu.kernel@gmail.com>,
	"Daniël Mantione" <daniel@deadlock.et.tudelft.nl>,
	alex.kern@gmx.de, "Linux Kernel" <linux-kernel@vger.kernel.org>
Subject: Re: Atyfb questions and issues
Date: Mon, 15 Aug 2005 13:21:45 -0600	[thread overview]
Message-ID: <4789af9e0508151221486d0003@mail.gmail.com> (raw)
In-Reply-To: <Pine.LNX.4.56.0508151733160.7300@pentafluge.infradead.org>

[-- Attachment #1: Type: text/plain, Size: 1332 bytes --]

On 8/15/05, James Simmons <jsimmons@infradead.org> wrote:
> 
> > > I wonder if James put that in mainstream, he already sent one patch
> > > for 2.6.5....
> > >
> > > please refer to
> > > http://www.linuxbios.org/pipermail/linuxbios/2004-May/007734.html
> >
> > It appears to me that this patch is in the 2.6.11 from linux-mips.org
> > that I am presently using.
> 
> Its in the standard tree as well. The question is does it work in the mips
> branch? Last time I tried booting without the bios it did not work. Yhlu
> is right, atyfb_setup_generic is called which in x86 calls the
> init_from_bios function. Then in aty_init is the biosless initializing is
> done.
> 
> > Maybe his mips FW does this, but mine doesn't.  Any tips on how I can
> > do this in software?
> 
> The idea of the patch is not to need FW.

Of course.

How about the replacement for 'xlinit.c' I have attached here?

I noticed that the big difference between what the 2.4 kernel and 2.6
kernel did is that the 'var_to_pll' (and its component functions) in
2.4 did a lot more probing than that in the 2.6 kernel.

So I copied the relevant 2.4 bits for non-i386 archs, and replaced the
call to 'var_to_pll' with the "new" stuff.

This seems to work for me.  Enjoy!

-- 
Jim Ramsay
"Me fail English?  That's unpossible!"

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: xlinit.c --]
[-- Type: text/x-csrc; name="xlinit.c", Size: 17864 bytes --]

/*
 *  ATI Rage XL Initialization. Support for Xpert98 and Victoria
 *  PCI cards.
 *
 *  Copyright (C) 2002 MontaVista Software Inc.
 *  Author: MontaVista Software, Inc.
 *         	stevel@mvista.com or source@mvista.com
 *
 *  This program is free software; you can redistribute  it and/or modify it
 *  under  the terms of  the GNU General  Public License as published by the
 *  Free Software Foundation;  either version 2 of the  License, or (at your
 *  option) any later version.
 *
 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *  You should have received a copy of the  GNU General Public License along
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h> 
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <video/mach64.h>
#include "atyfb.h"

#define MPLL_GAIN       0xad
#define VPLL_GAIN       0xd5

enum {
	VICTORIA = 0,
	XPERT98,
	NUM_XL_CARDS
};

extern const struct aty_pll_ops aty_pll_ct;

#define DEFAULT_CARD XPERT98
static int xl_card = DEFAULT_CARD;

static const struct xl_card_cfg_t {
	int ref_crystal; // 10^4 Hz
	int mem_type;
	int mem_size;
	u32 mem_cntl;
	u32 ext_mem_cntl;
	u32 mem_addr_config;
	u32 bus_cntl;
	u32 dac_cntl;
	u32 hw_debug;
	u32 custom_macro_cntl;
	u8  dll2_cntl;
	u8  pll_yclk_cntl;
} card_cfg[NUM_XL_CARDS] = {
	// VICTORIA
	{	2700, SDRAM, 0x800000,
		0x10757A3B, 0x64000C81, 0x00110202, 0x7b33A040,
		0x82010102, 0x48803800, 0x005E0179,
		0x50, 0x25
	},
	// XPERT98
	{	1432,  WRAM, 0x800000,
		0x00165A2B, 0xE0000CF1, 0x00200213, 0x7333A001,
		0x8000000A, 0x48833800, 0x007F0779,
		0x10, 0x19
	}
};
	  
typedef struct {
	u8 lcd_reg;
	u32 val;
} lcd_tbl_t;

static const lcd_tbl_t lcd_tbl[] = {
	{ 0x01,	0x000520C0 },
	{ 0x08,	0x02000408 },
	{ 0x03,	0x00000F00 },
	{ 0x00,	0x00000000 },
	{ 0x02,	0x00000000 },
	{ 0x04,	0x00000000 },
	{ 0x05,	0x00000000 },
	{ 0x06,	0x00000000 },
	{ 0x33,	0x00000000 },
	{ 0x34,	0x00000000 },
	{ 0x35,	0x00000000 },
	{ 0x36,	0x00000000 },
	{ 0x37,	0x00000000 }
};

static void reset_gui(struct atyfb_par *par)
{
	aty_st_8(GEN_TEST_CNTL+1, 0x01, par);
	aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
	aty_st_8(GEN_TEST_CNTL+1, 0x02, par);
	mdelay(5);
}

static void reset_sdram(struct atyfb_par *par)
{
	u8 temp;

	temp = aty_ld_8(EXT_MEM_CNTL, par);
	temp |= 0x02;
	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_RESET = 1b
	temp |= 0x08;
	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST    = 10b
	temp |= 0x0c;
	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST    = 11b
	mdelay(5);
	temp &= 0xf3;
	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST    = 00b
	temp &= 0xfd;
	aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_REST  = 0b
	mdelay(5);
}

static void init_dll(struct atyfb_par *par)
{
	// enable DLL
	aty_st_pll_ct(PLL_GEN_CNTL,
		   aty_ld_pll_ct(PLL_GEN_CNTL, par) & 0x7f,
		   par);

	// reset DLL
	aty_st_pll_ct(DLL_CNTL, 0x82, par);
	aty_st_pll_ct(DLL_CNTL, 0xE2, par);
	mdelay(5);
	aty_st_pll_ct(DLL_CNTL, 0x82, par);
	mdelay(6);
}

static void reset_clocks(struct atyfb_par *par, struct pll_ct *pll,
			 int hsync_enb)
{
	reset_gui(par);
	aty_st_pll_ct(MCLK_FB_DIV, pll->mclk_fb_div, par);
	aty_st_pll_ct(SCLK_FB_DIV, pll->sclk_fb_div, par);

	mdelay(15);
	init_dll(par);
	aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
	mdelay(5);
	aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
	mdelay(6);
	reset_sdram(par);
	aty_st_8(CRTC_GEN_CNTL+3,
		 hsync_enb ? 0x00 : 0x04, par);

	aty_st_pll_ct(SPLL_CNTL2, pll->spll_cntl2, par);
	aty_st_pll_ct(PLL_GEN_CNTL, pll->pll_gen_cntl, par);
	aty_st_pll_ct(PLL_VCLK_CNTL, pll->pll_vclk_cntl, par);
}

#ifndef __i386__
/*
 * These 3 routines (init_valid_pll_ct, init_dsp_gt, init_calc_pll_ct)
 * are copied from the 2.4 initialization which properly initializes a
 * bios-less chip.
 *
 * The i386 version includes code which uses the bios init instead, so
 * these are unnecessary there.
 */

#define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)

static int init_valid_pll_ct(const struct fb_info *info, u32 vclk_per,
                            struct pll_ct *pll)
{
#ifdef DEBUG
    int pllmclk, pllsclk;
#endif
    u32 q;
    struct atyfb_par *par = (struct atyfb_par *) info->par;

    pll->pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;

    /* FIXME: use the VTB/GTB /3 post divider if it's better suited */

    /* actually 8*q */
    q = par->ref_clk_per*pll->pll_ref_div*4/par->mclk_per;

    if (q < 16*8 || q > 255*8)
        FAIL("mclk out of range");
    else if (q < 32*8)
        pll->mclk_post_div_real = 8;
    else if (q < 64*8)
        pll->mclk_post_div_real = 4;
    else if (q < 128*8)
        pll->mclk_post_div_real = 2;
    else
        pll->mclk_post_div_real = 1;
    pll->sclk_fb_div = q*pll->mclk_post_div_real/8;

#ifdef DEBUG
    pllsclk = (1000000 * 2 * pll->sclk_fb_div) /
            (par->ref_clk_per * pll->pll_ref_div);
    printk(__FUNCTION__ ": pllsclk=%d MHz, mclk=%d MHz\n",
           pllsclk, pllsclk / pll->mclk_post_div_real);
#endif

    pll->mclk_fb_mult = M64_HAS(MFB_FORCE_4) ? 4 : 2;

    /* actually 8*q */
    q = par->ref_clk_per * pll->pll_ref_div * 8 /
            (pll->mclk_fb_mult * par->xclk_per);

    if (q < 16*8 || q > 255*8)
        FAIL("mclk out of range");
    else if (q < 32*8)
        pll->xclk_post_div_real = 8;
    else if (q < 64*8)
        pll->xclk_post_div_real = 4;
    else if (q < 128*8)
        pll->xclk_post_div_real = 2;
    else
        pll->xclk_post_div_real = 1;
    pll->mclk_fb_div = q*pll->xclk_post_div_real/8;

#ifdef DEBUG
    pllmclk = (1000000 * pll->mclk_fb_mult * pll->mclk_fb_div) /
            (par->ref_clk_per * pll->pll_ref_div);
    printk(__FUNCTION__ ": pllmclk=%d MHz, xclk=%d MHz\n",
           pllmclk, pllmclk / pll->xclk_post_div_real);
#endif

    /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
    q = par->ref_clk_per*pll->pll_ref_div*4/vclk_per;  /* actually 8*q */
    if (q < 16*8 || q > 255*8)
        FAIL("vclk out of range");
    else if (q < 32*8)
        pll->vclk_post_div_real = 8;
    else if (q < 64*8)
        pll->vclk_post_div_real = 4;
    else if (q < 128*8)
        pll->vclk_post_div_real = 2;
    else
        pll->vclk_post_div_real = 1;
    pll->vclk_fb_div = q*pll->vclk_post_div_real/8;
    return 0;
}

static int init_dsp_gt(const struct fb_info *info, u32 bpp,
                      struct pll_ct *pll)
{
    struct atyfb_par *par = (struct atyfb_par *) info->par;
    u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on;
    u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size;
    u32 memcntl, n, t_pfc, t_rp, t_ras, t_rcd, t_crd, t_rcc, t_lat;

#ifdef DEBUG
    printk(__FUNCTION__ ": mclk_fb_mult=%d\n", pll->mclk_fb_mult);
#endif

    /* (64*xclk/vclk/bpp)<<11 = xclocks_per_row<<11 */
    xclks_per_row = ((u32)pll->mclk_fb_mult * (u32)pll->mclk_fb_div *
                     (u32)pll->vclk_post_div_real * 64) << 11;
    xclks_per_row /=
            (2 * (u32)pll->vclk_fb_div * (u32)pll->xclk_post_div_real * bpp);

    if (xclks_per_row < (1<<11))
        FAIL("Dotclock too high");
    if (M64_HAS(FIFO_32)) {
        fifo_size = 32;
        dsp_loop_latency = 2;
    } else {
        fifo_size = 24;
        dsp_loop_latency = 0;
    }
    dsp_precision = 0;
    y = (xclks_per_row*fifo_size)>>11;
    while (y) {
        y >>= 1;
        dsp_precision++;
    }
    dsp_precision -= 5;

    /* fifo_off<<6 */
    fifo_off = ((xclks_per_row*(fifo_size-1))>>5); // + (3<<6);

    if (info->fix.smem_len > 1*1024*1024) {
        switch (par->ram_type) {
        case WRAM:
            /* >1 MB WRAM */
            dsp_loop_latency += 9;
            n = 4;
            break;
        case SDRAM:
        case SGRAM:
            /* >1 MB SDRAM */
            dsp_loop_latency += 8;
            n = 2;
            break;
        default:
            /* >1 MB DRAM */
            dsp_loop_latency += 6;
            n = 3;
            break;
        }
    } else {
        if (par->ram_type >= SDRAM) {
            /* <2 MB SDRAM */
            dsp_loop_latency += 9;
            n = 2;
        } else {
            /* <2 MB DRAM */
            dsp_loop_latency += 8;
            n = 3;
        }
    }

    memcntl = aty_ld_le32(MEM_CNTL, par);
    t_rcd = ((memcntl >> 10) & 0x03) + 1;
    t_crd = ((memcntl >> 12) & 0x01);
    t_rp  = ((memcntl >>  8) & 0x03) + 1;
    t_ras = ((memcntl >> 16) & 0x07) + 1;
    t_lat =  (memcntl >>  4) & 0x03;

    t_pfc = t_rp + t_rcd + t_crd;

    t_rcc = max(t_rp + t_ras, t_pfc + n);

    /* fifo_on<<6 */
    fifo_on = (2 * t_rcc + t_pfc + n - 1) << 6;

    dsp_xclks_per_row = xclks_per_row>>dsp_precision;
    dsp_on = fifo_on>>dsp_precision;
    dsp_off = fifo_off>>dsp_precision;

    pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
                      ((dsp_loop_latency & 0xf)<<16) |
                      ((dsp_precision & 7)<<20);
    pll->dsp_on_off = (dsp_off & 0x7ff) | ((dsp_on & 0x7ff)<<16);
    return 0;
}

void init_calc_pll_ct(const struct fb_info *info, struct pll_ct *pll)
{
    struct atyfb_par *par = (struct atyfb_par *) info->par;
    u8 xpostdiv = 0;
    u8 mpostdiv = 0;  
    u8 vpostdiv = 0;  
    
    if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
            pll->pll_gen_cntl = 0x64; /* mclk = sclk */
    else
        pll->pll_gen_cntl = 0xe4; /* mclk = sclk */

    switch (pll->mclk_post_div_real) {
        case 1:
            mpostdiv = 0;
            break;
        case 2:
            mpostdiv = 1;
            break;
        case 4:
            mpostdiv = 2;
            break;
        case 8:
            mpostdiv = 3;
            break;
    }       
    
    pll->spll_cntl2 = mpostdiv << 4; /* sclk == pllsclk / mpostdiv */
    
    switch (pll->xclk_post_div_real) {
        case 1:
            xpostdiv = 0;
            break;
        case 2:
            xpostdiv = 1;
            break;
        case 3:
            xpostdiv = 4;
            break;
        case 4:
            xpostdiv = 2;
            break;
        case 8:
            xpostdiv = 3;
            break;
    }

    if (M64_HAS(MAGIC_POSTDIV))
        pll->pll_ext_cntl = 0;
    else
        pll->pll_ext_cntl = xpostdiv;   /* xclk == pllmclk / xpostdiv */

    if (pll->mclk_fb_mult == 4)
            pll->pll_ext_cntl |= 0x08;

    switch (pll->vclk_post_div_real) {
        case 2:
            vpostdiv = 1;
            break;
        case 3:
            pll->pll_ext_cntl |= 0x10;
        case 1:
            vpostdiv = 0;
            break;
        case 6:
            pll->pll_ext_cntl |= 0x10;
        case 4:
            vpostdiv = 2;
            break;
        case 12:
            pll->pll_ext_cntl |= 0x10;
        case 8:
            vpostdiv = 3;
            break;
    }

    pll->pll_vclk_cntl = 0x03;  /* VCLK = PLL_VCLK/VCLKx_POST */
    pll->vclk_post_div = vpostdiv;
}
#endif // __i386__

int atyfb_xl_init(struct fb_info *info)
{
	const struct xl_card_cfg_t * card = &card_cfg[xl_card];
	struct atyfb_par *par = (struct atyfb_par *) info->par;
	union aty_pll pll;
	int err;
	u32 temp;

	aty_st_8(CONFIG_STAT0, 0x85, par);
	mdelay(10);

	/*
	 * The following needs to be set before the call
	 * to var_to_pll() below. They'll be re-set again
	 * to the same values in aty_init().
	 */
	par->ref_clk_per = 100000000UL/card->ref_crystal;
	par->ram_type = card->mem_type;
	info->fix.smem_len = card->mem_size;
	if (xl_card == VICTORIA) {
		// the MCLK, XCLK are 120MHz on victoria card
		par->mclk_per = 1000000/120;
		par->xclk_per = 1000000/120;
		par->features &= ~M64F_MFB_FORCE_4;
	}

	/*
	 * Calculate mclk and xclk dividers, etc. The passed
	 * pixclock and bpp values don't matter yet, the vclk
	 * isn't programmed until later.
	 */
#ifndef __i386__
	// These were stolen from the working 2.4 kernel xlinit.c
	// This is what 'var_to_pll' used to do.
	if( (err = init_valid_pll_ct( info, 39726, &(pll.ct) ) ) )
		return err;
	if( M64_HAS(GTB_DSP) && (err = init_dsp_gt( info, 8, &(pll.ct) ) ) )
		return err;
	init_calc_pll_ct( info, &(pll.ct) );
#else
	// The current 'var_to_pll' assumes you have already called
	// 'init_from_bios' which only occurrs for __i386__
	if ((err = aty_pll_ct.var_to_pll(info, 39726, 8, &pll)))
		return err;
#endif

	aty_st_pll_ct(LVDS_CNTL0, 0x00, par);
	aty_st_pll_ct(DLL2_CNTL, card->dll2_cntl, par);
	aty_st_pll_ct(V2PLL_CNTL, 0x10, par);
	aty_st_pll_ct(MPLL_CNTL, MPLL_GAIN, par);
	aty_st_pll_ct(VPLL_CNTL, VPLL_GAIN, par);
	aty_st_pll_ct(PLL_VCLK_CNTL, 0x00, par);
	aty_st_pll_ct(VFC_CNTL, 0x1B, par);
	aty_st_pll_ct(PLL_REF_DIV, pll.ct.pll_ref_div, par);
	aty_st_pll_ct(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, par);
	aty_st_pll_ct(SPLL_CNTL2, 0x03, par);
	aty_st_pll_ct(PLL_GEN_CNTL, 0x44, par);

	reset_clocks(par, &pll.ct, 0);
	mdelay(10);

	aty_st_pll_ct(VCLK_POST_DIV, 0x03, par);
	aty_st_pll_ct(VCLK0_FB_DIV, 0xDA, par);
	aty_st_pll_ct(VCLK_POST_DIV, 0x0F, par);
	aty_st_pll_ct(VCLK1_FB_DIV, 0xF5, par);
	aty_st_pll_ct(VCLK_POST_DIV, 0x3F, par);
	aty_st_pll_ct(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, par);
	aty_st_pll_ct(VCLK2_FB_DIV, 0x00, par);
	aty_st_pll_ct(VCLK_POST_DIV, 0xFF, par);
	aty_st_pll_ct(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, par);
	aty_st_pll_ct(VCLK3_FB_DIV, 0x00, par);

	aty_st_8(BUS_CNTL, 0x01, par);
	aty_st_le32(BUS_CNTL, card->bus_cntl | 0x08000000, par);

	aty_st_le32(CRTC_GEN_CNTL, 0x04000200, par);
	aty_st_le16(CONFIG_STAT0, 0x0020, par);
	aty_st_le32(MEM_CNTL, 0x10151A33, par);
	aty_st_le32(EXT_MEM_CNTL, 0xE0000C01, par);
	aty_st_le16(CRTC_GEN_CNTL+2, 0x0000, par);
	aty_st_le32(DAC_CNTL, card->dac_cntl, par);
	aty_st_le16(GEN_TEST_CNTL, 0x0100, par);
	aty_st_le32(CUSTOM_MACRO_CNTL, 0x003C0171, par);
	aty_st_le32(MEM_BUF_CNTL, 0x00382848, par);

	aty_st_le32(HW_DEBUG, card->hw_debug, par);
	aty_st_le16(MEM_ADDR_CONFIG, 0x0000, par);
	aty_st_le16(GP_IO+2, 0x0000, par);
	aty_st_le16(GEN_TEST_CNTL, 0x0000, par);
	aty_st_le16(EXT_DAC_REGS+2, 0x0000, par);
	aty_st_le32(CRTC_INT_CNTL, 0x00000000, par);
	aty_st_le32(TIMER_CONFIG, 0x00000000, par);
	aty_st_le32(0xEC, 0x00000000, par);
	aty_st_le32(0xFC, 0x00000000, par);

#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
	{
	int i;
	for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); i++) {
		aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par);
	}
	}
#endif

	aty_st_le16(CONFIG_STAT0, 0x00A4, par);
	mdelay(10);

	aty_st_8(BUS_CNTL+1, 0xA0, par);
	mdelay(10);
	
	reset_clocks(par, &pll.ct, 1);
	mdelay(10);

	// something about power management
	aty_st_8(LCD_INDEX, 0x08, par);
	aty_st_8(LCD_DATA, 0x0A, par);
	aty_st_8(LCD_INDEX, 0x08, par);
	aty_st_8(LCD_DATA+3, 0x02, par);
	aty_st_8(LCD_INDEX, 0x08, par);
	aty_st_8(LCD_DATA, 0x0B, par);
	mdelay(2);
	
	// enable display requests, enable CRTC
	aty_st_8(CRTC_GEN_CNTL+3, 0x02, par);
	// disable display
	aty_st_8(CRTC_GEN_CNTL, 0x40, par);
	// disable display requests, disable CRTC
	aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
	mdelay(10);

	aty_st_pll_ct(PLL_YCLK_CNTL, 0x25, par);

	aty_st_le16(CUSTOM_MACRO_CNTL, 0x0179, par);
	aty_st_le16(CUSTOM_MACRO_CNTL+2, 0x005E, par);
	aty_st_le16(CUSTOM_MACRO_CNTL+2, card->custom_macro_cntl>>16, par);
	aty_st_8(CUSTOM_MACRO_CNTL+1,
		 (card->custom_macro_cntl>>8) & 0xff, par);

	aty_st_le32(MEM_ADDR_CONFIG, card->mem_addr_config, par);
	aty_st_le32(MEM_CNTL, card->mem_cntl, par);
	aty_st_le32(EXT_MEM_CNTL, card->ext_mem_cntl, par);

	aty_st_8(CONFIG_STAT0, 0xA0 | card->mem_type, par);

	aty_st_pll_ct(PLL_YCLK_CNTL, 0x01, par);
	mdelay(15);
	aty_st_pll_ct(PLL_YCLK_CNTL, card->pll_yclk_cntl, par);
	mdelay(1);
	
	reset_clocks(par, &pll.ct, 0);
	mdelay(50);
	reset_clocks(par, &pll.ct, 0);
	mdelay(50);

	// enable extended register block
	aty_st_8(BUS_CNTL+3, 0x7B, par);
	mdelay(1);
	// disable extended register block
	aty_st_8(BUS_CNTL+3, 0x73, par);

	aty_st_8(CONFIG_STAT0, 0x80 | card->mem_type, par);

	// disable display requests, disable CRTC
	aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
	// disable mapping registers in VGA aperture
	aty_st_8(CONFIG_CNTL, aty_ld_8(CONFIG_CNTL, par) & ~0x04, par);
	mdelay(50);
	// enable display requests, enable CRTC
	aty_st_8(CRTC_GEN_CNTL+3, 0x02, par);

	// make GPIO's 14,15,16 all inputs
	aty_st_8(LCD_INDEX, 0x07, par);
	aty_st_8(LCD_DATA+3, 0x00, par);

	// enable the display
	aty_st_8(CRTC_GEN_CNTL, 0x00, par);
	mdelay(17);
	// reset the memory controller
	aty_st_8(GEN_TEST_CNTL+1, 0x02, par);
	mdelay(15);
	aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
	mdelay(30);

	// enable extended register block
	aty_st_8(BUS_CNTL+3,
		 (u8)(aty_ld_8(BUS_CNTL+3, par) | 0x08),
		 par);
	// set FIFO size to 512 (PIO)
	aty_st_le32(GUI_CNTL,
		    aty_ld_le32(GUI_CNTL, par) & ~0x3,
		    par);

	// enable CRT and disable lcd
	aty_st_8(LCD_INDEX, 0x01, par);
	temp = aty_ld_le32(LCD_DATA, par);
	temp = (temp | 0x01) & ~0x02;
	aty_st_le32(LCD_DATA, temp, par);
	return 0;
}


  reply	other threads:[~2005-08-15 19:21 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-08-12 17:11 Atyfb questions and issues Jim Ramsay
2005-08-12 17:24 ` Daniël Mantione
2005-08-12 17:50   ` James Simmons
2005-08-12 18:15     ` yhlu
2005-08-15 16:43       ` James Simmons
2005-08-15 20:39         ` yhlu
2005-08-15 20:51           ` Jim Ramsay
2005-08-15 21:15             ` Daniël Mantione
2005-08-12 18:02   ` yhlu
2005-08-15 16:25     ` Jim Ramsay
2005-08-15 16:40       ` James Simmons
2005-08-15 19:21         ` Jim Ramsay [this message]
2005-08-15 19:40           ` Daniël Mantione
2005-08-15 20:53             ` Jim Ramsay
     [not found] <4789af9e050815133711481beb@mail.gmail.com>
2005-08-15 21:10 ` Daniël Mantione

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4789af9e0508151221486d0003@mail.gmail.com \
    --to=jim.ramsay@gmail.com \
    --cc=alex.kern@gmx.de \
    --cc=daniel@deadlock.et.tudelft.nl \
    --cc=jsimmons@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=yhlu.kernel@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.