📄 w100fb.c
字号:
w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0; w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0; w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0; w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0; writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL; w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */ w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */ writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */ w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */ w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0; w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5; w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff; writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV); w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1; w100_pwr_state.pll_cntl.f.pll_reset = 0x1; w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0; w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */ w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0; w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0; w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; w100_pwr_state.pll_cntl.f.pll_pcp = 0x4; w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0; w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0; w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */ w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3; w100_pwr_state.pll_cntl.f.pll_conf = 0x2; w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2; w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0; writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0; w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */ w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0; w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */ w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */ w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF; w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF; writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); w100_pwr_state.auto_mode = 0; /* manual mode */}/* * Setup the w100 clocks for the specified mode */static void w100_init_clocks(struct w100fb_par *par){ struct w100_mode *mode = par->mode; if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL) w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq); w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src; w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider; w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider; writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL);}static void w100_init_lcd(struct w100fb_par *par){ u32 temp32; struct w100_mode *mode = par->mode; struct w100_gen_regs *regs = par->mach->regs; union active_h_disp_u active_h_disp; union active_v_disp_u active_v_disp; union graphic_h_disp_u graphic_h_disp; union graphic_v_disp_u graphic_v_disp; union crtc_total_u crtc_total; /* w3200 doesnt like undefined bits being set so zero register values first */ active_h_disp.val = 0; active_h_disp.f.active_h_start=mode->left_margin; active_h_disp.f.active_h_end=mode->left_margin + mode->xres; writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP); active_v_disp.val = 0; active_v_disp.f.active_v_start=mode->upper_margin; active_v_disp.f.active_v_end=mode->upper_margin + mode->yres; writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP); graphic_h_disp.val = 0; graphic_h_disp.f.graphic_h_start=mode->left_margin; graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres; writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP); graphic_v_disp.val = 0; graphic_v_disp.f.graphic_v_start=mode->upper_margin; graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres; writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP); crtc_total.val = 0; crtc_total.f.crtc_h_total=mode->left_margin + mode->xres + mode->right_margin; crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin; writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL); writel(mode->crtc_ss, remapped_regs + mmCRTC_SS); writel(mode->crtc_ls, remapped_regs + mmCRTC_LS); writel(mode->crtc_gs, remapped_regs + mmCRTC_GS); writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS); writel(mode->crtc_rev, remapped_regs + mmCRTC_REV); writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK); writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK); writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE); writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE); writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT); writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1); writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2); writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1); writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2); writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3); writel(0x00000000, remapped_regs + mmCRTC_FRAME); writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS); writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT); writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR); /* Hack for overlay in ext memory */ temp32 = readl(remapped_regs + mmDISP_DEBUG2); temp32 |= 0xc0000000; writel(temp32, remapped_regs + mmDISP_DEBUG2);}static void w100_setup_memory(struct w100fb_par *par){ union mc_ext_mem_location_u extmem_location; union mc_fb_location_u intmem_location; struct w100_mem_info *mem = par->mach->mem; struct w100_bm_mem_info *bm_mem = par->mach->bm_mem; if (!par->extmem_active) { w100_suspend(W100_SUSPEND_EXTMEM); /* Map Internal Memory at FB Base */ intmem_location.f.mc_fb_start = W100_FB_BASE >> 8; intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8; writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION); /* Unmap External Memory - value is *probably* irrelevant but may have meaning to acceleration libraries */ extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8; extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8; writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION); } else { /* Map Internal Memory to its default location */ intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8; intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8; writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION); /* Map External Memory at FB Base */ extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8; extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8; writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION); writel(0x00007800, remapped_regs + mmMC_BIST_CTRL); writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL); writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG); udelay(100); writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG); udelay(100); writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG); udelay(100); writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL); writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL); if (bm_mem) { writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH); writel(bm_mem->offset, remapped_regs + mmBM_OFFSET); writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL); writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL); writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG); writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL); writel(bm_mem->config, remapped_regs + mmBM_CONFIG); } }}static void w100_set_dispregs(struct w100fb_par *par){ unsigned long rot=0, divider, offset=0; union graphic_ctrl_u graphic_ctrl; /* See if the mode has been rotated */ if (par->xres == par->mode->xres) { if (par->flip) { rot=3; /* 180 degree */ offset=(par->xres * par->yres) - 1; } /* else 0 degree */ divider = par->mode->pixclk_divider; } else { if (par->flip) { rot=2; /* 270 degree */ offset=par->xres - 1; } else { rot=1; /* 90 degree */ offset=par->xres * (par->yres - 1); } divider = par->mode->pixclk_divider_rotated; } graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */ switch (par->chip_id) { case CHIP_ID_W100: graphic_ctrl.f_w100.color_depth=6; graphic_ctrl.f_w100.en_crtc=1; graphic_ctrl.f_w100.en_graphic_req=1; graphic_ctrl.f_w100.en_graphic_crtc=1; graphic_ctrl.f_w100.lcd_pclk_on=1; graphic_ctrl.f_w100.lcd_sclk_on=1; graphic_ctrl.f_w100.low_power_on=0; graphic_ctrl.f_w100.req_freq=0; graphic_ctrl.f_w100.portrait_mode=rot; /* Zaurus needs this */ switch(par->xres) { case 240: case 320: default: graphic_ctrl.f_w100.total_req_graphic=0xa0; break; case 480: case 640: switch(rot) { case 0: /* 0 */ case 3: /* 180 */ graphic_ctrl.f_w100.low_power_on=1; graphic_ctrl.f_w100.req_freq=5; break; case 1: /* 90 */ case 2: /* 270 */ graphic_ctrl.f_w100.req_freq=4; break; default: break; } graphic_ctrl.f_w100.total_req_graphic=0xf0; break; } break; case CHIP_ID_W3200: case CHIP_ID_W3220: graphic_ctrl.f_w32xx.color_depth=6; graphic_ctrl.f_w32xx.en_crtc=1; graphic_ctrl.f_w32xx.en_graphic_req=1; graphic_ctrl.f_w32xx.en_graphic_crtc=1; graphic_ctrl.f_w32xx.lcd_pclk_on=1; graphic_ctrl.f_w32xx.lcd_sclk_on=1; graphic_ctrl.f_w32xx.low_power_on=0; graphic_ctrl.f_w32xx.req_freq=0; graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */ graphic_ctrl.f_w32xx.portrait_mode=rot; break; } /* Set the pixel clock source and divider */ w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src; w100_pwr_state.pclk_cntl.f.pclk_post_div = divider; writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL); writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET); writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH);}/* * Work out how long the sync pulse lasts * Value is 1/(time in seconds) */static void calc_hsync(struct w100fb_par *par){ unsigned long hsync; struct w100_mode *mode = par->mode; union crtc_ss_u crtc_ss; if (mode->pixclk_src == CLK_SRC_XTAL) hsync=par->mach->xtal_freq; else hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000; hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1); crtc_ss.val = readl(remapped_regs + mmCRTC_SS); if (crtc_ss.val) par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start); else par->hsync_len = 0;}static void w100_suspend(u32 mode){ u32 val; writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION); writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL); val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL); val &= ~(0x00100000); /* bit20=0 */ val |= 0xFF000000; /* bit31:24=0xff */ writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL); val = readl(remapped_regs + mmMEM_EXT_CNTL); val &= ~(0x00040000); /* bit18=0 */ val |= 0x00080000; /* bit19=1 */ writel(val, remapped_regs + mmMEM_EXT_CNTL); udelay(1); /* wait 1us */ if (mode == W100_SUSPEND_EXTMEM) { /* CKE: Tri-State */ val = readl(remapped_regs + mmMEM_EXT_CNTL); val |= 0x40000000; /* bit30=1 */ writel(val, remapped_regs + mmMEM_EXT_CNTL); /* CLK: Stop */ val = readl(remapped_regs + mmMEM_EXT_CNTL); val &= ~(0x00000001); /* bit0=0 */ writel(val, remapped_regs + mmMEM_EXT_CNTL); } else { writel(0x00000000, remapped_regs + mmSCLK_CNTL); writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL); writel(0x00000015, remapped_regs + mmPWRMGT_CNTL); udelay(5); val = readl(remapped_regs + mmPLL_CNTL); val |= 0x00000004; /* bit2=1 */ writel(val, remapped_regs + mmPLL_CNTL); writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL); }}static void w100_vsync(void){ u32 tmp; int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */ tmp = readl(remapped_regs + mmACTIVE_V_DISP); /* set vline pos */ writel((tmp >> 16) & 0x3ff, remapped_regs + mmDISP_INT_CNTL); /* disable vline irq */ tmp = readl(remapped_regs + mmGEN_INT_CNTL); tmp &= ~0x00000002; writel(tmp, remapped_regs + mmGEN_INT_CNTL); /* clear vline irq status */ writel(0x00000002, remapped_regs + mmGEN_INT_STATUS); /* enable vline irq */ writel((tmp | 0x00000002), remapped_regs + mmGEN_INT_CNTL); /* clear vline irq status */ writel(0x00000002, remapped_regs + mmGEN_INT_STATUS); while(timeout > 0) { if (readl(remapped_regs + mmGEN_INT_STATUS) & 0x00000002) break; udelay(1); timeout--; } /* disable vline irq */ writel(tmp, remapped_regs + mmGEN_INT_CNTL); /* clear vline irq status */ writel(0x00000002, remapped_regs + mmGEN_INT_STATUS);}static struct platform_driver w100fb_driver = { .probe = w100fb_probe, .remove = w100fb_remove, .suspend = w100fb_suspend, .resume = w100fb_resume, .driver = { .name = "w100fb", },};int __devinit w100fb_init(void){ return platform_driver_register(&w100fb_driver);}void __exit w100fb_cleanup(void){ platform_driver_unregister(&w100fb_driver);}module_init(w100fb_init);module_exit(w100fb_cleanup);MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -