All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anatolij Gustschin <agust@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] [PATCH] Extend ATI Radeon driver to support more video modes
Date: Mon, 11 Feb 2008 20:42:08 +0100	[thread overview]
Message-ID: <47B0A510.6060108@denx.de> (raw)

Adds ATI Radeon 9200 support for 1280x1024, 1024x768,
800x600, 640x480 at 24, 16 and 8 bpp. Hope this patch
won't screw up X300 and X700 support.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 drivers/video/ati_radeon_fb.c |  401 +++++++++++++++++++++++++++++++++++++++--
 1 files changed, 386 insertions(+), 15 deletions(-)

diff --git a/drivers/video/ati_radeon_fb.c b/drivers/video/ati_radeon_fb.c
index 0bdaa1c..740a360 100644
--- a/drivers/video/ati_radeon_fb.c
+++ b/drivers/video/ati_radeon_fb.c
@@ -44,6 +44,7 @@
 #include <asm/io.h>
 #include <malloc.h>
 #include <video_fb.h>
+#include "videomodes.h"
 
 #include <radeon.h>
 #include "ati_ids.h"
@@ -70,6 +71,7 @@
 #define PCI_CHIP_RV280_5961		0x5961
 #define PCI_CHIP_RV280_5962		0x5962
 #define PCI_CHIP_RV280_5964		0x5964
+#define PCI_CHIP_RV280_5C63		0x5C63
 #define PCI_CHIP_RV370_5B60		0x5B60
 #define PCI_CHIP_RV380_5657		0x5657
 #define PCI_CHIP_R420_554d		0x554d
@@ -79,6 +81,7 @@ static struct pci_device_id ati_radeon_pci_ids[] = {
 	{PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5961},
 	{PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5962},
 	{PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5964},
+	{PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5C63},
 	{PCI_VENDOR_ID_ATI, PCI_CHIP_RV370_5B60},
 	{PCI_VENDOR_ID_ATI, PCI_CHIP_RV380_5657},
 	{PCI_VENDOR_ID_ATI, PCI_CHIP_R420_554d},
@@ -90,12 +93,115 @@ static u16 ati_radeon_id_family_table[][2] = {
 	{PCI_CHIP_RV280_5961, CHIP_FAMILY_RV280},
 	{PCI_CHIP_RV280_5962, CHIP_FAMILY_RV280},
 	{PCI_CHIP_RV280_5964, CHIP_FAMILY_RV280},
+	{PCI_CHIP_RV280_5C63, CHIP_FAMILY_RV280},
 	{PCI_CHIP_RV370_5B60, CHIP_FAMILY_RV380},
 	{PCI_CHIP_RV380_5657, CHIP_FAMILY_RV380},
 	{PCI_CHIP_R420_554d,  CHIP_FAMILY_R420},
 	{0, 0}
 };
 
+static struct {
+	unsigned char idx;
+	unsigned int val;
+} pal_16[] = {
+	{0x00, 0x00000000},
+	{0x00, 0x00000400},
+	{0x04, 0x00000400},
+	{0x08, 0x00080c08},
+	{0x08, 0x00080808},
+	{0x10, 0x00101410},
+	{0x0c, 0x00080c08},
+	{0x18, 0x00181c18},
+	{0x10, 0x00101010},
+	{0x20, 0x00202420},
+	{0x14, 0x00101410},
+	{0x28, 0x00292c29},
+	{0x18, 0x00181818},
+	{0x30, 0x00313431},
+	{0x1c, 0x00181c18},
+	{0x38, 0x00393c39},
+	{0x20, 0x00202020},
+	{0x40, 0x00414441},
+	{0x24, 0x00202420},
+	{0x48, 0x004a4c4a},
+	{0x28, 0x00292829},
+	{0x50, 0x00525552},
+	{0x2c, 0x00292c29},
+	{0x58, 0x005a5d5a},
+	{0x30, 0x00313031},
+	{0x60, 0x00626562},
+	{0x34, 0x00313431},
+	{0x68, 0x006a6d6a},
+	{0x38, 0x00393839},
+	{0x70, 0x00737573},
+	{0x3c, 0x00393c39},
+	{0x78, 0x007b7d7b},
+	{0x40, 0x00414041},
+	{0x80, 0x00838583},
+	{0x44, 0x00414441},
+	{0x88, 0x008b8d8b},
+	{0x48, 0x004a484a},
+	{0x90, 0x00949594},
+	{0x4c, 0x004a4c4a},
+	{0x98, 0x009c9d9c},
+	{0x50, 0x00525052},
+	{0xa0, 0x00a4a5a4},
+	{0x54, 0x00525552},
+	{0xa8, 0x00acaeac},
+	{0x58, 0x005a595a},
+	{0xb0, 0x00b4b6b4},
+	{0x5c, 0x005a5d5a},
+	{0xb8, 0x00bdbebd},
+	{0x60, 0x00626162},
+	{0xc0, 0x00c5c6c5},
+	{0x64, 0x00626562},
+	{0xc8, 0x00cdcecd},
+	{0x68, 0x006a696a},
+	{0xd0, 0x00d5d6d5},
+	{0x6c, 0x006a6d6a},
+	{0xd8, 0x00dedede},
+	{0x70, 0x00737173},
+	{0xe0, 0x00e6e6e6},
+	{0x74, 0x00737573},
+	{0xe8, 0x00eeeeee},
+	{0x78, 0x007b797b},
+	{0xf0, 0x00f6f6f6},
+	{0x7c, 0x007b7d7b},
+	{0xf8, 0x00ffffff},
+	{0x80, 0x00838183},
+	{0x84, 0x00838583},
+	{0x88, 0x008b898b},
+	{0x8c, 0x008b8d8b},
+	{0x90, 0x00949194},
+	{0x94, 0x00949594},
+	{0x98, 0x009c999c},
+	{0x9c, 0x009c9d9c},
+	{0xa0, 0x00a4a1a4},
+	{0xa4, 0x00a4a5a4},
+	{0xa8, 0x00acaaac},
+	{0xac, 0x00acaeac},
+	{0xb0, 0x00b4b2b4},
+	{0xb4, 0x00b4b6b4},
+	{0xb8, 0x00bdbabd},
+	{0xbc, 0x00bdbebd},
+	{0xc0, 0x00c5c2c5},
+	{0xc4, 0x00c5c6c5},
+	{0xc8, 0x00cdcacd},
+	{0xcc, 0x00cdcecd},
+	{0xd0, 0x00d5d2d5},
+	{0xd4, 0x00d5d6d5},
+	{0xd8, 0x00dedade},
+	{0xdc, 0x00dedede},
+	{0xe0, 0x00e6e2e6},
+	{0xe4, 0x00e6e6e6},
+	{0xe8, 0x00eeeaee},
+	{0xec, 0x00eeeeee},
+	{0xf0, 0x00f6f2f6},
+	{0xf4, 0x00f6f6f6},
+	{0xf8, 0x00fffaff},
+	{0xfc, 0x00ffffff},
+};
+
 u16 get_radeon_id_family(u16 device)
 {
 	int i;
@@ -350,6 +456,196 @@ void radeon_setmode(void)
 	radeon_write_pll_regs(rinfo, mode);
 }
 
+static void set_pal_16(void)
+{
+	int i;
+
+	for (i = 0; i < 96; i++) {
+		OUTREG8(PALETTE_INDEX, pal_16[i].idx);
+		OUTREG(PALETTE_DATA, pal_16[i].val);
+	}
+}
+
+static void set_pal_24(void)
+{
+	int idx, val = 0;
+
+	for (idx = 0; idx < 256; idx++) {
+		OUTREG8(PALETTE_INDEX, idx);
+		OUTREG(PALETTE_DATA, val);
+		val += 0x00010101;
+	}
+}
+
+void radeon_setmode_9200(int vesa_idx, int bpp)
+{
+	struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
+	unsigned long dp_gm_cntl;
+
+	mode->crtc_gen_cntl = 0x03000600;
+	mode->surface_cntl = 0x00a00000;
+	dp_gm_cntl = 0x100036d2;
+	mode->crtc_ext_cntl = 0x00008048;
+	mode->dac_cntl = 0xff002102;
+	mode->crtc_offset_cntl = 0x00008000;
+
+	if (bpp == 16) {
+		mode->crtc_gen_cntl = 0x03000400;
+		dp_gm_cntl = 0x100034d2;
+		mode->surface_cntl = 0x00500000;
+	} else if (bpp == 8) {
+		mode->crtc_gen_cntl = 0x03000200;
+		dp_gm_cntl = 0x100032d2;
+		mode->surface_cntl = 0x00000000;
+	}
+
+	if (vesa_idx == RES_MODE_640x480 && bpp == 8) {
+		mode->dac_cntl = 0xff002100;
+		mode->crtc_offset_cntl = 0x00000000;
+	}
+
+	switch (vesa_idx) {
+	case RES_MODE_1280x1024:
+#if 1 /* @ 60 Hz */
+		mode->crtc_h_total_disp = 0x009f00d2;
+		mode->crtc_h_sync_strt_wid = 0x000e0528;
+		mode->crtc_v_total_disp = 0x03ff0429;
+		mode->crtc_v_sync_strt_wid = 0x00030400;
+		mode->crtc_pitch = 0x00a000a0;
+		mode->ppll_div_3 = 0x00010060;
+#else /* @ 75 Hz */
+		mode->crtc_h_total_disp = 0x009f00d2;
+		mode->crtc_h_sync_strt_wid = 0x00120508;
+		mode->crtc_v_total_disp = 0x03ff0429;
+		mode->crtc_v_sync_strt_wid = 0x00030400;
+		mode->crtc_pitch = 0x00a000a0;
+		mode->ppll_div_3 = 0x00010078;
+#endif
+		switch (bpp) {
+		case 24:
+			mode->surf_info[0] = 0x00a10140;
+			mode->surf_upper_bound[0] = 0x004fffff;
+			break;
+		case 16:
+			mode->surf_info[0] = 0x005100a0;
+			mode->surf_upper_bound[0] = 0x0027ffff;
+			break;
+		default: /* 8 bpp */
+			mode->surf_info[0] = 0x00010050;
+			mode->surf_upper_bound[0] = 0x0013ffff;
+			break;
+		}
+		break;
+	case RES_MODE_1024x768:
+#if 1 /* @ 60 Hz */
+		mode->crtc_h_total_disp = 0x007f00a7;
+		mode->crtc_h_sync_strt_wid = 0x00910410;
+		mode->crtc_v_total_disp = 0x02ff0325;
+		mode->crtc_v_sync_strt_wid = 0x00860302;
+		mode->crtc_pitch = 0x00800080;
+		mode->ppll_div_3 = 0x00020074;
+#else /* @ 75 Hz */
+		mode->crtc_h_total_disp = 0x007f00a3;
+		mode->crtc_h_sync_strt_wid = 0x000c0408;
+		mode->crtc_v_total_disp = 0x02ff031f;
+		mode->crtc_v_sync_strt_wid = 0x00030300;
+		mode->crtc_pitch = 0x00800080;
+		mode->ppll_div_3 = 0x0002008c;
+#endif
+		switch (bpp) {
+		case 24:
+			mode->surf_info[0] = 0x00a10100;
+			mode->surf_upper_bound[0] = 0x002fffff;
+			break;
+		case 16:
+			mode->surf_info[0] = 0x00510080;
+			mode->surf_upper_bound[0] = 0x0017ffff;
+			break;
+		default: /* 8 bpp */
+			mode->surf_info[0] = 0x00010040;
+			mode->surf_upper_bound[0] = 0x000bffff;
+			break;
+		}
+		break;
+	case RES_MODE_800x600:
+		mode->crtc_h_total_disp = 0x00630083;
+		mode->crtc_h_sync_strt_wid = 0x00100340;
+		mode->crtc_v_total_disp = 0x02570273;
+		mode->crtc_v_sync_strt_wid = 0x00040258;
+		mode->ppll_div_3 = 0x0003008e;
+		switch (bpp) {
+		case 24:
+			mode->crtc_pitch = 0x00680068;
+			mode->surf_info[0] = 0x00a100d0;
+			mode->surf_upper_bound[0] = 0x001edfff;
+			break;
+		case 16:
+			mode->crtc_pitch = 0x00700070;
+			mode->surf_info[0] = 0x00510070;
+			mode->surf_upper_bound[0] = 0x00109fff;
+			break;
+		default: /* 8 bpp */
+			mode->crtc_pitch = 0x00800080;
+			mode->surf_info[0] = 0x00010040;
+			mode->surf_upper_bound[0] = 0x00097fff;
+			break;
+		}
+		break;
+	default: /* RES_MODE_640x480 */
+		mode->crtc_h_total_disp = 0x4f0063;
+		mode->crtc_h_sync_strt_wid = 0x8c02a2;
+		mode->crtc_v_total_disp = 0x01df020c;
+		mode->crtc_v_sync_strt_wid = 0x8201ea;
+		mode->crtc_pitch = 0x00500050;
+		mode->ppll_div_3 = 0x00030059;
+		switch (bpp) {
+		case 24:
+			mode->surf_info[0] = 0x00a100a0;
+			mode->surf_upper_bound[0] = 0x0012bfff;
+			break;
+		case 16:
+			mode->surf_info[0] = 0x00510050;
+			mode->surf_upper_bound[0] = 0x00095fff;
+			break;
+		default: /* 8 bpp */
+			break;
+		}
+		break;
+	}
+
+	OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
+	OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
+		~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
+	OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
+	OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
+	OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
+	OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
+	OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
+	OUTREG(CRTC_OFFSET, 0);
+	OUTREG(CRTC_OFFSET_CNTL, mode->crtc_offset_cntl);
+	OUTREG(CRTC_PITCH, mode->crtc_pitch);
+
+	mode->clk_cntl_index = 0x300;
+	mode->ppll_ref_div = 0xc;
+
+	radeon_write_pll_regs(rinfo, mode);
+
+	OUTREG(SURFACE0_INFO, mode->surf_info[0]);
+	OUTREG(SURFACE0_LOWER_BOUND, 0);
+	OUTREG(SURFACE0_UPPER_BOUND, mode->surf_upper_bound[0]);
+	OUTREG(SURFACE_CNTL, mode->surface_cntl);
+
+	OUTREG(DP_GUI_MASTER_CNTL, dp_gm_cntl);
+	OUTREG(0x0000325c, 0x0000000f);
+
+	if (bpp == 24)
+		set_pal_24();
+	else if (bpp == 16)
+		set_pal_16();
+
+	free(mode);
+}
+
 #include "../bios_emulator/include/biosemu.h"
 extern int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp);
 
@@ -421,29 +717,101 @@ GraphicDevice ctfb;
 void *video_hw_init(void)
 {
 	GraphicDevice *pGD = (GraphicDevice *) & ctfb;
-	int i;
 	u32 *vm;
+	char *penv;
+	unsigned long t1, hsynch, vsynch;
+	int bits_per_pixel, i, tmp, vesa_idx = 0, videomode;
+	struct ctfb_res_modes *res_mode;
+	struct ctfb_res_modes var_mode;
 
 	rinfo = malloc(sizeof(struct radeonfb_info));
 
+	printf("Video: ");
 	if(radeon_probe(rinfo)) {
 		printf("No radeon video card found!\n");
 		return NULL;
 	}
 
-	/* fill in Graphic device struct */
-	sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", 640,
-		 480, 16, (1000 / 1000),
-		 (2000 / 1000));
-	printf ("%s\n", pGD->modeIdent);
+	tmp = 0;
+
+	videomode = CFG_DEFAULT_VIDEO_MODE;
+	/* get video mode via environment */
+	if ((penv = getenv ("videomode")) != NULL) {
+		/* deceide if it is a string */
+		if (penv[0] <= '9') {
+			videomode = (int) simple_strtoul (penv, NULL, 16);
+			tmp = 1;
+		}
+	} else {
+		tmp = 1;
+	}
+	if (tmp) {
+		/* parameter are vesa modes */
+		/* search params */
+		for (i = 0; i < VESA_MODES_COUNT; i++) {
+			if (vesa_modes[i].vesanr == videomode)
+				break;
+		}
+		if (i == VESA_MODES_COUNT) {
+			printf ("no VESA Mode found, switching to mode 0x%x ", CFG_DEFAULT_VIDEO_MODE);
+			i = 0;
+		}
+		res_mode = (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].resindex];
+		bits_per_pixel = vesa_modes[i].bits_per_pixel;
+		vesa_idx = vesa_modes[i].resindex;
+	} else {
+		res_mode = (struct ctfb_res_modes *) &var_mode;
+		bits_per_pixel = video_get_params (res_mode, penv);
+	}
 
-	pGD->winSizeX = 640;
-	pGD->winSizeY = 480;
-	pGD->plnSizeX = 640;
-	pGD->plnSizeY = 480;
+	/* calculate hsynch and vsynch freq (info only) */
+	t1 = (res_mode->left_margin + res_mode->xres +
+	      res_mode->right_margin + res_mode->hsync_len) / 8;
+	t1 *= 8;
+	t1 *= res_mode->pixclock;
+	t1 /= 1000;
+	hsynch = 1000000000L / t1;
+	t1 *= (res_mode->upper_margin + res_mode->yres +
+	       res_mode->lower_margin + res_mode->vsync_len);
+	t1 /= 1000;
+	vsynch = 1000000000L / t1;
 
-	pGD->gdfBytesPP = 1;
-	pGD->gdfIndex = GDF__8BIT_INDEX;
+	/* fill in Graphic device struct */
+	sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
+		 res_mode->yres, bits_per_pixel, (hsynch / 1000),
+		 (vsynch / 1000));
+	printf ("%s\n", pGD->modeIdent);
+	pGD->winSizeX = res_mode->xres;
+	pGD->winSizeY = res_mode->yres;
+	pGD->plnSizeX = res_mode->xres;
+	pGD->plnSizeY = res_mode->yres;
+
+	switch (bits_per_pixel) {
+	case 24:
+		pGD->gdfBytesPP = 4;
+		pGD->gdfIndex = GDF_32BIT_X888RGB;
+		if (res_mode->xres == 800) {
+			pGD->winSizeX = 832;
+			pGD->plnSizeX = 832;
+		}
+		break;
+	case 16:
+		pGD->gdfBytesPP = 2;
+		pGD->gdfIndex = GDF_16BIT_565RGB;
+		if (res_mode->xres == 800) {
+			pGD->winSizeX = 896;
+			pGD->plnSizeX = 896;
+		}
+		break;
+	default:
+		if (res_mode->xres == 800) {
+			pGD->winSizeX = 1024;
+			pGD->plnSizeX = 1024;
+		}
+		pGD->gdfBytesPP = 1;
+		pGD->gdfIndex = GDF__8BIT_INDEX;
+		break;
+	}
 
 	pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
 	pGD->pciBase = rinfo->fb_base_phys;
@@ -464,14 +832,17 @@ void *video_hw_init(void)
 	pGD->cprBase = rinfo->fb_base_phys;	/* Dummy */
 	/* set up Hardware */
 
-	/* Clear video memory */
-	i = pGD->memSize / 4;
+	/* Clear video memory (only visible screen area) */
+	i = pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP / 4;
 	vm = (unsigned int *) pGD->pciBase;
 	while (i--)
 		*vm++ = 0;
 	/*SetDrawingEngine (bits_per_pixel);*/
 
-	radeon_setmode();
+	if (rinfo->family == CHIP_FAMILY_RV280)
+		radeon_setmode_9200(vesa_idx, bits_per_pixel);
+	else
+		radeon_setmode();
 
 	return ((void *) pGD);
 }
-- 
1.5.3.3

             reply	other threads:[~2008-02-11 19:42 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-11 19:42 Anatolij Gustschin [this message]
2008-02-12  8:20 ` [U-Boot-Users] [PATCH] Extend ATI Radeon driver to support more video modes Rodolfo Giometti
2008-02-13 23:51   ` Anatolij Gustschin
2008-02-14  0:39     ` Wolfgang Denk
2008-02-15  9:24       ` Rodolfo Giometti
2008-02-15 10:02         ` Jean-Christophe PLAGNIOL-VILLARD
2008-02-15 10:33           ` Anatolij Gustschin

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=47B0A510.6060108@denx.de \
    --to=agust@denx.de \
    --cc=u-boot@lists.denx.de \
    /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.