sstfb.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,724 行 · 第 1/4 页
C
1,724 行
u32 stride = info->fix.line_length; if (!IS_VOODOO2(par)) return; sst_write(BLTCLIPX, info->var.xres); sst_write(BLTCLIPY, info->var.yres); sst_write(BLTDSTBASEADDR, 0); sst_write(BLTCOLOR, rect->color); sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR); sst_write(BLTXYSTRIDES, stride | (stride << 16)); sst_write(BLTDSTXY, rect->dx | (rect->dy << 16)); sst_write(BLTSIZE, rect->width | (rect->height << 16)); sst_write(BLTCOMMAND, BLT_RECFILL_BITBLT | LAUNCH_BITBLT | (BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) | BIT(16) ); sst_wait_idle();}/* * get lfb size */static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize){ u_long fbbase_virt = (u_long) info->screen_base; /* force memsize */ if ((mem >= 1 ) && (mem <= 4)) { *memsize = (mem * 0x100000); iprintk("supplied memsize: %#x\n", *memsize); return 1; } writel(0xdeadbeef, fbbase_virt); writel(0xdeadbeef, fbbase_virt+0x100000); writel(0xdeadbeef, fbbase_virt+0x200000); f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n", readl(fbbase_virt), readl(fbbase_virt + 0x100000), readl(fbbase_virt + 0x200000)); writel(0xabcdef01, fbbase_virt); f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n", readl(fbbase_virt), readl(fbbase_virt + 0x100000), readl(fbbase_virt + 0x200000)); /* checks for 4mb lfb, then 2, then defaults to 1 */ if (readl(fbbase_virt + 0x200000) == 0xdeadbeef) *memsize = 0x400000; else if (readl(fbbase_virt + 0x100000) == 0xdeadbeef) *memsize = 0x200000; else *memsize = 0x100000; f_ddprintk("detected memsize: %dMB\n", *memsize >> 20); return 1;}/* * DAC detection routines *//* fbi should be idle, and fifo emty and mem disabled *//* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */static int __devinit sst_detect_att(struct fb_info *info){ struct sstfb_par *par = (struct sstfb_par *) info->par; int i, mir, dir; for (i=0; i<3; i++) { sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_read(DACREG_RMR); /* read 4 times RMR */ sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); /* the fifth time, CR0 is read */ sst_dac_read(DACREG_RMR); /* the 6th, manufacturer id register */ mir = sst_dac_read(DACREG_RMR); /*the 7th, device ID register */ dir = sst_dac_read(DACREG_RMR); f_ddprintk("mir: %#x, dir: %#x\n", mir, dir); if ((mir == DACREG_MIR_ATT ) && (dir == DACREG_DIR_ATT)) { return 1; } } return 0;}static int __devinit sst_detect_ti(struct fb_info *info){ struct sstfb_par *par = (struct sstfb_par *) info->par; int i, mir, dir; for (i = 0; i<3; i++) { sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_read(DACREG_RMR); /* read 4 times RMR */ sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); /* the fifth time, CR0 is read */ sst_dac_read(DACREG_RMR); /* the 6th, manufacturer id register */ mir = sst_dac_read(DACREG_RMR); /*the 7th, device ID register */ dir = sst_dac_read(DACREG_RMR); f_ddprintk("mir: %#x, dir: %#x\n", mir, dir); if ((mir == DACREG_MIR_TI ) && (dir == DACREG_DIR_TI)) { return 1; } } return 0;}/* * try to detect ICS5342 ramdac * we get the 1st byte (M value) of preset f1,f7 and fB * why those 3 ? mmmh... for now, i'll do it the glide way... * and ask questions later. anyway, it seems that all the freq registers are * realy at their default state (cf specs) so i ask again, why those 3 regs ? * mmmmh.. it seems that's much more ugly than i thought. we use f0 and fA for * pll programming, so in fact, we *hope* that the f1, f7 & fB won't be * touched... * is it realy safe ? how can i reset this ramdac ? geee... */static int __devinit sst_detect_ics(struct fb_info *info){ struct sstfb_par *par = (struct sstfb_par *) info->par; int m_clk0_1, m_clk0_7, m_clk1_b; int n_clk0_1, n_clk0_7, n_clk1_b; int i; for (i = 0; i<5; i++ ) { sst_dac_write(DACREG_ICS_PLLRMA, 0x1); /* f1 */ m_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA); n_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA); sst_dac_write(DACREG_ICS_PLLRMA, 0x7); /* f7 */ m_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA); n_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA); sst_dac_write(DACREG_ICS_PLLRMA, 0xb); /* fB */ m_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA); n_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA); f_ddprintk("m_clk0_1: %#x, m_clk0_7: %#x, m_clk1_b: %#x\n", m_clk0_1, m_clk0_7, m_clk1_b); f_ddprintk("n_clk0_1: %#x, n_clk0_7: %#x, n_clk1_b: %#x\n", n_clk0_1, n_clk0_7, n_clk1_b); if (( m_clk0_1 == DACREG_ICS_PLL_CLK0_1_INI) && (m_clk0_7 == DACREG_ICS_PLL_CLK0_7_INI) && (m_clk1_b == DACREG_ICS_PLL_CLK1_B_INI)) { return 1; } } return 0;}/* * gfx, video, pci fifo should be reset, dram refresh disabled * see detect_dac */static int sst_set_pll_att_ti(struct fb_info *info, const struct pll_timing *t, const int clock){ struct sstfb_par *par = (struct sstfb_par *) info->par; u8 cr0, cc; /* enable indexed mode */ sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_read(DACREG_RMR); /* 1 time: RMR */ sst_dac_read(DACREG_RMR); /* 2 RMR */ sst_dac_read(DACREG_RMR); /* 3 // */ sst_dac_read(DACREG_RMR); /* 4 // */ cr0 = sst_dac_read(DACREG_RMR); /* 5 CR0 */ sst_dac_write(DACREG_WMA, 0); sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); sst_dac_write(DACREG_RMR, (cr0 & 0xf0) | DACREG_CR0_EN_INDEXED | DACREG_CR0_8BIT | DACREG_CR0_PWDOWN ); /* so, now we are in indexed mode . dunno if its common, but i find this way of doing things a little bit weird :p */ udelay(300); cc = dac_i_read(DACREG_CC_I); switch (clock) { case VID_CLOCK: dac_i_write(DACREG_AC0_I, t->m); dac_i_write(DACREG_AC1_I, t->p << 6 | t->n); dac_i_write(DACREG_CC_I, (cc & 0x0f) | DACREG_CC_CLKA | DACREG_CC_CLKA_C); break; case GFX_CLOCK: dac_i_write(DACREG_BD0_I, t->m); dac_i_write(DACREG_BD1_I, t->p << 6 | t->n); dac_i_write(DACREG_CC_I, (cc & 0xf0) | DACREG_CC_CLKB | DACREG_CC_CLKB_D); break; default: dprintk("%s: wrong clock code '%d'\n", __FUNCTION__, clock); return 0; } udelay(300); /* power up the dac & return to "normal" non-indexed mode */ dac_i_write(DACREG_CR0_I, cr0 & ~DACREG_CR0_PWDOWN & ~DACREG_CR0_EN_INDEXED); return 1;}static int sst_set_pll_ics(struct fb_info *info, const struct pll_timing *t, const int clock){ struct sstfb_par *par = (struct sstfb_par *) info->par; u8 pll_ctrl; sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL); pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA); switch(clock) { case VID_CLOCK: sst_dac_write(DACREG_ICS_PLLWMA, 0x0); /* CLK0, f0 */ sst_dac_write(DACREG_ICS_PLLDATA, t->m); sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n); /* selects freq f0 for clock 0 */ sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL); sst_dac_write(DACREG_ICS_PLLDATA, (pll_ctrl & 0xd8) | DACREG_ICS_CLK0 | DACREG_ICS_CLK0_0); break; case GFX_CLOCK : sst_dac_write(DACREG_ICS_PLLWMA, 0xa); /* CLK1, fA */ sst_dac_write(DACREG_ICS_PLLDATA, t->m); sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n); /* selects freq fA for clock 1 */ sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL); sst_dac_write(DACREG_ICS_PLLDATA, (pll_ctrl & 0xef) | DACREG_ICS_CLK1_A); break; default: dprintk("%s: wrong clock code '%d'\n", __FUNCTION__, clock); return 0; } udelay(300); return 1;}static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp){ struct sstfb_par *par = (struct sstfb_par *) info->par; u8 cr0; sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_read(DACREG_RMR); /* read 4 times RMR */ sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); /* the fifth time, CR0 is read */ cr0 = sst_dac_read(DACREG_RMR); sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_read(DACREG_RMR); /* read 4 times RMR */ sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR); /* cr0 */ switch(bpp) { case 16: sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP); break;#ifdef EN_24_32_BPP case 24: case 32: sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_24BPP); break;#endif default: dprintk("%s: bad depth '%u'\n", __FUNCTION__, bpp); break; }}static void sst_set_vidmod_ics(struct fb_info *info, const int bpp){ struct sstfb_par *par = (struct sstfb_par *) info->par; switch(bpp) { case 16: sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP); break;#ifdef EN_24_32_BPP case 24: case 32: sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_24BPP); break;#endif default: dprintk("%s: bad depth '%u'\n", __FUNCTION__, bpp); break; }}/* * detect dac type * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset, * dram refresh disabled, FbiInit remaped. * TODO: mmh.. maybe i shoud put the "prerequisite" in the func ... */static struct dac_switch dacs[] __devinitdata = { { .name = "TI TVP3409", .detect = sst_detect_ti, .set_pll = sst_set_pll_att_ti, .set_vidmod = sst_set_vidmod_att_ti }, { .name = "AT&T ATT20C409", .detect = sst_detect_att, .set_pll = sst_set_pll_att_ti, .set_vidmod = sst_set_vidmod_att_ti }, { .name = "ICS ICS5342", .detect = sst_detect_ics, .set_pll = sst_set_pll_ics, .set_vidmod = sst_set_vidmod_ics },};static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par){ int i, ret = 0; for (i=0; i<sizeof(dacs)/sizeof(dacs[0]); i++) { ret = dacs[i].detect(info); if (ret) break; } if (!ret) return 0; f_dprintk("%s found %s\n", __FUNCTION__, dacs[i].name); par->dac_sw = dacs[i]; return 1;}/* * Internal Routines */static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par){ u32 fbiinit0, fbiinit1, fbiinit4; struct pci_dev *dev = par->dev; struct pll_timing gfx_timings; struct sst_spec *spec; int Fout; spec = &voodoo_spec[par->type]; f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 " " fbiinit6\n"); f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n", sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2), sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6)); /* disable video clock */ pci_write_config_dword(dev, PCI_VCLK_DISABLE, 0); /* enable writing to init registers, disable pci fifo */ pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR); /* reset video */ sst_set_bits(FBIINIT1, VIDEO_RESET); sst_wait_idle(); /* reset gfx + pci fifo */ sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET); sst_wait_idle(); /* unreset fifo */ /*sst_unset_bits(FBIINIT0, FIFO_RESET); sst_wait_idle();*/ /* unreset FBI */ /*sst_unset_bits(FBIINIT0, FBI_RESET); sst_wait_idle();*/ /* disable dram refresh */ sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH); sst_wait_idle(); /* remap fbinit2/3 to dac */ pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR | PCI_REMAP_DAC ); /* detect dac type */ if (!sst_detect_dactype(info, par)) { eprintk("Unknown dac type\n"); //FIXME watch it: we are not in a safe state, bad bad bad. return 0; } /* set graphic clock */ par->gfx_clock = spec->default_gfx_clock; if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) { iprintk("Using supplied graphic freq : %dMHz\n", gfxclk); par->gfx_clock = gfxclk *1000; } else if (gfxclk) { wprintk ("%dMhz is way out of spec! Using default\n", gfxclk); } sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings); par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK); /* disable fbiinit remap */ pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR| PCI_EN_FIFO_WR ); /* defaults init registers */ /* FbiInit0: unreset gfx, unreset fifo */ fbiinit0 = FBIINIT0_DEFAULT; fbiinit1 = FBIINIT1_DEFAULT; fbiinit4 = FBIINIT4_DEFAULT; if (vgapass) fbiinit0 &= ~EN_VGA_PASSTHROUGH; else fbiinit0 |= EN_VGA_PASSTHROUGH; if (slowpci) { fbiinit1 |= SLOW_PCI_WRITES; fbiinit4 |= SLOW_PCI_READS; } else { fbiinit1 &= ~SLOW_PCI_WRITES; fbiinit4 &= ~SLOW_PCI_READS; } sst_write(FBIINIT0, fbiinit0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?