📄 mq200fb.c
字号:
*/static voidvsync(){}/**** * interrupt handler. */static voidmq200_interrupt(int irq, void* dev_id, struct pt_regs* regs){ u32 status; status = readl(IN02R(&mq200fb_info)); writel(status, IN02R(&mq200fb_info)); if (status & 0x02) vsync();}/**** * enable interrupt controller. */static voidmq200_enable_irq(const struct mq200fb_info* fb_info){ writel(0x1F02, IN01R(fb_info)); /* unmask */ writel(1, IN00R(fb_info)); /* interrupt enable */}#endif/**** * Configure register and framebuffer addresses. * If you need to get virtual addresses using ioremap(), rewrite this * function. * * [RETURN] * 1: success * 0: fail */static int __initmq200fb_conf(struct mq200fb_info* fb_info){ /* set framebuffer related values */ fb_info->regions.p_fb = virt_to_phys((void*)MQ200_FB_BASE); fb_info->regions.v_fb = MQ200_FB_BASE; fb_info->regions.p_regs = virt_to_phys((void*)MQ200_REGS_BASE); fb_info->regions.v_regs = MQ200_REGS_BASE; fb_info->regions.fb_size = MQ200_FB_SIZE - CURSOR_IMAGE_SIZE; /* set addresses of module register */ fb_info->pmu_base = fb_info->regions.v_regs + PMU_OFFSET; fb_info->cpu_base = fb_info->regions.v_regs + CPU_OFFSET; fb_info->miu_base = fb_info->regions.v_regs + MIU_OFFSET; fb_info->in_base = fb_info->regions.v_regs + IN_OFFSET; fb_info->gc_base = fb_info->regions.v_regs + GC_OFFSET; fb_info->ge_base = fb_info->regions.v_regs + GE_OFFSET; fb_info->fpi_base = fb_info->regions.v_regs + FPI_OFFSET; fb_info->pci_base = fb_info->regions.v_regs + PCI_OFFSET; fb_info->dc_base = fb_info->regions.v_regs + DC_OFFSET; fb_info->cp1_base = fb_info->regions.v_regs + CP1_OFFSET; fb_info->psf_base = fb_info->regions.v_regs + PSF_OFFSET; if (! mq200_probe(fb_info)) { printk(CHIPNAME ": MQ-200 not found.\n"); return 0; } PRINTK(CHIPNAME ": MQ-200 found.\n"); /* set cursor info */ init_timer(&fb_info->cursor_info.timer); fb_info->cursor_info.timer.data = (unsigned long)fb_info; fb_info->cursor_info.timer.function = cursor_timer_handler; add_cursor_timer(&fb_info->cursor_info); return 1;}/**** * [RETURN] * 1: detect * 0: not found */static int __initmq200_probe(struct mq200fb_info* fb_info){ union pc00r pc00r; if (readl(PMR(fb_info)) != PMR_VALUE) return 0; pc00r.whole = readl(PC00R(fb_info)); fb_info->vendor_id = pc00r.part.vendor; fb_info->device_id = pc00r.part.device; return 1;}/**** * mq-200 hardware reset. */static voidmq200_reset(const struct mq200fb_info* fb_info){ power_state_transition(fb_info, 0); /* transition to D0 state */ dc_reset(fb_info); /* device configuration */ miu_reset(fb_info); /* memory interface unit */ pmu_reset(fb_info); /* power management unit */ gc1_reset(fb_info); /* graphics controller 1 */ ge_reset(fb_info); /* graphics engine */ cp1_reset(fb_info); /* color palette 1 */}/**** * device configuration initialization. */static voiddc_reset(const struct mq200fb_info* fb_info){ union dc00r dc00r; dc00r.whole = 0; dc00r.part.osc_enbl = 1; dc00r.part.pll1_enbl = 1; dc00r.part.pll1_p_par = fb_info->current_par.pll[0].p_par; dc00r.part.pll1_n_par = fb_info->current_par.pll[0].n_par; dc00r.part.pll1_m_par = fb_info->current_par.pll[0].m_par; dc00r.part.fast_pwr = 1; dc00r.part.osc_frq = 3; /* oscillator frequency is in the range of 12 MHz to 25 MHz */ writel(dc00r.whole, DC00R(fb_info)); PRINTK(CHIPNAME ": DC00R = %lx\n", readl(DC00R(fb_info)));}/**** * initialize memory interface unit. */static voidmiu_reset(const struct mq200fb_info* fb_info){ union mm00r mm00r; union mm01r mm01r; union mm02r mm02r; union mm03r mm03r; union mm04r mm04r; /* MIU interface control 1 */ mm00r.whole = 0; mm00r.part.miu_enbl = 1; mm00r.part.mr_dsbl = 1; writel(mm00r.whole, MM00R(fb_info)); mdelay(100); writel(0, MM00R(fb_info)); mdelay(50); /* MIU interface control 2 * o PLL 1 output is used as memory clock source. */ mm01r.whole = 0; mm01r.part.msr_enbl = 1; mm01r.part.pb_cpu = 1; mm01r.part.pb_ge = 1; mm01r.part.mr_interval = 3744; /* normal memory refresh time interval */ writel(mm01r.whole, MM01R(fb_info)); /* memory interface control 3 */ mm02r.whole = 0; mm02r.part.bs_stnr = 1; /* burst count for STN read is four */ mm02r.part.bs_ge = 3; /* burst count for graphics engine is eight */ mm02r.part.fifo_gc1 = 2; mm02r.part.fifo_gc2 = 1; mm02r.part.fifo_stnr = 2; mm02r.part.fifo_stnw = 1; mm02r.part.fifo_ge_src = 3; mm02r.part.fifo_ge_dst = 3; writel(mm02r.whole, MM02R(fb_info)); /* memory interface control 5 */ mm04r.whole = 0; mm04r.part.latency = 1; /* EDRAM latency 1 */ mm04r.part.dmm_cyc = 1; mm04r.part.bnk_act_cls = 1; writel(mm04r.whole, MM04R(fb_info)); /* memory interface control 4 */ mm03r.whole = 0; mm03r.part.rd_late_req = 1; mm03r.part.reserved_1 = 134; /* ? */ writel(mm03r.whole, MM03R(fb_info)); mdelay(10); /* MIU interface control 1 */ writel(mm00r.whole, MM00R(fb_info)); mdelay(50); PRINTK(CHIPNAME ": MIU reset.\n");}/**** * initialize power management unit. */static voidpmu_reset(const struct mq200fb_info* fb_info){ union pm00r pm00r; union pm01r pm01r; union pm02r pm02r; union pm06r pm06r; union pm07r pm07r; /* power management miscellaneous control * o GE is driven by PLL 1 clock. */ pm00r.whole = 0; pm00r.part.pll2_enbl = 1; pm00r.part.pll3_enbl = 1; pm00r.part.ge_enbl = 1; pm00r.part.ge_bsy_gl = 1; pm00r.part.ge_bsy_lcl = 1; pm00r.part.ge_clock = 1; /* GE is driven by PLL 1 clock */ pm00r.part.d3_mem_rfsh = 1; writel(pm00r.whole, PM00R(fb_info)); mdelay(1); writel(pm00r.whole & 0x6000, PM00R(fb_info)); mdelay(1); /* D1 state control */ pm01r.whole = 0; pm01r.part.osc_enbl = 1; pm01r.part.pll1_enbl = 1; pm01r.part.pll2_enbl = 1; pm01r.part.miu_enbl = 1; pm01r.part.mem_rfsh = 1; pm01r.part.ge_enbl = 1; pm01r.part.fpd_enbl = 1; pm01r.part.ctl1_enbl = 1; pm01r.part.awin1_enbl = 1; writel(pm01r.whole, PM01R(fb_info)); /* D2 state control */ pm02r.whole = 0; pm02r.part.osc_enbl = 1; pm02r.part.pll1_enbl = 1; pm02r.part.pll2_enbl = 1; pm02r.part.miu_enbl = 1; pm02r.part.mem_rfsh = 1; pm02r.part.ge_enbl = 1; writel(pm02r.whole, PM02R(fb_info)); /* PLL 2 programming */ pm06r.whole = 0; pm06r.part.p_par = fb_info->current_par.pll[1].p_par; pm06r.part.n_par = fb_info->current_par.pll[1].n_par; pm06r.part.m_par = fb_info->current_par.pll[1].m_par; writel(pm06r.whole, PM06R(fb_info)); /* PLL 3 programming */ pm07r.whole = 0; pm07r.part.p_par = fb_info->current_par.pll[2].p_par; pm07r.part.n_par = fb_info->current_par.pll[2].n_par; pm07r.part.m_par = fb_info->current_par.pll[2].m_par; writel(pm07r.whole, PM07R(fb_info)); writel(pm00r.whole, PM00R(fb_info)); PRINTK(CHIPNAME ": PMU reset.\n");}/**** * initialize graphics controller 1. */static voidgc1_reset(const struct mq200fb_info* fb_info){ unsigned long flags; union gc00r gc00r; union gc01r gc01r; union gc02r gc02r; union gc03r gc03r; union gc04r gc04r; union gc05r gc05r; union gc08r gc08r; union gc09r gc09r; union gc0er gc0er; union gc11r gc11r; spin_lock_irqsave(&fb_info->lock, flags); /* graphics controller CRT control */ gc01r.whole = 0; gc01r.part.dac_enbl = 1; gc01r.part.hsync_out = 1; gc01r.part.vsync_out = 1; writel(gc01r.whole, GC01R(fb_info)); /* horizontal display 1 control */ gc02r.whole = 0; gc02r.part.hd1t = fb_info->current_par.gc[0].disp.hdt; gc02r.part.hd1e = fb_info->current_par.gc[0].disp.hde; writel(gc02r.whole, GC02R(fb_info)); /* vertical display 1 control */ gc03r.whole = 0; gc03r.part.vd1t = fb_info->current_par.gc[0].disp.vdt; gc03r.part.vd1e = fb_info->current_par.gc[0].disp.vde; writel(gc03r.whole, GC03R(fb_info)); /* horizontal sync 1 control */ gc04r.whole = 0; gc04r.part.hs1s = fb_info->current_par.gc[0].disp.hss; gc04r.part.hs1e = fb_info->current_par.gc[0].disp.hse; writel(gc04r.whole, GC04R(fb_info)); /* vertical sync 1 control */ gc05r.whole = 0; gc05r.part.vs1s = fb_info->current_par.gc[0].disp.vss; gc05r.part.vs1e = fb_info->current_par.gc[0].disp.vse; writel(gc05r.whole, GC05R(fb_info)); /* horizontal window 1 control */ gc08r.whole = 0; gc08r.part.hw1s = fb_info->current_par.gc[0].win.hws; gc08r.part.hw1w = fb_info->current_par.gc[0].win.hww; gc08r.part.w1ald = fb_info->current_par.gc[0].win.wald; writel(gc08r.whole, GC08R(fb_info)); /* vertical window 1 control */ gc09r.whole = 0; gc09r.part.vw1s = fb_info->current_par.gc[0].win.vws; gc09r.part.vw1h = fb_info->current_par.gc[0].win.vwh; writel(gc09r.whole, GC09R(fb_info)); /* alternate horizontal window 1 control */ writel(0, GC0AR(fb_info)); /* alternate vertical window 1 control */ writel(0, GC0BR(fb_info)); /* window 1 start address */ writel(fb_info->current_par.gc[0].win.wsa, GC0CR(fb_info)); /* alternate window 1 start address */ writel(0, GC0DR(fb_info)); /* window 1 stride */ gc0er.whole = 0; gc0er.part.w1st = fb_info->current_par.gc[0].win.wst; gc0er.part.aw1st = fb_info->current_par.gc[0].awin.wst; writel(gc0er.whole, GC0ER(fb_info)); /* reserved register - ??? - */ writel(0x31f, GC0FR(fb_info)); /* hardware cursor 1 position */ writel(0, GC10R(fb_info)); /* hardware cursor 1 start address and offset */ gc11r.whole = 0; gc11r.part.hc1sa = CURSOR_OFFSET >> 10; writel(gc11r.whole, GC11R(fb_info)); /* hardware cursor 1 foreground color */ writel(0x00ffffff, GC12R(fb_info)); /* hardware cursor 1 background color */ writel(0x00000000, GC13R(fb_info)); /* graphics controller 1 register * o GC1 clock source is PLL 2. * o hardware cursor is enabled. */ gc00r.whole = 0; gc00r.part.ctl_enbl = 1; gc00r.part.iwin_enbl = 1; gc00r.part.gcd = fb_info->current_par.gc[0].gcd; gc00r.part.hc_enbl = 1; gc00r.part.agcd = fb_info->current_par.gc[0].agcd; gc00r.part.g1rclk_src = 2; /* PLL 2 */ gc00r.part.fd = 0; /* FD = 1 */ gc00r.part.sd = 1; /* SD = 1 */ writel(gc00r.whole, GC00R(fb_info)); spin_unlock_irqrestore(&fb_info->lock, flags); PRINTK(CHIPNAME ": GC1 reset.\n");}/**** * initialize graphics engine. */static voidge_reset(const struct mq200fb_info* fb_info){ /* drawing command register */ writel(0, GE00R(fb_info)); /* promary width and height register */ writel(0, GE01R(fb_info)); /* primary destination address register */ writel(0, GE02R(fb_info)); /* primary source XY register */ writel(0, GE03R(fb_info)); /* primary color compare register */ writel(0, GE04R(fb_info)); /* primary clip left/top register */ writel(0, GE05R(fb_info)); /* primary clip right/bottom register */ writel(0, GE06R(fb_info)); /* primary source and pattern offset register */ writel(0, GE07R(fb_info)); /* primary foreground color register/rectangle fill color depth */ writel(0, GE08R(fb_info)); /* source stride/offset register */ writel(0, GE09R(fb_info)); /* destination stride register and color depth */ writel(0, GE0AR(fb_info)); /* image base address register */ writel(0, GE0BR(fb_info)); PRINTK(CHIPNAME ": GE reset.\n");}/**** * initialize Color Palette 1. */static voidcp1_reset(const struct mq200fb_info* fb_info){ int i; for (i = 0; i < 256; i++) writel(0, C1xxR(fb_info, i));}/**** * change screen size and depth, and so on. * Right now, screen attributes modification is not implemeted. */static voidset_screen(const struct mq200fb_info* fb_info, const struct mq200fb_par* par){ unsigned long flags; union ge0ar ge0ar; /* set destination stride and color depth for GE */ ge0ar.whole = 0; ge0ar.part.dst_strid = get_line_length(par); switch (get_bits_per_pixel(par)) { case 8: ge0ar.part.col_dpth = 0; break; case 16: ge0ar.part.col_dpth = 1; break; case 32: ge0ar.part.col_dpth = 3; break; default: printk(CHIPNAME ": unexpected %d bits/pixel\n", get_bits_per_pixel(par)); break; } spin_lock_irqsave(&fb_info->lock, flags); writel(ge0ar.whole, GE0AR(fb_info)); spin_unlock_irqrestore(&fb_info->lock, flags);}/**** * set hardware cursor shape. * * [NOTE] * This function assume that cursor width is less than or equal to 64 * pixels. */static voidset_cursor_shape(const struct mq200fb_info* fb_info){ static int already_created; static u32 cursor_images[2][256]; unsigned long flags; u32 image; if (! already_created) { u16 and_bits[4], xor_bits[4]; u32 transparent = 0x0000FFFF; int line, i; /* * set "CM_DRAW" cursor shape */ image = fb_info->regions.v_fb + CURSOR_OFFSET; /* inverse transparency */ for (i = 0; i < fb_info->cursor_info.size.x / 16; i++) and_bits[i] = xor_bits[i] = ~0; /* partially inverse transparency */ and_bits[i] = ~0; xor_bits[i] = (u16)~0 >> (16 - fb_info->cursor_info.size.x % 16); /* rest is transparent */ while (++i < 4) { and_bits[i] = ~0; xor_bits[i] = 0; } spin_lock_irqsave(&fb_info->lock, flags); for (line = 0; line < fb_info->cursor_info.size.y; line++) for (i = 0; i < 4; i++) { writel(((u32)xor_bits[i] << 16) | (u32)and_bits[i], image); image += 4; } while (line++ < 64) for (i = 0; i < 4; i++) { writel(transparent, image); image += 4; } /* * set "CM_ERASE" cursor shape */ image = fb_info->regions.v_fb + CURSOR_OFFSET + 1024; for (line = 0; line < 64; line++) for (i = 0; i < 4; i++) { writel(transparent, image); image += 4; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -