Index: arch/arm/mach-imx/generic.c =================================================================== --- arch/arm/mach-imx/generic.c (revision 3303) +++ arch/arm/mach-imx/generic.c (working copy) @@ -30,6 +30,10 @@ #include #include +//#undef VGA_SCREEN +#define VGA_SCREEN 1 +#define NORM_SCREEN 0 +#define SVGA_SCREEN 0 void imx_gpio_mode(int gpio_mode) { unsigned int pin = gpio_mode & GPIO_PIN_MASK; @@ -480,12 +484,22 @@ while (CSCR & CSCR_SPLL_RESTART) ; #endif - /* Set the peripheral clock divider 3 (PERDIV3) to divide by 6 */ -// PCDR1 &= ~PCDR1_PERDIV3_MASK; -// PCDR1 |= PCDR1_PERDIV3(5); +#if VGA_SCREEN + /* Set the peripheral clock divider 3 (PERDIV3) to divide by 7 */ + PCDR1 &= ~PCDR1_PERDIV3_MASK; + PCDR1 |= PCDR1_PERDIV3(7); // 6 is preferred, but triggers a bug in the MX21 LCDC controller that causes the graphic overlay window to pan to the right uncontrollably. +#endif +#if SVGA_SCREEN + /* Set the peripheral clock divider 3 (PERDIV3) to divide by 2 */ + PCDR1 &= ~PCDR1_PERDIV3_MASK; + PCDR1 |= PCDR1_PERDIV3(1); // set to 176 MHz +#endif +#if NORM_SCREEN + /* Set the peripheral clock divider 3 (PERDIV3) to divide by 8 */ /* For 352 MHz clock - PCLCK3 = 44MHz */ PCDR1 &= ~PCDR1_PERDIV3_MASK; PCDR1 |= PCDR1_PERDIV3(7); +#endif // printk( "+++set PCLK2,4\n" ); /* For 352 MHz clock - PCLCK2 = 33MHz */ Index: arch/arm/mach-imx/mx21ads.c =================================================================== --- arch/arm/mach-imx/mx21ads.c (revision 3672) +++ arch/arm/mach-imx/mx21ads.c (working copy) @@ -75,12 +75,26 @@ unsigned int chumby_hwversion; EXPORT_SYMBOL(chumby_hwversion); +#define HIRES_SCREEN 1 +#define SVGA_SCREEN 0 +#define NORM_SCREEN 0 + static struct imxfb_mach_info mx21ads_fb_info __initdata = { // PERDIV3 = 7, 44 MHz clock rate .pixclock = 62500, .bpp = 16, +#if HIRES_SCREEN + .xres = 640, + .yres = 480, +#endif +#if SVGA_SCREEN + .xres = 800, + .yres = 600, +#endif +#if NORM_SCREEN .xres = 320, .yres = 240, +#endif .hsync_len = 0x1, .vsync_len = 0x1, .left_margin = 0xf, @@ -411,7 +425,8 @@ // A11 USBH1_FS PB26 // A12 USBH1_OE PB27 // G11 USBH_ON PB25 - + +#if 1 // make 0 to turn off internal usb port imx_gpio_mode(29 | GPIO_PORTB | GPIO_PF | GPIO_OUT | GPIO_PUEN ); // USBH1_TXDP imx_gpio_mode(28 | GPIO_PORTB | GPIO_PF | GPIO_OUT | GPIO_PUEN ); // USBH1_TXDM imx_gpio_mode(31 | GPIO_PORTB | GPIO_PF | GPIO_IN | GPIO_PUEN ); // USBH1_RXDP @@ -419,6 +434,13 @@ imx_gpio_mode(26 | GPIO_PORTB | GPIO_PF | GPIO_OUT ); /* USBH1 FS */ imx_gpio_mode(27 | GPIO_PORTB | GPIO_PF | GPIO_OUT | GPIO_PUEN ); // USBH1_OE imx_gpio_mode(25 | GPIO_PORTB | GPIO_PF | GPIO_OUT | GPIO_PUEN ); // USBH_ON +#else + DDIR(1) |= 0xFC000000; + OCR2(1) |= 0xFFF00000; + ICONFA2(1) &= 0x000FFFFF; + GIUS(1) |= 0xFC000000; + DR(1) |= 0xFC000000; +#endif PUEN(1) |= 0x08000000; // enable pull-up on OE line -- may want to consider this also on the other 2 ports printk( "DDIR(1): %08X\n", DDIR(1)); Index: drivers/video/imxfb.c =================================================================== --- drivers/video/imxfb.c (revision 3304) +++ drivers/video/imxfb.c (working copy) @@ -17,6 +17,10 @@ */ #define DEBUG 1 +#undef EMU_HIRES_SCREEN +#define VGA_SCREEN 1 +#define SVGA_SCREEN 0 +#define NORM_SCREEN 0 // pr_debug was replaced with printk @@ -72,6 +76,8 @@ .transp = { .offset = 0, .length = 0, }, }; +static unsigned long global_a = 0; + static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info); static int imxfbov_activate_var(struct fb_var_screeninfo *var, struct fb_info *info); @@ -366,26 +372,32 @@ if (fbi->pcr & PCR_REV_VS) { /* Vertical scan is reversed */ +#ifdef EMU_HIRES_SCREEN + int xres = 320; + int yres = 240; + int bpp = fbi->max_bpp; + int offset = (xres * (yres - 1) * (bpp / 8)); +#else int xres = fbi->max_xres; int yres = fbi->max_yres; int bpp = fbi->max_bpp; int offset = (xres * (yres - 1) * (bpp / 8)); - +#endif // LCDC frame buffer logo force setting code framebuffer -- bunnie - for( i = 0; i < 0x25800; i++ ) { + for( i = 0; i < 0x96000; i++ ) { *((unsigned char *)fbi->screen_dma + offset + i) = *((unsigned char *)0xC2500000 + i); } LCDC_SSA = fbi->screen_dma + offset; } else { // LCDC frame buffer logo force setting code framebuffer -- bunnie - for( i = 0; i < 0x25800; i++ ) { + for( i = 0; i < 0x96000; i++ ) { *((unsigned char *)fbi->screen_dma + i) = *((unsigned char *)0xC2500000 + i); } LCDC_SSA = fbi->screen_dma; } /* physical screen start address */ - LCDC_VPW = VPW_VPW(fbi->max_xres * fbi->max_bpp / 8 / 4); + LCDC_VPW = VPW_VPW(fbi->max_xres * fbi->max_bpp / 8 / 4); /* panning offset 0 (0 pixel offset) */ LCDC_POS = 0x00000000; @@ -424,6 +436,7 @@ /* panning offset 0 (0 pixel offset) */ LCDC_LGWPOR = 0x00000000; + LCDC_LGWPR = 0; /* fixed burst length (see erratum 11) */ LCDC_LGWDCR = DMACR_HM(3) | DMACR_TM(8); @@ -545,7 +558,11 @@ VCR_V_WAIT_1(var->upper_margin) | VCR_V_WAIT_2(var->lower_margin); +#ifdef EMU_HIRES_SCREEN + LCDC_SIZE = SIZE_XMAX(320) | SIZE_YMAX(240); +#else LCDC_SIZE = SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres); +#endif LCDC_PCR = fbi->pcr; LCDC_PWMR = fbi->pwmr; LCDC_LSCR1 = fbi->lscr1; @@ -604,8 +621,8 @@ // BPIX (LPCR[27:25]) = 101 :16pp in memory // PIXPOL (LPCR[24]) = 0 :Pixels are active low - // FLMPOL (LPCR[23]) = 0 :VSYNC is active high - // LPPOL (LPCR[22]) = 0 :HSYNC is active high + // FLMPOL (LPCR[23]) = 1 :VSYNC is active low + // LPPOL (LPCR[22]) = 1 :HSYNC is active low // CLKPOL (LPCR[21]) = 0 :LSCLK is active on positive edge // OEPOL (LPCR[20]) = 0 :OE is active high @@ -619,8 +636,85 @@ // SCLKSEL (LPCR[7]) = 1 :Enable OE and LSCLK when no data output // SHARP (LPCR[6]) = 0 :Disable Sharp signals - // PCD (LPCR[5:0]) = 000100 :Pixel Clock = LSCLK = 33.25MHz/5 = 6.65MHz (DI demo board is @ 5.26MHz) - // = 000111 :V and H timing calculated with Pixel Clock = LSCLK = 33.25MHz/8 = 4.15MHz, but less noise at higher LSCLK + // PCD (LPCR[5:0]) = 000001 :Pixel Clock = LSCLK = 50.285 / 2 = 25.142 + + // we want 25.175 MHz (typ) + + // 1100 1010 1100 1000 0000 0000 1000 0001 + // CAC8 0081 +#if VGA_SCREEN + LCDC_PCR = 0xCAC80082; + + // If we're not using a Sharp panel, clear this register to be safe + LCDC_LSCR1 = 0x00000000; + + // Configure horizontal LCD timing + // 30 = H_WIDTH = 0x1E + // TH - (HS + EP) = 800 - (640 + 30) = 130 = H_WAIT_1 = 0x82 + // HS-DEN - HS time 144 - 30 = 114 = H_WAIT_2 = 0x72 + LCDC_HCR = 0x78008272; + + // Configure vertical LCD timing + // V_WIDTH = 3 + // V_WIDTH_1 = 525 - (480 + 35) = 10 = 0xA + // V_WIDTH_2 = TSTV - TWV = 35 - 3 = 32 = 0x20 + LCDC_VCR = 0x0C000A20; + + LCDC_LGWPOR = 0x00000000; + LCDC_LGWPR = 0; +#endif +#if SVGA_SCREEN + // Setup LCDC panel configuration + // TFT (LPCR[31]) = 1 :TFT display + // COLOR (LPCR[30]) = 1 :Color display + // PBSIZ (LPCR[29:28]) = 00 :Active matrix fixed at 16bpp + + // BPIX (LPCR[27:25]) = 101 :16pp in memory + // PIXPOL (LPCR[24]) = 0 :Pixels are active low + + // FLMPOL (LPCR[23]) = 1 :VSYNC is active low + // LPPOL (LPCR[22]) = 1 :HSYNC is active low + // CLKPOL (LPCR[21]) = 1 :LSCLK is active on negative edge + // OEPOL (LPCR[20]) = 0 :OE is active high + + // SCLKIDLE (LPCR[19]) = 1 :Enable LSCLK when VSYNC is idle + // END_SEL (LPCR[18]) = 0 :Image in memory is in little endian format + // SWAP_SEL (LPCR[17]) = 0 :Ignored for big endian format + // REV_VS (LPCR[16]) = 0 :Vertical scan in normal direction + + // ACDSEL (LPCR[15]) = 0 :Ignored for TFT display + // ACD (LPCR[14:8]) = 0000000 :Ignored for TFT display + + // SCLKSEL (LPCR[7]) = 1 :Enable OE and LSCLK when no data output + // SHARP (LPCR[6]) = 0 :Disable Sharp signals + // PCD (LPCR[5:0]) = 000100 :Pixel Clock = LSCLK = 176 / 5 = 35.2 MHz + + // we want 40 MHz (typ) + + // 1100 1010 1110 1000 0000 0000 1000 0100 + // CAC8 0081 + + LCDC_PCR = 0xCAE80084; + + // If we're not using a Sharp panel, clear this register to be safe + LCDC_LSCR1 = 0x00000000; + + // Configure horizontal LCD timing + // 128 = H_WIDTH = 0x80 - 1 = 0x7F + // TH - (HS + EP) = 1056 - (800 + 128) = 128 = H_WAIT_1 = 0x80 - 4 (cycle fudge) = 0x7C + // H_WAIT_2 = 128 = 0x0 + LCDC_HCR = 0x7F007C00; + + // Configure vertical LCD timing + // V_WIDTH = 4 + // V_WIDTH_1 = 666 - (600 + 4 + 23) = 0x27 + // V_WIDTH_2 = 23 = 0x17 + LCDC_VCR = 0x10002717; + + LCDC_LGWPOR = 0x00000000; + LCDC_LGWPR = 0; +#endif +#if NORM_SCREEN LCDC_PCR = 0xCA080084; // If we're not using a Sharp panel, clear this register to be safe @@ -631,6 +725,8 @@ // Configure vertical LCD timing LCDC_VCR = 0x10000F0F; +#endif + } // Setup DMA for main frame buffer @@ -651,7 +747,14 @@ struct imxfb_info *fbi = info->par; printk( "imxfbov_activate_var\n" ); +#ifdef EMU_HIRES_SCREEN + LCDC_LGWSR = SIZE_XMAX(320) | SIZE_YMAX(240); +#else LCDC_LGWSR = SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres); + +#endif + LCDC_LGWPOR = 0x00000000; + LCDC_LGWPR = 0; LCDC_LGWDCR = fbi->dmacr; LCDC_LGWPR = 0; @@ -1063,7 +1166,7 @@ green = (key >> 8) & 0x3f; blue = (key >> 0) & 0x3f; - lgwcr |= ((red << 12) | (green << 6) | (blue)); + lgwcr |= (((red << 12) | (green << 6) | (blue)) & 0x3ffff); printk( "imxfb_proc_write_key %lx\n", (unsigned long) lgwcr ); LCDC_LGWCR = lgwcr; @@ -1071,7 +1174,94 @@ return count; } +static int imxfb_proc_debug(char *buf, char **start, off_t offset, + int count, int *eof, void *data) +{ + int len; + int i; + + len = sprintf(buf, "dumping\n" ); + *eof = 1; + + // hack hack, but whatever, it's a lot easier and faster to write for debug purposes + printk("LCDC_SSA : %08lx\n", (unsigned long) LCDC_SSA); + printk("LCDC_SIZE : %08lx\n", (unsigned long) LCDC_SIZE); + printk("LCDC_VPW : %08lx\n", (unsigned long) LCDC_VPW); + printk("LCDC_CPOS : %08lx\n", (unsigned long) LCDC_CPOS); + printk("LCDC_LCWHB : %08lx\n", (unsigned long) LCDC_LCWHB); + printk("LCDC_LCHCC : %08lx\n", (unsigned long) LCDC_LCHCC); + printk("LCDC_PCR : %08lx\n", (unsigned long) LCDC_PCR); + printk("LCDC_HCR : %08lx\n", (unsigned long) LCDC_HCR); + printk("LCDC_VCR : %08lx\n", (unsigned long) LCDC_VCR); + printk("LCDC_POS : %08lx\n", (unsigned long) LCDC_POS); + printk("LCDC_LSCR1 : %08lx\n", (unsigned long) LCDC_LSCR1); + printk("LCDC_PWMR : %08lx\n", (unsigned long) LCDC_PWMR); + printk("LCDC_DMACR : %08lx\n", (unsigned long) LCDC_DMACR); + printk("LCDC_RMCR : %08lx\n", (unsigned long) LCDC_RMCR); + printk("LCDC_LCDICR: %08lx\n", (unsigned long) LCDC_LCDICR); + printk("LCDC_LCDISR: %08lx\n", (unsigned long) LCDC_LCDISR); + printk("LCDC_LGWSAR: %08lx\n", (unsigned long) LCDC_LGWSAR); + printk("LCDC_LGWSR : %08lx\n", (unsigned long) LCDC_LGWSR); + printk("LCDC_LGWVPWR:%08lx\n", (unsigned long) LCDC_LGWVPWR); + printk("LCDC_LGWPOR: %08lx\n", (unsigned long) LCDC_LGWPOR); + printk("LCDC_LGWPR : %08lx\n", (unsigned long) LCDC_LGWPR); + printk("LCDC_LGWCR : %08lx\n", (unsigned long) LCDC_LGWCR); + printk("LCDC_PALETTE(0): %08lx\n", (unsigned long) LCDC_PALETTE(0)); + printk("LCDC_PALETTE(1): %08lx\n", (unsigned long) LCDC_PALETTE(1)); + printk("LCDC_PALETTE(2): %08lx\n", (unsigned long) LCDC_PALETTE(2)); + printk("LCDC_PALETTE(3): %08lx\n", (unsigned long) LCDC_PALETTE(3)); +#if 0 + printk("WSRA: %08lx\n", (unsigned long) WSRA ); + printk("WSRB: %08lx\n", (unsigned long) WSRB ); + printk("XSRA: %08lx\n", (unsigned long) XSRA ); + printk("XSRB: %08lx\n", (unsigned long) XSRB ); + printk("YSRA: %08lx\n", (unsigned long) YSRA ); + printk("YSRB: %08lx\n", (unsigned long) YSRB ); + for( i = 0; i < 16; i++ ) { + printk("SAR(%d): %08lx\n", i, (unsigned long) SAR(i) ); + printk("DAR(%d): %08lx\n", i, (unsigned long) DAR(i) ); + printk("CNTR(%d): %08lx\n", i, (unsigned long) CNTR(i) ); + printk("CCR(%d): %08lx\n", i, (unsigned long) CCR(i) ); + printk("RSSR(%d): %08lx\n", i, (unsigned long) RSSR(i) ); + printk("BLR(%d): %08lx\n", i, (unsigned long) BLR(i) ); + printk("CHCNTR(%d): %08lx\n", i, (unsigned long) CHCNTR(i) ); + } +#endif + + return len; +} + + +static int imxfb_proc_write_debug(struct file *file, const char *buf, + unsigned long count, void *data) +{ + unsigned long d; + d = simple_strtoul(buf, NULL, 0); + + printk( "imxfb set register %08lx with %08lx\n", global_a, d ); + + if( global_a > 0x68 ) + printk( "error: address out of range.\n" ); + else + __REG(IMX_LCDC_BASE + global_a) = d; + + return count; +} + +static int imxfb_proc_write_debugAddr(struct file *file, const char *buf, + unsigned long count, void *data) +{ + unsigned long a; + a = simple_strtoul(buf, NULL, 0); + + global_a = a; + + printk( "imxfb addr set to %lx\n", global_a ); + + return count; +} + static int imxfb_proc_read_key_en(char *buf, char **start, off_t offset, int count, int *eof, void *data) { @@ -1096,9 +1286,14 @@ en = simple_strtoul(buf, NULL, 0); if (en) { - LCDC_LGWCR |= LGWCR_GWCKE; + uint32_t saveClock = PCCR0 & PCCR0_HCLK_LCDC_EN; // save state of HCLK + PCCR0 &= ~ PCCR0_HCLK_LCDC_EN; // force HCLK off + + LCDC_LGWCR |= LGWCR_GWCKE; + + PCCR0 |= saveClock; // restore the state of HCLK } else { - LCDC_LGWCR &= ~LGWCR_GWCKE; + LCDC_LGWCR &= ~LGWCR_GWCKE; } return count; @@ -1126,6 +1321,14 @@ imxfb_proc_read_key_en, NULL); pde->write_proc = imxfb_proc_write_key_en; + pde = create_proc_read_entry("driver/imxfb/debug", 0, NULL, + imxfb_proc_debug, NULL ); + pde->write_proc = imxfb_proc_write_debug; + + pde = create_proc_read_entry("driver/imxfb/debugAddr", 0, NULL, + imxfb_proc_debug, NULL ); + pde->write_proc = imxfb_proc_write_debugAddr; + } static int __init imxfb_probe(struct platform_device *pdev) @@ -1247,7 +1450,7 @@ // for( i = 0; i < 0x40000; i++ ) { // *((unsigned char *)LCDC_SSA + i) = *((unsigned char *)0xC1000000 + i); // } - for( i = 0; i < 0x25800; i++ ) { + for( i = 0; i < 0xA6000; i++ ) { *((unsigned char *)LCDC_SSA + i) = *((unsigned char *)0xC2500000 + i); } // consider hoisting above the DMA setting code in imxfb_enable_controller