diff options
author | ryd <ryd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-02-19 04:03:49 +0000 |
---|---|---|
committer | ryd <ryd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-02-19 04:03:49 +0000 |
commit | e4a3634c00818e77664da2c3592a95e8c8fad5d6 (patch) | |
tree | 5aec8287ecd3034c53cbbeb5a6408389b1d34507 /target/linux/olpc/files-2.6.23/drivers/video/geode | |
parent | ac24192a897d17c7416cfc1a58ad5432404662de (diff) |
Adding .24 support for olpc
kernel compiles fine, but graphic support is broken
to test new kernel version, change
target/linux/olpc/Makefile
from .23.16 to .24
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10493 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/olpc/files-2.6.23/drivers/video/geode')
-rw-r--r-- | target/linux/olpc/files-2.6.23/drivers/video/geode/geode_regs.h | 242 | ||||
-rw-r--r-- | target/linux/olpc/files-2.6.23/drivers/video/geode/suspend_gx.c | 272 |
2 files changed, 514 insertions, 0 deletions
diff --git a/target/linux/olpc/files-2.6.23/drivers/video/geode/geode_regs.h b/target/linux/olpc/files-2.6.23/drivers/video/geode/geode_regs.h new file mode 100644 index 000000000..9e75505a8 --- /dev/null +++ b/target/linux/olpc/files-2.6.23/drivers/video/geode/geode_regs.h @@ -0,0 +1,242 @@ +/* This header file defines the registers and suspend/resume + structures for the Geode GX and LX. The lxfb driver defines + _GEODELX_ before including this file, which will unlock the + extra registers that are only valid for LX. +*/ + +#ifndef _GEODE_REGS_H_ +#define _GEODE_REGS_H_ + +/* MSRs */ + +#define GX_VP_MSR_PAD_SELECT 0xC0002011 +#define LX_VP_MSR_PAD_SELECT 0x48000011 + +#define GEODE_MSR_GLCP_DOTPLL 0x4c000015 + +#define GLCP_DOTPLL_RESET (1 << 0) +#define GLCP_DOTPLL_BYPASS (1 << 15) +#define GLCP_DOTPLL_HALFPIX (1 << 24) +#define GLCP_DOTPLL_LOCK (1 << 25) + +/* Registers */ +#define VP_FP_START 0x400 + + +#ifdef _GEODELX_ + +#define GP_REG_SIZE 0x7C +#define DC_REG_SIZE 0xF0 +#define VP_REG_SIZE 0x158 +#define FP_REG_SIZE 0x70 + +#else + +#define GP_REG_SIZE 0x50 +#define DC_REG_SIZE 0x90 +#define VP_REG_SIZE 0x138 +#define FP_REG_SIZE 0x70 + +#endif + +#define DC_PAL_SIZE 0x105 + +struct geoderegs { + + struct { + u64 padsel; + u64 dotpll; + +#ifdef _GEODELX_ + u64 dfglcfg; + u64 dcspare; +#else + u64 rstpll; +#endif + } msr; + + union { + unsigned char b[GP_REG_SIZE]; + struct { + u32 dst_offset; /* 0x00 */ + u32 src_offset; /* 0x04 */ + u32 stride; /* 0x08 */ + u32 wid_height; /* 0x0C */ + u32 src_color_fg; /* 0x10 */ + u32 src_color_bg; /* 0x14 */ + u32 pat_color_0; /* 0x18 */ + u32 pat_color_1; /* 0x1C */ + u32 pat_color_2; /* 0x20 */ + u32 pat_color_3; /* 0x24 */ + u32 pat_color_4; /* 0x28 */ + u32 pat_color_5; /* 0x2C */ + u32 pat_data_0; /* 0x30 */ + u32 pat_data_1; /* 0x34 */ + u32 raster_mode; /* 0x38 */ + u32 vector_mode; /* 0x3C */ + u32 blt_mode; /* 0x40 */ + u32 blit_status; /* 0x4C */ + u32 hst_src; /* 0x48 */ + u32 base_offset; /* 0x4C */ + +#ifdef _GEODELX_ + u32 cmd_top; /* 0x50 */ + u32 cmd_bot; /* 0x54 */ + u32 cmd_read; /* 0x58 */ + u32 cmd_write; /* 0x5C */ + u32 ch3_offset; /* 0x60 */ + u32 ch3_mode_str; /* 0x64 */ + u32 ch3_width; /* 0x68 */ + u32 ch3_hsrc; /* 0x6C */ + u32 lut_index; /* 0x70 */ + u32 lut_data; /* 0x74 */ + u32 int_cntrl; /* 0x78 */ +#endif + } r; + } gp; + + union { + unsigned char b[DC_REG_SIZE]; + + struct { + u32 unlock; /* 0x00 */ + u32 gcfg; /* 0x04 */ + u32 dcfg; /* 0x08 */ + u32 arb; /* 0x0C */ + u32 fb_st_offset; /* 0x10 */ + u32 cb_st_offset; /* 0x14 */ + u32 curs_st_offset; /* 0x18 */ + u32 icon_st_offset; /* 0x1C */ + u32 vid_y_st_offset; /* 0x20 */ + u32 vid_u_st_offset; /* 0x24 */ + u32 vid_v_st_offset; /* 0x28 */ + u32 dctop; /* 0x2c */ + u32 line_size; /* 0x30 */ + u32 gfx_pitch; /* 0x34 */ + u32 vid_yuv_pitch; /* 0x38 */ + u32 rsvd2; /* 0x3C */ + u32 h_active_timing; /* 0x40 */ + u32 h_blank_timing; /* 0x44 */ + u32 h_sync_timing; /* 0x48 */ + u32 rsvd3; /* 0x4C */ + u32 v_active_timing; /* 0x50 */ + u32 v_blank_timing; /* 0x54 */ + u32 v_sync_timing; /* 0x58 */ + u32 fbactive; /* 0x5C */ + u32 dc_cursor_x; /* 0x60 */ + u32 dc_cursor_y; /* 0x64 */ + u32 dc_icon_x; /* 0x68 */ + u32 dc_line_cnt; /* 0x6C */ + u32 rsvd5; /* 0x70 - palette address */ + u32 rsvd6; /* 0x74 - palette data */ + u32 dfifo_diag; /* 0x78 */ + u32 cfifo_diag; /* 0x7C */ + u32 dc_vid_ds_delta; /* 0x80 */ + u32 gliu0_mem_offset; /* 0x84 */ + u32 dv_ctl; /* 0x88 - added by LX */ + u32 dv_acc; /* 0x8C */ + +#ifdef _GEODELX_ + u32 gfx_scale; + u32 irq_filt_ctl; + u32 filt_coeff1; + u32 filt_coeff2; + u32 vbi_event_ctl; + u32 vbi_odd_ctl; + u32 vbi_hor; + u32 vbi_ln_odd; + u32 vbi_ln_event; + u32 vbi_pitch; + u32 clr_key; + u32 clr_key_mask; + u32 clr_key_x; + u32 clr_key_y; + u32 irq; + u32 rsvd8; + u32 genlk_ctrl; + u32 vid_even_y_st_offset; /* 0xD8 */ + u32 vid_even_u_st_offset; /* 0xDC */ + u32 vid_even_v_st_offset; /* 0xE0 */ + u32 v_active_even_timing; /* 0xE4 */ + u32 v_blank_even_timing; /* 0xE8 */ + u32 v_sync_even_timing; /* 0xEC */ +#endif + } r; + } dc; + + union { + unsigned char b[VP_REG_SIZE]; + + struct { + u64 vcfg; /* 0x00 */ + u64 dcfg; /* 0x08 */ + u64 vx; /* 0x10 */ + u64 vy; /* 0x18 */ + u64 vs; /* 0x20 */ + u64 vck; /* 0x28 */ + u64 vcm; /* 0x30 */ + u64 rsvd1; /* 0x38 - Gamma address*/ + u64 rsvd2; /* 0x40 - Gamma data*/ + u64 rsvd3; /* 0x48 */ + u64 misc; /* 0x50 */ + u64 ccs; /* 0x58 */ + u64 rsvd4[3]; /* 0x60-0x70 */ + u64 vdc; /* 0x78 */ + u64 vco; /* 0x80 */ + u64 crc; /* 0x88 */ + u64 crc32; /* 0x90 */ + u64 vde; /* 0x98 */ + u64 cck; /* 0xA0 */ + u64 ccm; /* 0xA8 */ + u64 cc1; /* 0xB0 */ + u64 cc2; /* 0xB8 */ + u64 a1x; /* 0xC0 */ + u64 a1y; /* 0xC8 */ + u64 a1c; /* 0xD0 */ + u64 a1t; /* 0xD8 */ + u64 a2x; /* 0xE0 */ + u64 a2y; /* 0xE8 */ + u64 a2c; /* 0xF0 */ + u64 a2t; /* 0xF8 */ + u64 a3x; /* 0x100 */ + u64 a3y; /* 0x108 */ + u64 a3c; /* 0x110 */ + u64 a3t; /* 0x118 */ + u64 vrr; /* 0x120 */ + u64 awt; /* 0x128 */ + u64 vtm; /* 0x130 */ +#ifdef _GEODELX_ + u64 vye; /* 0x138 */ + u64 a1ye; /* 0x140 */ + u32 a2ye; /* 0x148 */ + u32 a3ye; /* 0x150 */ +#endif + } r; + } vp; + + union { + unsigned char b[FP_REG_SIZE]; + + struct { + u64 pt1; /* 0x400 */ + u64 pt2; /* 0x408 */ + u64 pm; /* 0x410 */ + u64 dfc; /* 0x418 */ + u64 blfsr; /* 0x420 */ + u64 rlfsr; /* 0x428 */ + u64 fmi; /* 0x430 */ + u64 fmd; /* 0x438 */ + u64 rsvd; /* 0x440 */ + u64 dca; /* 0x448 */ + u64 dmd; /* 0x450 */ + u64 crc; /* 0x458 */ + u64 fbb; /* 0x460 */ + u64 crc32; /* 0x468 */ + } r; + } fp; + + u32 pal[DC_PAL_SIZE]; + u32 gamma[256]; +}; + +#endif diff --git a/target/linux/olpc/files-2.6.23/drivers/video/geode/suspend_gx.c b/target/linux/olpc/files-2.6.23/drivers/video/geode/suspend_gx.c new file mode 100644 index 000000000..43c25bea5 --- /dev/null +++ b/target/linux/olpc/files-2.6.23/drivers/video/geode/suspend_gx.c @@ -0,0 +1,272 @@ +#include <linux/fb.h> +#include <asm/io.h> +#include <asm/msr.h> + +#include "geodefb.h" +#include "video_gx.h" + +void gx_set_dotpll(struct fb_info *info, struct geoderegs *regs) +{ + int timeout = 1000; + + u64 rstpll, dotpll; + + rdmsrl(MSR_GLCP_SYS_RSTPLL, rstpll); + rdmsrl(MSR_GLCP_DOTPLL, dotpll); + + dotpll &= 0x00000000ffffffffull; + dotpll |= regs->msr.dotpll & 0xffffffff00000000ull; + + dotpll |= MSR_GLCP_DOTPLL_DOTRESET; + dotpll &= ~MSR_GLCP_DOTPLL_BYPASS; + + wrmsrl(MSR_GLCP_DOTPLL, dotpll); + + rstpll |= (regs->msr.rstpll & + ( MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 | + MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 | + MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3)); + + wrmsrl(MSR_GLCP_SYS_RSTPLL, rstpll); + dotpll &= ~(MSR_GLCP_DOTPLL_DOTRESET); + wrmsrl(MSR_GLCP_DOTPLL, dotpll); + + do { + rdmsrl(MSR_GLCP_DOTPLL, dotpll); + } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); +} + +/* FIXME: Make sure nothing is read to clear */ + +void gx_save_regs(struct fb_info *info, struct geoderegs *regs) +{ + struct geodefb_par *par = info->par; + int i; + + /* Wait for the BLT engine to stop being busy */ + while(readl(par->gp_regs + 0x44) & 0x05); + + rdmsrl(GX_VP_MSR_PAD_SELECT, regs->msr.padsel); + rdmsrl(MSR_GLCP_DOTPLL, regs->msr.dotpll); + rdmsrl(MSR_GLCP_SYS_RSTPLL, regs->msr.rstpll); + + writel(0x4758, par->dc_regs + 0x00); + + memcpy(regs->gp.b, par->gp_regs, GP_REG_SIZE); + memcpy(regs->dc.b, par->dc_regs, DC_REG_SIZE); + memcpy(regs->vp.b, par->vid_regs, VP_REG_SIZE); + memcpy(regs->fp.b, par->vid_regs + 0x400, FP_REG_SIZE); + + /* Save the palettes */ + writel(0, par->dc_regs + 0x70); + + for(i = 0; i < DC_PAL_SIZE; i++) + regs->pal[i] = readl(par->dc_regs + 0x74); + + writel(0, par->vid_regs + 0x38); + + for(i = 0; i < 0xFF; i++) + regs->gamma[i] = readl(par->vid_regs + 0x40); +} + +void gx_restore_regs(struct fb_info *info, struct geoderegs *regs) +{ + struct geodefb_par *par = info->par; + u32 val, i; + + /* DOTPLL */ + gx_set_dotpll(info, regs); + + /* GP */ + + writel(regs->gp.r.dst_offset, par->gp_regs + 0x00); + writel(regs->gp.r.src_offset, par->gp_regs + 0x04); + writel(regs->gp.r.stride, par->gp_regs + 0x08); + writel(regs->gp.r.wid_height, par->gp_regs + 0x0C); + writel(regs->gp.r.src_color_fg, par->gp_regs + 0x10); + writel(regs->gp.r.src_color_bg, par->gp_regs + 0x14); + writel(regs->gp.r.pat_color_0, par->gp_regs + 0x18); + writel(regs->gp.r.pat_color_1, par->gp_regs + 0x1C); + writel(regs->gp.r.pat_color_2, par->gp_regs + 0x20); + writel(regs->gp.r.pat_color_3, par->gp_regs + 0x24); + writel(regs->gp.r.pat_color_4, par->gp_regs + 0x28); + writel(regs->gp.r.pat_color_5, par->gp_regs + 0x2C); + writel(regs->gp.r.pat_data_0, par->gp_regs + 0x30); + writel(regs->gp.r.pat_data_1, par->gp_regs + 0x34); + + /* Don't write the raster / vector / blt mode regs */ + /* status register is read only */ + + writel(regs->gp.r.hst_src, par->gp_regs + 0x48); + writel(regs->gp.r.base_offset, par->gp_regs + 0x4c); + + /* DC */ + + /* Write the unlock value */ + writel(0x4758, par->dc_regs + 0x00); + + writel(0, par->dc_regs + 0x70); + + for(i = 0; i < DC_PAL_SIZE; i++) + writel(regs->pal[i], par->dc_regs + 0x74); + + /* Write the gcfg register without the enables */ + writel(regs->dc.r.gcfg & ~0x0F, par->dc_regs + 0x04); + + /* Write the vcfg register without the enables */ + writel(regs->dc.r.dcfg & ~0x19, par->dc_regs + 0x08); + + /* Write the rest of the active registers */ + + writel(regs->dc.r.fb_st_offset, par->dc_regs + 0x10); + writel(regs->dc.r.cb_st_offset, par->dc_regs + 0x14); + writel(regs->dc.r.curs_st_offset, par->dc_regs + 0x18); + writel(regs->dc.r.icon_st_offset, par->dc_regs + 0x1C); + writel(regs->dc.r.vid_y_st_offset, par->dc_regs + 0x20); + writel(regs->dc.r.vid_u_st_offset, par->dc_regs + 0x24); + writel(regs->dc.r.vid_v_st_offset, par->dc_regs + 0x28); + writel(regs->dc.r.line_size, par->dc_regs + 0x30); + writel(regs->dc.r.gfx_pitch, par->dc_regs + 0x34); + writel(regs->dc.r.vid_yuv_pitch, par->dc_regs + 0x38); + writel(regs->dc.r.h_active_timing, par->dc_regs + 0x40); + writel(regs->dc.r.h_blank_timing, par->dc_regs + 0x44); + writel(regs->dc.r.h_sync_timing, par->dc_regs + 0x48); + writel(regs->dc.r.v_active_timing, par->dc_regs + 0x50); + writel(regs->dc.r.v_blank_timing, par->dc_regs + 0x54); + writel(regs->dc.r.v_sync_timing, par->dc_regs + 0x58); + writel(regs->dc.r.dc_cursor_x, par->dc_regs + 0x60); + writel(regs->dc.r.dc_cursor_y, par->dc_regs + 0x64); + writel(regs->dc.r.dc_icon_x, par->dc_regs + 0x68); + + /* Don't write the line_cnt or diag registers */ + + writel(regs->dc.r.dc_vid_ds_delta, par->dc_regs + 0x80); + writel(regs->dc.r.gliu0_mem_offset, par->dc_regs + 0x84); + writel(regs->dc.r.dv_acc, par->dc_regs + 0x8C); + + /* VP */ + + /* MSR */ + wrmsrl(GX_VP_MSR_PAD_SELECT, regs->msr.padsel); + + writel(0, par->vid_regs + 0x38); + + for(i = 0; i < 0xFF; i++) + writel((u32) regs->gamma[i], par->vid_regs + 0x40); + + /* Don't enable video yet */ + writel((u32) regs->vp.r.vcfg & ~0x01, par->vid_regs + 0x00); + + /* Don't enable the CRT yet */ + writel((u32) regs->vp.r.dcfg & ~0x0F, par->vid_regs + 0x08); + + /* Write the rest of the VP registers */ + + writel((u32) regs->vp.r.vx, par->vid_regs + 0x10); + writel((u32) regs->vp.r.vy, par->vid_regs + 0x18); + writel((u32) regs->vp.r.vs, par->vid_regs + 0x20); + writel((u32) regs->vp.r.vck, par->vid_regs + 0x28); + writel((u32) regs->vp.r.vcm, par->vid_regs + 0x30); + writel((u32) regs->vp.r.misc, par->vid_regs + 0x50); + writel((u32) regs->vp.r.ccs, par->vid_regs + 0x58); + writel((u32) regs->vp.r.vdc, par->vid_regs + 0x78); + writel((u32) regs->vp.r.vco, par->vid_regs + 0x80); + writel((u32) regs->vp.r.crc, par->vid_regs + 0x88); + writel((u32) regs->vp.r.vde, par->vid_regs + 0x98); + writel((u32) regs->vp.r.cck, par->vid_regs + 0xA0); + writel((u32) regs->vp.r.ccm, par->vid_regs + 0xA8); + writel((u32) regs->vp.r.cc1, par->vid_regs + 0xB0); + writel((u32) regs->vp.r.cc2, par->vid_regs + 0xB8); + writel((u32) regs->vp.r.a1x, par->vid_regs + 0xC0); + writel((u32) regs->vp.r.a1y, par->vid_regs + 0xC8); + writel((u32) regs->vp.r.a1c, par->vid_regs + 0xD0); + writel((u32) regs->vp.r.a1t, par->vid_regs + 0xD8); + writel((u32) regs->vp.r.a2x, par->vid_regs + 0xE0); + writel((u32) regs->vp.r.a2y, par->vid_regs + 0xE8); + writel((u32) regs->vp.r.a2c, par->vid_regs + 0xF0); + writel((u32) regs->vp.r.a2t, par->vid_regs + 0xF8); + writel((u32) regs->vp.r.a3x, par->vid_regs + 0x100); + writel((u32) regs->vp.r.a3y, par->vid_regs + 0x108); + writel((u32) regs->vp.r.a3c, par->vid_regs + 0x110); + writel((u32) regs->vp.r.a3t, par->vid_regs + 0x118); + writel((u32) regs->vp.r.vrr, par->vid_regs + 0x120); + + + /* FP registers */ + + writel((u32) regs->fp.r.pt1, par->vid_regs + 0x400); + writel((u32) regs->fp.r.pt2, par->vid_regs + 0x408); + + writel((u32) regs->fp.r.dfc, par->vid_regs + 0x418); + writel(regs->fp.r.blfsr, par->vid_regs + 0x420); + writel(regs->fp.r.rlfsr, par->vid_regs + 0x428); + writel(regs->fp.r.fmi, par->vid_regs + 0x430); + writel(regs->fp.r.fmd, par->vid_regs + 0x438); + writel(regs->fp.r.dca, par->vid_regs + 0x448); + writel(regs->fp.r.dmd, par->vid_regs + 0x450); + writel(regs->fp.r.crc, par->vid_regs + 0x458); + writel(regs->fp.r.fbb, par->vid_regs + 0x460); + + /* Final enables */ + + val = readl(par->vid_regs + 0x410); + + /* Control the panel */ + if (regs->fp.r.pm & (1 << 24)) { + + if (!(val & 0x09)) + writel(regs->fp.r.pm, par->vid_regs + 0x410); + } + else { + if (!(val & 0x05)) + writel(regs->fp.r.pm, par->vid_regs + 0x410); + } + + /* Turn everything on */ + + writel(regs->dc.r.gcfg, par->dc_regs + 0x04); + writel((u32) regs->vp.r.vcfg, par->vid_regs + 0x00); + writel((u32) regs->vp.r.dcfg, par->vid_regs + 0x08); + writel(regs->dc.r.dcfg, par->dc_regs + 0x08); +} + + +#ifdef DEBUG + +void dump_regs(struct fb_info *info, int mode) { + + struct geodefb_par *par = info->par; + u32 val; + int i; + + if (mode == 0) { + for(i = 0; i < GP_REG_SIZE; i += 4) { + val = readl(par->gp_regs + i); + } + } + + if (mode == 1) { + writel(0x4758, par->dc_regs + 0x00); + + for(i = 0; i < DC_REG_SIZE; i += 4) { + val = readl(par->dc_regs + i); + printk("DC%x: %x\n", i, val); + } + } + + if (mode == 2) { + for(i = 0; i < VP_REG_SIZE; i += 8) { + val = readl(par->vid_regs + i); + printk("VP%x: %x\n", i, val); + } + } + + if (mode == 3) { + for(i = 0; i < FP_REG_SIZE; i += 8) { + val = readl(par->vid_regs + 0x400 + i); + printk("FP%x: %x\n", i, val); + } + } +} + +#endif |