diff options
Diffstat (limited to 'drivers/video')
117 files changed, 14379 insertions, 4165 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3b54b3940178..9bbb2855ea91 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -7,6 +7,8 @@ menu "Graphics support" source "drivers/char/agp/Kconfig" +source "drivers/gpu/vga/Kconfig" + source "drivers/gpu/drm/Kconfig" config VGASTATE @@ -935,7 +937,7 @@ config FB_S1D13XXX config FB_ATMEL tristate "AT91/AT32 LCD Controller support" - depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || AVR32) + depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9G10 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 || AVR32) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -951,7 +953,7 @@ config FB_INTSRAM config FB_ATMEL_STN bool "Use a STN display with AT91/AT32 LCD Controller" - depends on FB_ATMEL && MACH_AT91SAM9261EK + depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK) default n help Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD @@ -1273,26 +1275,6 @@ config FB_MATROX_MAVEN painting procedures (the secondary head does not use acceleration engine). -config FB_MATROX_MULTIHEAD - bool "Multihead support" - depends on FB_MATROX - ---help--- - Say Y here if you have more than one (supported) Matrox device in - your computer and you want to use all of them for different monitors - ("multihead"). If you have only one device, you should say N because - the driver compiled with Y is larger and a bit slower, especially on - ia32 (ix86). - - If you said M to "Matrox unified accelerated driver" and N here, you - will still be able to use several Matrox devices simultaneously: - insert several instances of the module matroxfb into the kernel - with insmod, supplying the parameter "dev=N" where N is 0, 1, etc. - for the different Matrox devices. This method is slightly faster but - uses 40 KB of kernel memory per Matrox card. - - There is no need for enabling 'Matrox multihead support' if you have - only one Matrox card in the box. - config FB_RADEON tristate "ATI Radeon display support" depends on FB && PCI @@ -1867,7 +1849,7 @@ config FB_W100 config FB_SH_MOBILE_LCDC tristate "SuperH Mobile LCDC framebuffer support" - depends on FB && SUPERH + depends on FB && SUPERH && HAVE_CLK select FB_SYS_FILLRECT select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT @@ -2039,6 +2021,17 @@ config FB_SH7760 and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for panels <= 320 pixel horizontal resolution. +config FB_DA8XX + tristate "DA8xx/OMAP-L1xx Framebuffer support" + depends on FB && ARCH_DAVINCI_DA8XX + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + This is the frame buffer device driver for the TI LCD controller + found on DA8xx/OMAP-L1xx SoCs. + If unsure, say N. + config FB_VIRTUAL tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" depends on FB @@ -2115,6 +2108,17 @@ config FB_MB862XX_LIME ---help--- Framebuffer support for Fujitsu Lime GDC on host CPU bus. +config FB_EP93XX + tristate "EP93XX frame buffer support" + depends on FB && ARCH_EP93XX + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Framebuffer driver for the Cirrus Logic EP93XX series of processors. + This driver is also available as a module. The module will be called + ep93xx-fb. + config FB_PRE_INIT_FB bool "Don't reinitialize, use bootloader's GDC/Display configuration" depends on FB_MB862XX_LIME @@ -2122,6 +2126,14 @@ config FB_PRE_INIT_FB Select this option if display contents should be inherited as set by the bootloader. +config FB_MSM + tristate + depends on FB && ARCH_MSM + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + default y + config FB_MX3 tristate "MX3 Framebuffer support" depends on FB && MX3_IPU diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 01a819f47371..80232e124889 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -85,6 +85,7 @@ obj-$(CONFIG_FB_Q40) += q40fb.o obj-$(CONFIG_FB_TGA) += tgafb.o obj-$(CONFIG_FB_HP300) += hpfb.o obj-$(CONFIG_FB_G364) += g364fb.o +obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o obj-$(CONFIG_FB_HIT) += hitfb.o obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o @@ -126,6 +127,7 @@ obj-$(CONFIG_FB_OMAP) += omap/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ +obj-$(CONFIG_FB_MSM) += msm/ # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o @@ -136,6 +138,7 @@ obj-$(CONFIG_FB_OF) += offb.o obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o obj-$(CONFIG_FB_MX3) += mx3fb.o +obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o # the test framebuffer is last obj-$(CONFIG_FB_VIRTUAL) += vfb.o diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index da05f0801bb7..2830ffd72976 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -182,7 +182,8 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) { unsigned long value; - if (!(cpu_is_at91sam9261() || cpu_is_at32ap7000())) + if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10() + || cpu_is_at32ap7000())) return xres; value = xres; @@ -824,7 +825,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) info->fix = atmel_lcdfb_fix; /* Enable LCDC Clocks */ - if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) { + if (cpu_is_at91sam9261() || cpu_is_at91sam9g10() + || cpu_is_at32ap7000()) { sinfo->bus_clk = clk_get(dev, "hck1"); if (IS_ERR(sinfo->bus_clk)) { ret = PTR_ERR(sinfo->bus_clk); diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 63d3739d43a8..913b4a47ae52 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -132,7 +132,7 @@ #endif #define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args) -#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args) +#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args) #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) @@ -188,24 +188,23 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par) */ static void ATIReduceRatio(int *Numerator, int *Denominator) { - int Multiplier, Divider, Remainder; + int Multiplier, Divider, Remainder; - Multiplier = *Numerator; - Divider = *Denominator; + Multiplier = *Numerator; + Divider = *Denominator; - while ((Remainder = Multiplier % Divider)) - { - Multiplier = Divider; - Divider = Remainder; - } + while ((Remainder = Multiplier % Divider)) { + Multiplier = Divider; + Divider = Remainder; + } - *Numerator /= Divider; - *Denominator /= Divider; + *Numerator /= Divider; + *Denominator /= Divider; } #endif - /* - * The Hardware parameters for each card - */ +/* + * The Hardware parameters for each card + */ struct pci_mmap_map { unsigned long voff; @@ -223,17 +222,19 @@ static struct fb_fix_screeninfo atyfb_fix __devinitdata = { .ypanstep = 1, }; - /* - * Frame buffer device API - */ +/* + * Frame buffer device API + */ static int atyfb_open(struct fb_info *info, int user); static int atyfb_release(struct fb_info *info, int user); -static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); +static int atyfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info); static int atyfb_set_par(struct fb_info *info); static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info); -static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); + u_int transp, struct fb_info *info); +static int atyfb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info); static int atyfb_blank(int blank, struct fb_info *info); static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg); #ifdef __sparc__ @@ -241,9 +242,9 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma); #endif static int atyfb_sync(struct fb_info *info); - /* - * Internal routines - */ +/* + * Internal routines + */ static int aty_init(struct fb_info *info); @@ -254,8 +255,11 @@ static int store_video_par(char *videopar, unsigned char m64_num); static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); -static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc); -static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var); +static int aty_var_to_crtc(const struct fb_info *info, + const struct fb_var_screeninfo *var, + struct crtc *crtc); +static int aty_crtc_to_var(const struct crtc *crtc, + struct fb_var_screeninfo *var); static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info); #ifdef CONFIG_PPC static int read_aty_sense(const struct atyfb_par *par); @@ -264,9 +268,9 @@ static int read_aty_sense(const struct atyfb_par *par); static DEFINE_MUTEX(reboot_lock); static struct fb_info *reboot_info; - /* - * Interface used by the world - */ +/* + * Interface used by the world + */ static struct fb_var_screeninfo default_var = { /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ @@ -452,14 +456,14 @@ static int __devinit correct_chipset(struct atyfb_par *par) type = chip_id & CFG_CHIP_TYPE; rev = (chip_id & CFG_CHIP_REV) >> 24; - switch(par->pci_id) { + switch (par->pci_id) { #ifdef CONFIG_FB_ATY_GX case PCI_CHIP_MACH64GX: - if(type != 0x00d7) + if (type != 0x00d7) return -ENODEV; break; case PCI_CHIP_MACH64CX: - if(type != 0x0057) + if (type != 0x0057) return -ENODEV; break; #endif @@ -564,7 +568,8 @@ static char *aty_xl_ram[8] __devinitdata = { }; #endif /* CONFIG_FB_ATY_CT */ -static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *par) +static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, + struct atyfb_par *par) { u32 pixclock = var->pixclock; #ifdef CONFIG_FB_ATY_GENERIC_LCD @@ -572,7 +577,7 @@ static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *p par->pll.ct.xres = 0; if (par->lcd_table != 0) { lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par); - if(lcd_on_off & LCD_ON) { + if (lcd_on_off & LCD_ON) { par->pll.ct.xres = var->xres; pixclock = par->lcd_pixclock; } @@ -584,7 +589,7 @@ static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *p #if defined(CONFIG_PPC) /* - * Apple monitor sense + * Apple monitor sense */ static int __devinit read_aty_sense(const struct atyfb_par *par) @@ -625,16 +630,16 @@ static int __devinit read_aty_sense(const struct atyfb_par *par) /* ------------------------------------------------------------------------- */ /* - * CRTC programming + * CRTC programming */ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) { #ifdef CONFIG_FB_ATY_GENERIC_LCD if (par->lcd_table != 0) { - if(!M64_HAS(LT_LCD_REGS)) { - crtc->lcd_index = aty_ld_le32(LCD_INDEX, par); - aty_st_le32(LCD_INDEX, crtc->lcd_index, par); + if (!M64_HAS(LT_LCD_REGS)) { + crtc->lcd_index = aty_ld_le32(LCD_INDEX, par); + aty_st_le32(LCD_INDEX, crtc->lcd_index, par); } crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par); crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par); @@ -642,7 +647,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) /* switch to non shadow registers */ aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & - ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); + ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); /* save stretching */ crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par); @@ -663,7 +668,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) if (par->lcd_table != 0) { /* switch to shadow registers */ aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) | - SHADOW_EN | SHADOW_RW_EN, par); + SHADOW_EN | SHADOW_RW_EN, par); crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par); crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par); @@ -680,21 +685,20 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) #ifdef CONFIG_FB_ATY_GENERIC_LCD if (par->lcd_table != 0) { /* stop CRTC */ - aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par); + aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & + ~(CRTC_EXT_DISP_EN | CRTC_EN), par); /* update non-shadow registers first */ aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par); aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & - ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); + ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); /* temporarily disable stretching */ - aty_st_lcd(HORZ_STRETCHING, - crtc->horz_stretching & - ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par); - aty_st_lcd(VERT_STRETCHING, - crtc->vert_stretching & - ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | - VERT_STRETCH_USE0 | VERT_STRETCH_EN), par); + aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching & + ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par); + aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching & + ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | + VERT_STRETCH_USE0 | VERT_STRETCH_EN), par); } #endif /* turn off CRT */ @@ -702,17 +706,19 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) DPRINTK("setting up CRTC\n"); DPRINTK("set primary CRT to %ix%i %c%c composite %c\n", - ((((crtc->h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->v_tot_disp>>16) & 0x7ff) + 1), - (crtc->h_sync_strt_wid & 0x200000)?'N':'P', (crtc->v_sync_strt_wid & 0x200000)?'N':'P', - (crtc->gen_cntl & CRTC_CSYNC_EN)?'P':'N'); - - DPRINTK("CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp); - DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid); - DPRINTK("CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp); - DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid); + ((((crtc->h_tot_disp >> 16) & 0xff) + 1) << 3), + (((crtc->v_tot_disp >> 16) & 0x7ff) + 1), + (crtc->h_sync_strt_wid & 0x200000) ? 'N' : 'P', + (crtc->v_sync_strt_wid & 0x200000) ? 'N' : 'P', + (crtc->gen_cntl & CRTC_CSYNC_EN) ? 'P' : 'N'); + + DPRINTK("CRTC_H_TOTAL_DISP: %x\n", crtc->h_tot_disp); + DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n", crtc->h_sync_strt_wid); + DPRINTK("CRTC_V_TOTAL_DISP: %x\n", crtc->v_tot_disp); + DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n", crtc->v_sync_strt_wid); DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch); DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline); - DPRINTK("CRTC_GEN_CNTL: %x\n",crtc->gen_cntl); + DPRINTK("CRTC_GEN_CNTL: %x\n", crtc->gen_cntl); aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par); aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par); @@ -732,16 +738,22 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) if (par->lcd_table != 0) { /* switch to shadow registers */ aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) | - (SHADOW_EN | SHADOW_RW_EN), par); + SHADOW_EN | SHADOW_RW_EN, par); DPRINTK("set shadow CRT to %ix%i %c%c\n", - ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1), - (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P'); - - DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", crtc->shadow_h_tot_disp); - DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", crtc->shadow_h_sync_strt_wid); - DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", crtc->shadow_v_tot_disp); - DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", crtc->shadow_v_sync_strt_wid); + ((((crtc->shadow_h_tot_disp >> 16) & 0xff) + 1) << 3), + (((crtc->shadow_v_tot_disp >> 16) & 0x7ff) + 1), + (crtc->shadow_h_sync_strt_wid & 0x200000) ? 'N' : 'P', + (crtc->shadow_v_sync_strt_wid & 0x200000) ? 'N' : 'P'); + + DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", + crtc->shadow_h_tot_disp); + DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", + crtc->shadow_h_sync_strt_wid); + DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", + crtc->shadow_v_tot_disp); + DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", + crtc->shadow_v_sync_strt_wid); aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par); aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par); @@ -752,16 +764,16 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl); DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching); DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching); - if(!M64_HAS(LT_LCD_REGS)) - DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch); + if (!M64_HAS(LT_LCD_REGS)) + DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch); aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par); aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par); aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par); - if(!M64_HAS(LT_LCD_REGS)) { - aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par); - aty_ld_le32(LCD_INDEX, par); - aty_st_le32(LCD_INDEX, crtc->lcd_index, par); + if (!M64_HAS(LT_LCD_REGS)) { + aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par); + aty_ld_le32(LCD_INDEX, par); + aty_st_le32(LCD_INDEX, crtc->lcd_index, par); } } #endif /* CONFIG_FB_ATY_GENERIC_LCD */ @@ -779,7 +791,8 @@ static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp) } static int aty_var_to_crtc(const struct fb_info *info, - const struct fb_var_screeninfo *var, struct crtc *crtc) + const struct fb_var_screeninfo *var, + struct crtc *crtc) { struct atyfb_par *par = (struct atyfb_par *) info->par; u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp; @@ -814,34 +827,32 @@ static int aty_var_to_crtc(const struct fb_info *info, if (bpp <= 8) { bpp = 8; pix_width = CRTC_PIX_WIDTH_8BPP; - dp_pix_width = - HOST_8BPP | SRC_8BPP | DST_8BPP | - BYTE_ORDER_LSB_TO_MSB; + dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_8BPP; } else if (bpp <= 15) { bpp = 16; pix_width = CRTC_PIX_WIDTH_15BPP; dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | - BYTE_ORDER_LSB_TO_MSB; + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_15BPP; } else if (bpp <= 16) { bpp = 16; pix_width = CRTC_PIX_WIDTH_16BPP; dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP | - BYTE_ORDER_LSB_TO_MSB; + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_16BPP; } else if (bpp <= 24 && M64_HAS(INTEGRATED)) { bpp = 24; pix_width = CRTC_PIX_WIDTH_24BPP; - dp_pix_width = - HOST_8BPP | SRC_8BPP | DST_8BPP | - BYTE_ORDER_LSB_TO_MSB; + dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_24BPP; } else if (bpp <= 32) { bpp = 32; pix_width = CRTC_PIX_WIDTH_32BPP; dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP | - BYTE_ORDER_LSB_TO_MSB; + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_32BPP; } else FAIL("invalid bpp"); @@ -854,9 +865,9 @@ static int aty_var_to_crtc(const struct fb_info *info, h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; - if((xres > 1600) || (yres > 1200)) { + if ((xres > 1600) || (yres > 1200)) { FAIL("MACH64 chips are designed for max 1600x1200\n" - "select anoter resolution."); + "select anoter resolution."); } h_sync_strt = h_disp + var->right_margin; h_sync_end = h_sync_strt + var->hsync_len; @@ -869,11 +880,12 @@ static int aty_var_to_crtc(const struct fb_info *info, #ifdef CONFIG_FB_ATY_GENERIC_LCD if (par->lcd_table != 0) { - if(!M64_HAS(LT_LCD_REGS)) { - u32 lcd_index = aty_ld_le32(LCD_INDEX, par); - crtc->lcd_index = lcd_index & - ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS); - aty_st_le32(LCD_INDEX, lcd_index, par); + if (!M64_HAS(LT_LCD_REGS)) { + u32 lcd_index = aty_ld_le32(LCD_INDEX, par); + crtc->lcd_index = lcd_index & + ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | + LCD_SRC_SEL | CRTC2_DISPLAY_DIS); + aty_st_le32(LCD_INDEX, lcd_index, par); } if (!M64_HAS(MOBIL_BUS)) @@ -888,12 +900,14 @@ static int aty_var_to_crtc(const struct fb_info *info, USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN); crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT; - if((crtc->lcd_gen_cntl & LCD_ON) && - ((xres > par->lcd_width) || (yres > par->lcd_height))) { - /* We cannot display the mode on the LCD. If the CRT is enabled - we can turn off the LCD. - If the CRT is off, it isn't a good idea to switch it on; we don't - know if one is connected. So it's better to fail then. + if ((crtc->lcd_gen_cntl & LCD_ON) && + ((xres > par->lcd_width) || (yres > par->lcd_height))) { + /* + * We cannot display the mode on the LCD. If the CRT is + * enabled we can turn off the LCD. + * If the CRT is off, it isn't a good idea to switch it + * on; we don't know if one is connected. So it's better + * to fail then. */ if (crtc->lcd_gen_cntl & CRT_ON) { if (!(var->activate & FB_ACTIVATE_TEST)) @@ -916,17 +930,18 @@ static int aty_var_to_crtc(const struct fb_info *info, vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED); - /* This is horror! When we simulate, say 640x480 on an 800x600 - LCD monitor, the CRTC should be programmed 800x600 values for - the non visible part, but 640x480 for the visible part. - This code has been tested on a laptop with it's 1400x1050 LCD - monitor and a conventional monitor both switched on. - Tested modes: 1280x1024, 1152x864, 1024x768, 800x600, - works with little glitches also with DOUBLESCAN modes + /* + * This is horror! When we simulate, say 640x480 on an 800x600 + * LCD monitor, the CRTC should be programmed 800x600 values for + * the non visible part, but 640x480 for the visible part. + * This code has been tested on a laptop with it's 1400x1050 LCD + * monitor and a conventional monitor both switched on. + * Tested modes: 1280x1024, 1152x864, 1024x768, 800x600, + * works with little glitches also with DOUBLESCAN modes */ if (yres < par->lcd_height) { VScan = par->lcd_height / yres; - if(VScan > 1) { + if (VScan > 1) { VScan = 2; vmode |= FB_VMODE_DOUBLE; } @@ -952,7 +967,7 @@ static int aty_var_to_crtc(const struct fb_info *info, FAIL_MAX("h_disp too large", h_disp, 0xff); FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff); /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/ - if(h_sync_wid > 0x1f) + if (h_sync_wid > 0x1f) h_sync_wid = 0x1f; FAIL_MAX("h_total too large", h_total, 0x1ff); @@ -978,7 +993,7 @@ static int aty_var_to_crtc(const struct fb_info *info, FAIL_MAX("v_disp too large", v_disp, 0x7ff); FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff); /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/ - if(v_sync_wid > 0x1f) + if (v_sync_wid > 0x1f) v_sync_wid = 0x1f; FAIL_MAX("v_total too large", v_total, 0x7ff); @@ -995,11 +1010,13 @@ static int aty_var_to_crtc(const struct fb_info *info, ((line_length / bpp) << 22); crtc->vline_crnt_vline = 0; - crtc->h_tot_disp = h_total | (h_disp<<16); - crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) | - ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21); - crtc->v_tot_disp = v_total | (v_disp<<16); - crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21); + crtc->h_tot_disp = h_total | (h_disp << 16); + crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly << 8) | + ((h_sync_strt & 0x100) << 4) | (h_sync_wid << 16) | + (h_sync_pol << 21); + crtc->v_tot_disp = v_total | (v_disp << 16); + crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) | + (v_sync_pol << 21); /* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */ crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync; @@ -1014,13 +1031,15 @@ static int aty_var_to_crtc(const struct fb_info *info, #ifdef CONFIG_FB_ATY_GENERIC_LCD if (par->lcd_table != 0) { vdisplay = yres; - if(vmode & FB_VMODE_DOUBLE) + if (vmode & FB_VMODE_DOUBLE) vdisplay <<= 1; crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH); crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | - /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/ - USE_SHADOWED_VEND | USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN); - crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR/* | LOCK_8DOT*/); + /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/ + USE_SHADOWED_VEND | + USE_SHADOWED_ROWCUR | + SHADOW_EN | SHADOW_RW_EN); + crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR/* | LOCK_8DOT*/; /* MOBILITY M1 tested, FIXME: LT */ crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par); @@ -1028,28 +1047,32 @@ static int aty_var_to_crtc(const struct fb_info *info, crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) & ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3); - crtc->horz_stretching &= - ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO | - HORZ_STRETCH_MODE | HORZ_STRETCH_EN); + crtc->horz_stretching &= ~(HORZ_STRETCH_RATIO | + HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO | + HORZ_STRETCH_MODE | HORZ_STRETCH_EN); if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) { do { /* - * The horizontal blender misbehaves when HDisplay is less than a - * a certain threshold (440 for a 1024-wide panel). It doesn't - * stretch such modes enough. Use pixel replication instead of - * blending to stretch modes that can be made to exactly fit the - * panel width. The undocumented "NoLCDBlend" option allows the - * pixel-replicated mode to be slightly wider or narrower than the - * panel width. It also causes a mode that is exactly half as wide - * as the panel to be pixel-replicated, rather than blended. - */ + * The horizontal blender misbehaves when + * HDisplay is less than a certain threshold + * (440 for a 1024-wide panel). It doesn't + * stretch such modes enough. Use pixel + * replication instead of blending to stretch + * modes that can be made to exactly fit the + * panel width. The undocumented "NoLCDBlend" + * option allows the pixel-replicated mode to + * be slightly wider or narrower than the + * panel width. It also causes a mode that is + * exactly half as wide as the panel to be + * pixel-replicated, rather than blended. + */ int HDisplay = xres & ~7; int nStretch = par->lcd_width / HDisplay; int Remainder = par->lcd_width % HDisplay; if ((!Remainder && ((nStretch > 2))) || - (((HDisplay * 16) / par->lcd_width) < 7)) { - static const char StretchLoops[] = {10, 12, 13, 15, 16}; + (((HDisplay * 16) / par->lcd_width) < 7)) { + static const char StretchLoops[] = { 10, 12, 13, 15, 16 }; int horz_stretch_loop = -1, BestRemainder; int Numerator = HDisplay, Denominator = par->lcd_width; int Index = 5; @@ -1098,12 +1121,12 @@ static int aty_var_to_crtc(const struct fb_info *info, (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0)); if (!M64_HAS(LT_LCD_REGS) && - xres <= (M64_HAS(MOBIL_BUS)?1024:800)) + xres <= (M64_HAS(MOBIL_BUS) ? 1024 : 800)) crtc->ext_vert_stretch |= VERT_STRETCH_MODE; } else { /* - * Don't use vertical blending if the mode is too wide or not - * vertically stretched. + * Don't use vertical blending if the mode is too wide + * or not vertically stretched. */ crtc->vert_stretching = 0; } @@ -1125,11 +1148,11 @@ static int aty_var_to_crtc(const struct fb_info *info, return 0; } -static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var) +static int aty_crtc_to_var(const struct crtc *crtc, + struct fb_var_screeninfo *var) { u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync; - u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, - h_sync_pol; + u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; u32 pix_width; u32 double_scan, interlace; @@ -1161,8 +1184,8 @@ static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *va lower = v_sync_strt - v_disp; vslen = v_sync_wid; sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) | - (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | - (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); + (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | + (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); switch (pix_width) { #if 0 @@ -1252,20 +1275,21 @@ static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *va var->vsync_len = vslen; var->sync = sync; var->vmode = FB_VMODE_NONINTERLACED; - /* In double scan mode, the vertical parameters are doubled, so we need to - half them to get the right values. - In interlaced mode the values are already correct, so no correction is - necessary. + /* + * In double scan mode, the vertical parameters are doubled, + * so we need to halve them to get the right values. + * In interlaced mode the values are already correct, + * so no correction is necessary. */ if (interlace) var->vmode = FB_VMODE_INTERLACED; if (double_scan) { var->vmode = FB_VMODE_DOUBLE; - var->yres>>=1; - var->upper_margin>>=1; - var->lower_margin>>=1; - var->vsync_len>>=1; + var->yres >>= 1; + var->upper_margin >>= 1; + var->lower_margin >>= 1; + var->vsync_len >>= 1; } return 0; @@ -1286,7 +1310,8 @@ static int atyfb_set_par(struct fb_info *info) if (par->asleep) return 0; - if ((err = aty_var_to_crtc(info, var, &par->crtc))) + err = aty_var_to_crtc(info, var, &par->crtc); + if (err) return err; pixclock = atyfb_get_pixclock(var, par); @@ -1295,7 +1320,9 @@ static int atyfb_set_par(struct fb_info *info) PRINTKE("Invalid pixclock\n"); return -EINVAL; } else { - if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll))) + err = par->pll_ops->var_to_pll(info, pixclock, + var->bits_per_pixel, &par->pll); + if (err) return err; } @@ -1313,22 +1340,23 @@ static int atyfb_set_par(struct fb_info *info) wait_for_idle(par); aty_set_crtc(par, &par->crtc); - par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel, par->accel_flags); + par->dac_ops->set_dac(info, &par->pll, + var->bits_per_pixel, par->accel_flags); par->pll_ops->set_pll(info, &par->pll); #ifdef DEBUG - if(par->pll_ops && par->pll_ops->pll_to_var) - pixclock_in_ps = par->pll_ops->pll_to_var(info, &(par->pll)); + if (par->pll_ops && par->pll_ops->pll_to_var) + pixclock_in_ps = par->pll_ops->pll_to_var(info, &par->pll); else pixclock_in_ps = 0; - if(0 == pixclock_in_ps) { + if (0 == pixclock_in_ps) { PRINTKE("ALERT ops->pll_to_var get 0\n"); pixclock_in_ps = pixclock; } memset(&debug, 0, sizeof(debug)); - if(!aty_crtc_to_var(&(par->crtc), &debug)) { + if (!aty_crtc_to_var(&par->crtc, &debug)) { u32 hSync, vRefresh; u32 h_disp, h_sync_strt, h_sync_end, h_total; u32 v_disp, v_sync_strt, v_sync_end, v_total; @@ -1344,16 +1372,20 @@ static int atyfb_set_par(struct fb_info *info) hSync = 1000000000 / (pixclock_in_ps * h_total); vRefresh = (hSync * 1000) / v_total; - if (par->crtc.gen_cntl & CRTC_INTERLACE_EN) - vRefresh *= 2; - if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN) - vRefresh /= 2; + if (par->crtc.gen_cntl & CRTC_INTERLACE_EN) + vRefresh *= 2; + if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN) + vRefresh /= 2; DPRINTK("atyfb_set_par\n"); - DPRINTK(" Set Visible Mode to %ix%i-%i\n", var->xres, var->yres, var->bits_per_pixel); - DPRINTK(" Virtual resolution %ix%i, pixclock_in_ps %i (calculated %i)\n", - var->xres_virtual, var->yres_virtual, pixclock, pixclock_in_ps); - DPRINTK(" Dot clock: %i MHz\n", 1000000 / pixclock_in_ps); + DPRINTK(" Set Visible Mode to %ix%i-%i\n", + var->xres, var->yres, var->bits_per_pixel); + DPRINTK(" Virtual resolution %ix%i, " + "pixclock_in_ps %i (calculated %i)\n", + var->xres_virtual, var->yres_virtual, + pixclock, pixclock_in_ps); + DPRINTK(" Dot clock: %i MHz\n", + 1000000 / pixclock_in_ps); DPRINTK(" Horizontal sync: %i kHz\n", hSync); DPRINTK(" Vertical refresh: %i Hz\n", vRefresh); DPRINTK(" x style: %i.%03i %i %i %i %i %i %i %i %i\n", @@ -1448,7 +1480,8 @@ static int atyfb_set_par(struct fb_info *info) base = 0x2000; printk("debug atyfb: Mach64 non-shadow register values:"); for (i = 0; i < 256; i = i+4) { - if(i%16 == 0) printk("\ndebug atyfb: 0x%04X: ", base + i); + if (i % 16 == 0) + printk("\ndebug atyfb: 0x%04X: ", base + i); printk(" %08X", aty_ld_le32(i, par)); } printk("\n\n"); @@ -1458,8 +1491,10 @@ static int atyfb_set_par(struct fb_info *info) base = 0x00; printk("debug atyfb: Mach64 PLL register values:"); for (i = 0; i < 64; i++) { - if(i%16 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i); - if(i%4 == 0) printk(" "); + if (i % 16 == 0) + printk("\ndebug atyfb: 0x%02X: ", base + i); + if (i % 4 == 0) + printk(" "); printk("%02X", aty_ld_pll_ct(i, par)); } printk("\n\n"); @@ -1470,19 +1505,21 @@ static int atyfb_set_par(struct fb_info *info) /* LCD registers */ base = 0x00; printk("debug atyfb: LCD register values:"); - if(M64_HAS(LT_LCD_REGS)) { - for(i = 0; i <= POWER_MANAGEMENT; i++) { - if(i == EXT_VERT_STRETCH) - continue; - printk("\ndebug atyfb: 0x%04X: ", lt_lcd_regs[i]); - printk(" %08X", aty_ld_lcd(i, par)); - } - + if (M64_HAS(LT_LCD_REGS)) { + for (i = 0; i <= POWER_MANAGEMENT; i++) { + if (i == EXT_VERT_STRETCH) + continue; + printk("\ndebug atyfb: 0x%04X: ", + lt_lcd_regs[i]); + printk(" %08X", aty_ld_lcd(i, par)); + } } else { - for (i = 0; i < 64; i++) { - if(i%4 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i); - printk(" %08X", aty_ld_lcd(i, par)); - } + for (i = 0; i < 64; i++) { + if (i % 4 == 0) + printk("\ndebug atyfb: 0x%02X: ", + base + i); + printk(" %08X", aty_ld_lcd(i, par)); + } } printk("\n\n"); } @@ -1500,9 +1537,10 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) union aty_pll pll; u32 pixclock; - memcpy(&pll, &(par->pll), sizeof(pll)); + memcpy(&pll, &par->pll, sizeof(pll)); - if((err = aty_var_to_crtc(info, var, &crtc))) + err = aty_var_to_crtc(info, var, &crtc); + if (err) return err; pixclock = atyfb_get_pixclock(var, par); @@ -1512,7 +1550,9 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) PRINTKE("Invalid pixclock\n"); return -EINVAL; } else { - if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll))) + err = par->pll_ops->var_to_pll(info, pixclock, + var->bits_per_pixel, &pll); + if (err) return err; } @@ -1539,9 +1579,9 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info) } - /* - * Open/Release the frame buffer device - */ +/* + * Open/Release the frame buffer device + */ static int atyfb_open(struct fb_info *info, int user) { @@ -1553,7 +1593,7 @@ static int atyfb_open(struct fb_info *info, int user) par->mmaped = 0; #endif } - return (0); + return 0; } static irqreturn_t aty_irq(int irq, void *dev_id) @@ -1568,7 +1608,8 @@ static irqreturn_t aty_irq(int irq, void *dev_id) if (int_cntl & CRTC_VBLANK_INT) { /* clear interrupt */ - aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par); + aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | + CRTC_VBLANK_INT_AK, par); par->vblank.count++; if (par->vblank.pan_display) { par->vblank.pan_display = 0; @@ -1603,9 +1644,11 @@ static int aty_enable_irq(struct atyfb_par *par, int reenable) spin_lock_irq(&par->int_lock); int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK; if (!(int_cntl & CRTC_VBLANK_INT_EN)) { - printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl); + printk("atyfb: someone disabled IRQ [%08x]\n", + int_cntl); /* re-enable interrupt */ - aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par ); + aty_st_le32(CRTC_INT_CNTL, int_cntl | + CRTC_VBLANK_INT_EN, par); } spin_unlock_irq(&par->int_lock); } @@ -1625,7 +1668,7 @@ static int aty_disable_irq(struct atyfb_par *par) spin_lock_irq(&par->int_lock); int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK; /* disable interrupt */ - aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par ); + aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par); spin_unlock_irq(&par->int_lock); free_irq(par->irq, par); } @@ -1636,50 +1679,62 @@ static int aty_disable_irq(struct atyfb_par *par) static int atyfb_release(struct fb_info *info, int user) { struct atyfb_par *par = (struct atyfb_par *) info->par; - if (user) { - par->open--; - mdelay(1); - wait_for_idle(par); - if (!par->open) { #ifdef __sparc__ - int was_mmaped = par->mmaped; + int was_mmaped; +#endif - par->mmaped = 0; + if (!user) + return 0; - if (was_mmaped) { - struct fb_var_screeninfo var; + par->open--; + mdelay(1); + wait_for_idle(par); - /* Now reset the default display config, we have no - * idea what the program(s) which mmap'd the chip did - * to the configuration, nor whether it restored it - * correctly. - */ - var = default_var; - if (noaccel) - var.accel_flags &= ~FB_ACCELF_TEXT; - else - var.accel_flags |= FB_ACCELF_TEXT; - if (var.yres == var.yres_virtual) { - u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2)); - var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual; - if (var.yres_virtual < var.yres) - var.yres_virtual = var.yres; - } - } -#endif - aty_disable_irq(par); + if (par->open) + return 0; + +#ifdef __sparc__ + was_mmaped = par->mmaped; + + par->mmaped = 0; + + if (was_mmaped) { + struct fb_var_screeninfo var; + + /* + * Now reset the default display config, we have + * no idea what the program(s) which mmap'd the + * chip did to the configuration, nor whether it + * restored it correctly. + */ + var = default_var; + if (noaccel) + var.accel_flags &= ~FB_ACCELF_TEXT; + else + var.accel_flags |= FB_ACCELF_TEXT; + if (var.yres == var.yres_virtual) { + u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2)); + var.yres_virtual = + ((videoram * 8) / var.bits_per_pixel) / + var.xres_virtual; + if (var.yres_virtual < var.yres) + var.yres_virtual = var.yres; } } - return (0); +#endif + aty_disable_irq(par); + + return 0; } - /* - * Pan or Wrap the Display - * - * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag - */ +/* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ -static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +static int atyfb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; u32 xres, yres, xoffset, yoffset; @@ -1690,7 +1745,8 @@ static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info yres >>= 1; xoffset = (var->xoffset + 7) & ~7; yoffset = var->yoffset; - if (xoffset + xres > par->crtc.vxres || yoffset + yres > par->crtc.vyres) + if (xoffset + xres > par->crtc.vxres || + yoffset + yres > par->crtc.vyres) return -EINVAL; info->var.xoffset = xoffset; info->var.yoffset = yoffset; @@ -1727,10 +1783,10 @@ static int aty_waitforvblank(struct atyfb_par *par, u32 crtc) return ret; count = vbl->count; - ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10); - if (ret < 0) { + ret = wait_event_interruptible_timeout(vbl->wait, + count != vbl->count, HZ/10); + if (ret < 0) return ret; - } if (ret == 0) { aty_enable_irq(par, 1); return -ETIMEDOUT; @@ -1784,7 +1840,8 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) fbtyp.fb_depth = info->var.bits_per_pixel; fbtyp.fb_cmsize = info->cmap.len; fbtyp.fb_size = info->fix.smem_len; - if (copy_to_user((struct fbtype __user *) arg, &fbtyp, sizeof(fbtyp))) + if (copy_to_user((struct fbtype __user *) arg, &fbtyp, + sizeof(fbtyp))) return -EFAULT; break; #endif /* __sparc__ */ @@ -1804,7 +1861,7 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) case ATYIO_CLKR: if (M64_HAS(INTEGRATED)) { struct atyclk clk; - union aty_pll *pll = &(par->pll); + union aty_pll *pll = &par->pll; u32 dsp_config = pll->ct.dsp_config; u32 dsp_on_off = pll->ct.dsp_on_off; clk.ref_clk_per = par->ref_clk_per; @@ -1829,8 +1886,9 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) case ATYIO_CLKW: if (M64_HAS(INTEGRATED)) { struct atyclk clk; - union aty_pll *pll = &(par->pll); - if (copy_from_user(&clk, (struct atyclk __user *) arg, sizeof(clk))) + union aty_pll *pll = &par->pll; + if (copy_from_user(&clk, (struct atyclk __user *) arg, + sizeof(clk))) return -EFAULT; par->ref_clk_per = clk.ref_clk_per; pll->ct.pll_ref_div = clk.pll_ref_div; @@ -1841,8 +1899,10 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) pll->ct.vclk_fb_div = clk.vclk_fb_div; pll->ct.vclk_post_div_real = clk.vclk_post_div; pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) | - ((clk.dsp_loop_latency & 0xf)<<16)| ((clk.dsp_precision & 7)<<20); - pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | ((clk.dsp_on & 0x7ff)<<16); + ((clk.dsp_loop_latency & 0xf) << 16) | + ((clk.dsp_precision & 7) << 20); + pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | + ((clk.dsp_on & 0x7ff) << 16); /*aty_calc_pll_ct(info, &pll->ct);*/ aty_set_pll_ct(info, pll); } else @@ -1913,8 +1973,7 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma) continue; map_size = par->mmap_map[i].size - (offset - start); - map_offset = - par->mmap_map[i].poff + (offset - start); + map_offset = par->mmap_map[i].poff + (offset - start); break; } if (!map_size) { @@ -1924,8 +1983,7 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma) if (page + map_size > size) map_size = size - page; - pgprot_val(vma->vm_page_prot) &= - ~(par->mmap_map[i].prot_mask); + pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask); pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag; if (remap_pfn_range(vma, vma->vm_start + page, @@ -2029,7 +2087,8 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) par->asleep = 1; par->lock_blank = 1; - /* Because we may change PCI D state ourselves, we need to + /* + * Because we may change PCI D state ourselves, we need to * first save the config space content so the core can * restore it properly on resume. */ @@ -2080,7 +2139,8 @@ static int atyfb_pci_resume(struct pci_dev *pdev) acquire_console_sem(); - /* PCI state will have been restored by the core, so + /* + * PCI state will have been restored by the core, so * we should be in D0 now with our config space fully * restored */ @@ -2192,8 +2252,8 @@ static void aty_bl_init(struct atyfb_par *par) info->bl_dev = bd; fb_bl_default_curve(info, 0, - 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, - 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); + 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, + 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1; bd->props.brightness = bd->props.max_brightness; @@ -2236,16 +2296,16 @@ static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk) size = ARRAY_SIZE(ragepro_tbl); } - for (i=0; i < size; i++) { + for (i = 0; i < size; i++) { if (xclk < refresh_tbl[i]) - break; + break; } par->mem_refresh_rate = i; } - /* - * Initialisation - */ +/* + * Initialisation + */ static struct fb_info *fb_list = NULL; @@ -2375,8 +2435,10 @@ static int __devinit aty_init(struct fb_info *info) } #endif #ifdef CONFIG_PPC_PMAC - /* The Apple iBook1 uses non-standard memory frequencies. We detect it - * and set the frequency manually. */ + /* + * The Apple iBook1 uses non-standard memory frequencies. + * We detect it and set the frequency manually. + */ if (machine_is_compatible("PowerBook2,1")) { par->pll_limits.mclk = 70; par->pll_limits.xclk = 53; @@ -2421,13 +2483,14 @@ static int __devinit aty_init(struct fb_info *info) /* save previous video mode */ aty_get_crtc(par, &par->saved_crtc); - if(par->pll_ops->get_pll) + if (par->pll_ops->get_pll) par->pll_ops->get_pll(info, &par->saved_pll); par->mem_cntl = aty_ld_le32(MEM_CNTL, par); gtb_memsize = M64_HAS(GTB_DSP); if (gtb_memsize) - switch (par->mem_cntl & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ + /* 0xF used instead of MEM_SIZE_ALIAS */ + switch (par->mem_cntl & 0xF) { case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2496,8 +2559,8 @@ static int __devinit aty_init(struct fb_info *info) } /* - * Reg Block 0 (CT-compatible block) is at mmio_start - * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400 + * Reg Block 0 (CT-compatible block) is at mmio_start + * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400 */ if (M64_HAS(GX)) { info->fix.mmio_len = 0x400; @@ -2516,84 +2579,98 @@ static int __devinit aty_init(struct fb_info *info) } PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n", - info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len >> 20), - info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max, - par->pll_limits.mclk, par->pll_limits.xclk); + info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len>>20), + info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, + par->pll_limits.pll_max, par->pll_limits.mclk, + par->pll_limits.xclk); #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT) if (M64_HAS(INTEGRATED)) { int i; - printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL " - "DSP_CONFIG DSP_ON_OFF CLOCK_CNTL\n" - "debug atyfb: %08x %08x %08x %08x %08x %08x %08x %08x\n" + printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL " + "EXT_MEM_CNTL CRTC_GEN_CNTL DSP_CONFIG " + "DSP_ON_OFF CLOCK_CNTL\n" + "debug atyfb: %08x %08x %08x " + "%08x %08x %08x " + "%08x %08x\n" "debug atyfb: PLL", - aty_ld_le32(BUS_CNTL, par), aty_ld_le32(DAC_CNTL, par), - aty_ld_le32(MEM_CNTL, par), aty_ld_le32(EXT_MEM_CNTL, par), - aty_ld_le32(CRTC_GEN_CNTL, par), aty_ld_le32(DSP_CONFIG, par), - aty_ld_le32(DSP_ON_OFF, par), aty_ld_le32(CLOCK_CNTL, par)); + aty_ld_le32(BUS_CNTL, par), + aty_ld_le32(DAC_CNTL, par), + aty_ld_le32(MEM_CNTL, par), + aty_ld_le32(EXT_MEM_CNTL, par), + aty_ld_le32(CRTC_GEN_CNTL, par), + aty_ld_le32(DSP_CONFIG, par), + aty_ld_le32(DSP_ON_OFF, par), + aty_ld_le32(CLOCK_CNTL, par)); for (i = 0; i < 40; i++) printk(" %02x", aty_ld_pll_ct(i, par)); printk("\n"); } #endif - if(par->pll_ops->init_pll) + if (par->pll_ops->init_pll) par->pll_ops->init_pll(info, &par->pll); if (par->pll_ops->resume_pll) par->pll_ops->resume_pll(info, &par->pll); /* - * Last page of 8 MB (4 MB on ISA) aperture is MMIO, - * unless the auxiliary register aperture is used. + * Last page of 8 MB (4 MB on ISA) aperture is MMIO, + * unless the auxiliary register aperture is used. */ - if (!par->aux_start && - (info->fix.smem_len == 0x800000 || (par->bus_type == ISA && info->fix.smem_len == 0x400000))) + (info->fix.smem_len == 0x800000 || + (par->bus_type == ISA && info->fix.smem_len == 0x400000))) info->fix.smem_len -= GUI_RESERVE; /* - * Disable register access through the linear aperture - * if the auxiliary aperture is used so we can access - * the full 8 MB of video RAM on 8 MB boards. + * Disable register access through the linear aperture + * if the auxiliary aperture is used so we can access + * the full 8 MB of video RAM on 8 MB boards. */ if (par->aux_start) - aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | + BUS_APER_REG_DIS, par); #ifdef CONFIG_MTRR par->mtrr_aper = -1; par->mtrr_reg = -1; if (!nomtrr) { /* Cover the whole resource. */ - par->mtrr_aper = mtrr_add(par->res_start, par->res_size, MTRR_TYPE_WRCOMB, 1); - if (par->mtrr_aper >= 0 && !par->aux_start) { + par->mtrr_aper = mtrr_add(par->res_start, par->res_size, + MTRR_TYPE_WRCOMB, 1); + if (par->mtrr_aper >= 0 && !par->aux_start) { /* Make a hole for mmio. */ - par->mtrr_reg = mtrr_add(par->res_start + 0x800000 - GUI_RESERVE, - GUI_RESERVE, MTRR_TYPE_UNCACHABLE, 1); + par->mtrr_reg = mtrr_add(par->res_start + 0x800000 - + GUI_RESERVE, GUI_RESERVE, + MTRR_TYPE_UNCACHABLE, 1); if (par->mtrr_reg < 0) { mtrr_del(par->mtrr_aper, 0, 0); par->mtrr_aper = -1; } - } + } } #endif info->fbops = &atyfb_ops; info->pseudo_palette = par->pseudo_palette; info->flags = FBINFO_DEFAULT | - FBINFO_HWACCEL_IMAGEBLIT | - FBINFO_HWACCEL_FILLRECT | - FBINFO_HWACCEL_COPYAREA | - FBINFO_HWACCEL_YPAN; + FBINFO_HWACCEL_IMAGEBLIT | + FBINFO_HWACCEL_FILLRECT | + FBINFO_HWACCEL_COPYAREA | + FBINFO_HWACCEL_YPAN; #ifdef CONFIG_PMAC_BACKLIGHT if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) { - /* these bits let the 101 powerbook wake up from sleep -- paulus */ - aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) - | (USE_F32KHZ | TRISTATE_MEM_EN), par); + /* + * these bits let the 101 powerbook + * wake up from sleep -- paulus + */ + aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) | + USE_F32KHZ | TRISTATE_MEM_EN, par); } else #endif if (M64_HAS(MOBIL_BUS) && backlight) { #ifdef CONFIG_FB_ATY_BACKLIGHT - aty_bl_init (par); + aty_bl_init(par); #endif } @@ -2601,8 +2678,8 @@ static int __devinit aty_init(struct fb_info *info) #ifdef CONFIG_PPC if (machine_is(powermac)) { /* - * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it - * applies to all Mac video cards + * FIXME: The NVRAM stuff should be put in a Mac-specific file, + * as it applies to all Mac video cards */ if (mode) { if (mac_find_mode(&var, info, mode, 8)) @@ -2615,8 +2692,7 @@ static int __devinit aty_init(struct fb_info *info) default_vmode = VMODE_1024_768_60; else if (machine_is_compatible("iMac")) default_vmode = VMODE_1024_768_75; - else if (machine_is_compatible - ("PowerBook2,1")) + else if (machine_is_compatible("PowerBook2,1")) /* iBook with 800x600 LCD */ default_vmode = VMODE_800_600_60; else @@ -2630,7 +2706,7 @@ static int __devinit aty_init(struct fb_info *info) if (default_cmode < CMODE_8 || default_cmode > CMODE_32) default_cmode = CMODE_8; if (!mac_vmode_to_var(default_vmode, default_cmode, - &var)) + &var)) has_var = 1; } } @@ -2702,12 +2778,12 @@ aty_init_exit: #ifdef CONFIG_MTRR if (par->mtrr_reg >= 0) { - mtrr_del(par->mtrr_reg, 0, 0); - par->mtrr_reg = -1; + mtrr_del(par->mtrr_reg, 0, 0); + par->mtrr_reg = -1; } if (par->mtrr_aper >= 0) { - mtrr_del(par->mtrr_aper, 0, 0); - par->mtrr_aper = -1; + mtrr_del(par->mtrr_aper, 0, 0); + par->mtrr_aper = -1; } #endif return ret; @@ -2735,18 +2811,18 @@ static int __devinit store_video_par(char *video_str, unsigned char m64_num) phys_size[m64_num] = size; phys_guiregbase[m64_num] = guiregbase; PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size, - guiregbase); + guiregbase); return 0; - mach64_invalid: + mach64_invalid: phys_vmembase[m64_num] = 0; return -1; } #endif /* CONFIG_ATARI */ - /* - * Blank the display. - */ +/* + * Blank the display. + */ static int atyfb_blank(int blank, struct fb_info *info) { @@ -2768,20 +2844,20 @@ static int atyfb_blank(int blank, struct fb_info *info) gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par); gen_cntl &= ~0x400004c; switch (blank) { - case FB_BLANK_UNBLANK: - break; - case FB_BLANK_NORMAL: - gen_cntl |= 0x4000040; - break; - case FB_BLANK_VSYNC_SUSPEND: - gen_cntl |= 0x4000048; - break; - case FB_BLANK_HSYNC_SUSPEND: - gen_cntl |= 0x4000044; - break; - case FB_BLANK_POWERDOWN: - gen_cntl |= 0x400004c; - break; + case FB_BLANK_UNBLANK: + break; + case FB_BLANK_NORMAL: + gen_cntl |= 0x4000040; + break; + case FB_BLANK_VSYNC_SUSPEND: + gen_cntl |= 0x4000048; + break; + case FB_BLANK_HSYNC_SUSPEND: + gen_cntl |= 0x4000044; + break; + case FB_BLANK_POWERDOWN: + gen_cntl |= 0x400004c; + break; } aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); @@ -2806,15 +2882,15 @@ static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue, aty_st_8(DAC_DATA, blue, par); } - /* - * Set a single color register. The values supplied are already - * rounded down to the hardware's capabilities (according to the - * entries in the var structure). Return != 0 for invalid regno. - * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR - */ +/* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR + */ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info) + u_int transp, struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; int i, depth; @@ -2868,16 +2944,15 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, if (depth == 16) { if (regno < 32) aty_st_pal(regno << 3, red, - par->palette[regno<<1].green, + par->palette[regno << 1].green, blue, par); - red = par->palette[regno>>1].red; - blue = par->palette[regno>>1].blue; + red = par->palette[regno >> 1].red; + blue = par->palette[regno >> 1].blue; regno <<= 2; } else if (depth == 15) { regno <<= 3; - for(i = 0; i < 8; i++) { - aty_st_pal(regno + i, red, green, blue, par); - } + for (i = 0; i < 8; i++) + aty_st_pal(regno + i, red, green, blue, par); } } aty_st_pal(regno, red, green, blue, par); @@ -2890,7 +2965,8 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, #ifdef __sparc__ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, - struct fb_info *info, unsigned long addr) + struct fb_info *info, + unsigned long addr) { struct atyfb_par *par = info->par; struct device_node *dp; @@ -2978,7 +3054,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, j++; } - if((ret = correct_chipset(par))) + ret = correct_chipset(par); + if (ret) return ret; if (IS_XL(pdev->device)) { @@ -3108,28 +3185,28 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) u32 driv_inf_tab, sig; u16 lcd_ofs; - /* To support an LCD panel, we should know it's dimensions and + /* + * To support an LCD panel, we should know it's dimensions and * it's desired pixel clock. * There are two ways to do it: * - Check the startup video mode and calculate the panel * size from it. This is unreliable. * - Read it from the driver information table in the video BIOS. - */ + */ /* Address of driver information table is at offset 0x78. */ driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78)); /* Check for the driver information table signature. */ - sig = (*(u32 *)driv_inf_tab); + sig = *(u32 *)driv_inf_tab; if ((sig == 0x54504c24) || /* Rage LT pro */ - (sig == 0x544d5224) || /* Rage mobility */ - (sig == 0x54435824) || /* Rage XC */ - (sig == 0x544c5824)) { /* Rage XL */ + (sig == 0x544d5224) || /* Rage mobility */ + (sig == 0x54435824) || /* Rage XC */ + (sig == 0x544c5824)) { /* Rage XL */ PRINTKI("BIOS contains driver information table.\n"); - lcd_ofs = (*(u16 *)(driv_inf_tab + 10)); + lcd_ofs = *(u16 *)(driv_inf_tab + 10); par->lcd_table = 0; - if (lcd_ofs != 0) { + if (lcd_ofs != 0) par->lcd_table = bios_base + lcd_ofs; - } } if (par->lcd_table != 0) { @@ -3144,14 +3221,16 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) u16 width, height, panel_type, refresh_rates; u16 *lcdmodeptr; u32 format; - u8 lcd_refresh_rates[16] = {50,56,60,67,70,72,75,76,85,90,100,120,140,150,160,200}; - /* The most important information is the panel size at + u8 lcd_refresh_rates[16] = { 50, 56, 60, 67, 70, 72, 75, 76, 85, + 90, 100, 120, 140, 150, 160, 200 }; + /* + * The most important information is the panel size at * offset 25 and 27, but there's some other nice information * which we print to the screen. */ id = *(u8 *)par->lcd_table; - strncpy(model,(char *)par->lcd_table+1,24); - model[23]=0; + strncpy(model, (char *)par->lcd_table+1, 24); + model[23] = 0; width = par->lcd_width = *(u16 *)(par->lcd_table+25); height = par->lcd_height = *(u16 *)(par->lcd_table+27); @@ -3164,7 +3243,7 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) txtdual = "dual (split) "; else txtdual = ""; - tech = (panel_type>>2) & 63; + tech = (panel_type >> 2) & 63; switch (tech) { case 0: txtmonitor = "passive matrix"; @@ -3224,22 +3303,24 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) } } PRINTKI("%s%s %s monitor detected: %s\n", - txtdual ,txtcolour, txtmonitor, model); + txtdual, txtcolour, txtmonitor, model); PRINTKI(" id=%d, %dx%d pixels, %s\n", id, width, height, txtformat); refresh_rates_buf[0] = 0; refresh_rates = *(u16 *)(par->lcd_table+62); m = 1; f = 0; - for (i=0;i<16;i++) { + for (i = 0; i < 16; i++) { if (refresh_rates & m) { if (f == 0) { - sprintf(strbuf, "%d", lcd_refresh_rates[i]); + sprintf(strbuf, "%d", + lcd_refresh_rates[i]); f++; } else { - sprintf(strbuf, ",%d", lcd_refresh_rates[i]); + sprintf(strbuf, ",%d", + lcd_refresh_rates[i]); } - strcat(refresh_rates_buf,strbuf); + strcat(refresh_rates_buf, strbuf); } m = m << 1; } @@ -3247,7 +3328,8 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) PRINTKI(" supports refresh rates [%s], default %d Hz\n", refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]); par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate]; - /* We now need to determine the crtc parameters for the + /* + * We now need to determine the crtc parameters for the * LCD monitor. This is tricky, because they are not stored * individually in the BIOS. Instead, the BIOS contains a * table of display modes that work for this monitor. @@ -3382,7 +3464,9 @@ static int __devinit init_from_bios(struct atyfb_par *par) } #endif /* __i386__ */ -static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, unsigned long addr) +static int __devinit atyfb_setup_generic(struct pci_dev *pdev, + struct fb_info *info, + unsigned long addr) { struct atyfb_par *par = info->par; u16 tmp; @@ -3429,10 +3513,12 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i goto atyfb_setup_generic_fail; } - if((ret = correct_chipset(par))) + ret = correct_chipset(par); + if (ret) goto atyfb_setup_generic_fail; #ifdef __i386__ - if((ret = init_from_bios(par))) + ret = init_from_bios(par); + if (ret) goto atyfb_setup_generic_fail; #endif if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN)) @@ -3457,7 +3543,8 @@ atyfb_setup_generic_fail: #endif /* !__sparc__ */ -static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit atyfb_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { unsigned long addr, res_start, res_size; struct fb_info *info; @@ -3482,10 +3569,10 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi /* Reserve space */ res_start = rp->start; res_size = rp->end - rp->start + 1; - if (!request_mem_region (res_start, res_size, "atyfb")) + if (!request_mem_region(res_start, res_size, "atyfb")) return -EBUSY; - /* Allocate framebuffer */ + /* Allocate framebuffer */ info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev); if (!info) { PRINTKE("atyfb_pci_probe() can't alloc fb_info\n"); @@ -3573,7 +3660,8 @@ static int __init atyfb_atari_probe(void) for (m64_num = 0; m64_num < mach64_count; m64_num++) { if (!phys_vmembase[m64_num] || !phys_size[m64_num] || !phys_guiregbase[m64_num]) { - PRINTKI("phys_*[%d] parameters not set => returning early. \n", m64_num); + PRINTKI("phys_*[%d] parameters not set => " + "returning early. \n", m64_num); continue; } @@ -3589,8 +3677,8 @@ static int __init atyfb_atari_probe(void) par->irq = (unsigned int) -1; /* something invalid */ /* - * Map the video memory (physical address given) to somewhere in the - * kernel address space. + * Map the video memory (physical address given) + * to somewhere in the kernel address space. */ info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]); info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */ @@ -3661,12 +3749,12 @@ static void __devexit atyfb_remove(struct fb_info *info) #ifdef CONFIG_MTRR if (par->mtrr_reg >= 0) { - mtrr_del(par->mtrr_reg, 0, 0); - par->mtrr_reg = -1; + mtrr_del(par->mtrr_reg, 0, 0); + par->mtrr_reg = -1; } if (par->mtrr_aper >= 0) { - mtrr_del(par->mtrr_aper, 0, 0); - par->mtrr_aper = -1; + mtrr_del(par->mtrr_aper, 0, 0); + par->mtrr_aper = -1; } #endif #ifndef __sparc__ @@ -3900,29 +3988,29 @@ static const struct dmi_system_id atyfb_reboot_ids[] = { static int __init atyfb_init(void) { - int err1 = 1, err2 = 1; + int err1 = 1, err2 = 1; #ifndef MODULE - char *option = NULL; + char *option = NULL; - if (fb_get_options("atyfb", &option)) - return -ENODEV; - atyfb_setup(option); + if (fb_get_options("atyfb", &option)) + return -ENODEV; + atyfb_setup(option); #endif #ifdef CONFIG_PCI - err1 = pci_register_driver(&atyfb_driver); + err1 = pci_register_driver(&atyfb_driver); #endif #ifdef CONFIG_ATARI - err2 = atyfb_atari_probe(); + err2 = atyfb_atari_probe(); #endif - if (err1 && err2) - return -ENODEV; + if (err1 && err2) + return -ENODEV; - if (dmi_check_system(atyfb_reboot_ids)) - register_reboot_notifier(&atyfb_reboot_notifier); + if (dmi_check_system(atyfb_reboot_ids)) + register_reboot_notifier(&atyfb_reboot_notifier); - return 0; + return 0; } static void __exit atyfb_exit(void) @@ -3951,8 +4039,7 @@ MODULE_PARM_DESC(mclk, "int: override memory clock"); module_param(xclk, int, 0); MODULE_PARM_DESC(xclk, "int: override accelerated engine clock"); module_param(comp_sync, int, 0); -MODULE_PARM_DESC(comp_sync, - "Set composite sync signal to low (0) or high (1)"); +MODULE_PARM_DESC(comp_sync, "Set composite sync signal to low (0) or high (1)"); module_param(mode, charp, 0); MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); #ifdef CONFIG_MTRR diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 378f27745a1d..a699aab63820 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -715,8 +715,11 @@ int au1100fb_setup(char *options) } /* Mode option (only option that start with digit) */ else if (isdigit(this_opt[0])) { - mode = kmalloc(strlen(this_opt) + 1, GFP_KERNEL); - strncpy(mode, this_opt, strlen(this_opt) + 1); + mode = kstrdup(this_opt, GFP_KERNEL); + if (!mode) { + print_err("memory allocation failed"); + return -ENOMEM; + } } /* Unsupported option */ else { diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index f9d19be05540..09bfa9662e4d 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -31,6 +31,13 @@ config LCD_CORGI Say y here to support the LCD panels usually found on SHARP corgi (C7x0) and spitz (Cxx00) models. +config LCD_LMS283GF05 + tristate "Samsung LMS283GF05 LCD" + depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO + help + SPI driver for Samsung LMS283GF05. This provides basic support + for powering the LCD up/down through a sysfs interface. + config LCD_LTV350QV tristate "Samsung LTV350QV LCD Panel" depends on LCD_CLASS_DEVICE && SPI_MASTER @@ -110,7 +117,7 @@ config BACKLIGHT_CLASS_DEVICE config BACKLIGHT_ATMEL_LCDC bool "Atmel LCDC Contrast-as-Backlight control" depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL - default y if MACH_SAM9261EK || MACH_SAM9263EK + default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK help This provides a backlight control internal to the Atmel LCDC driver. If the LCD "contrast control" on your board is wired @@ -229,3 +236,29 @@ config BACKLIGHT_SAHARA help If you have a Tabletkiosk Sahara Touch-iT, say y to enable the backlight driver. + +config BACKLIGHT_WM831X + tristate "WM831x PMIC Backlight Driver" + depends on BACKLIGHT_CLASS_DEVICE && MFD_WM831X + help + If you have a backlight driven by the ISINK and DCDC of a + WM831x PMIC say y to enable the backlight driver for it. + +config BACKLIGHT_ADX + tristate "Avionic Design Xanthos Backlight Driver" + depends on BACKLIGHT_CLASS_DEVICE && ARCH_PXA_ADX + default y + help + Say Y to enable the backlight driver on Avionic Design Xanthos-based + boards. + +config BACKLIGHT_ADP5520 + tristate "Backlight Driver for ADP5520/ADP5501 using WLED" + depends on BACKLIGHT_CLASS_DEVICE && PMIC_ADP5520 + help + If you have a LCD backlight connected to the BST/BL_SNK output of + ADP5520 or ADP5501, say Y here to enable this driver. + + To compile this driver as a module, choose M here: the module will + be called adp5520_bl. + diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 4eb178c1d684..9a405548874c 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o +obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o obj-$(CONFIG_LCD_ILI9320) += ili9320.o obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o @@ -24,4 +25,7 @@ obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o +obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o +obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o +obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c new file mode 100644 index 000000000000..ad05da5ba3c7 --- /dev/null +++ b/drivers/video/backlight/adp5520_bl.c @@ -0,0 +1,377 @@ +/* + * Backlight driver for Analog Devices ADP5520/ADP5501 MFD PMICs + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/fb.h> +#include <linux/backlight.h> +#include <linux/mfd/adp5520.h> + +struct adp5520_bl { + struct device *master; + struct adp5520_backlight_platfrom_data *pdata; + struct mutex lock; + unsigned long cached_daylight_max; + int id; + int current_brightness; +}; + +static int adp5520_bl_set(struct backlight_device *bl, int brightness) +{ + struct adp5520_bl *data = bl_get_data(bl); + struct device *master = data->master; + int ret = 0; + + if (data->pdata->en_ambl_sens) { + if ((brightness > 0) && (brightness < ADP5020_MAX_BRIGHTNESS)) { + /* Disable Ambient Light auto adjust */ + ret |= adp5520_clr_bits(master, BL_CONTROL, + BL_AUTO_ADJ); + ret |= adp5520_write(master, DAYLIGHT_MAX, brightness); + } else { + /* + * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust + * restore daylight l3 sysfs brightness + */ + ret |= adp5520_write(master, DAYLIGHT_MAX, + data->cached_daylight_max); + ret |= adp5520_set_bits(master, BL_CONTROL, + BL_AUTO_ADJ); + } + } else { + ret |= adp5520_write(master, DAYLIGHT_MAX, brightness); + } + + if (data->current_brightness && brightness == 0) + ret |= adp5520_set_bits(master, + MODE_STATUS, DIM_EN); + else if (data->current_brightness == 0 && brightness) + ret |= adp5520_clr_bits(master, + MODE_STATUS, DIM_EN); + + if (!ret) + data->current_brightness = brightness; + + return ret; +} + +static int adp5520_bl_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + return adp5520_bl_set(bl, brightness); +} + +static int adp5520_bl_get_brightness(struct backlight_device *bl) +{ + struct adp5520_bl *data = bl_get_data(bl); + int error; + uint8_t reg_val; + + error = adp5520_read(data->master, BL_VALUE, ®_val); + + return error ? data->current_brightness : reg_val; +} + +static struct backlight_ops adp5520_bl_ops = { + .update_status = adp5520_bl_update_status, + .get_brightness = adp5520_bl_get_brightness, +}; + +static int adp5520_bl_setup(struct backlight_device *bl) +{ + struct adp5520_bl *data = bl_get_data(bl); + struct device *master = data->master; + struct adp5520_backlight_platfrom_data *pdata = data->pdata; + int ret = 0; + + ret |= adp5520_write(master, DAYLIGHT_MAX, pdata->l1_daylight_max); + ret |= adp5520_write(master, DAYLIGHT_DIM, pdata->l1_daylight_dim); + + if (pdata->en_ambl_sens) { + data->cached_daylight_max = pdata->l1_daylight_max; + ret |= adp5520_write(master, OFFICE_MAX, pdata->l2_office_max); + ret |= adp5520_write(master, OFFICE_DIM, pdata->l2_office_dim); + ret |= adp5520_write(master, DARK_MAX, pdata->l3_dark_max); + ret |= adp5520_write(master, DARK_DIM, pdata->l3_dark_dim); + ret |= adp5520_write(master, L2_TRIP, pdata->l2_trip); + ret |= adp5520_write(master, L2_HYS, pdata->l2_hyst); + ret |= adp5520_write(master, L3_TRIP, pdata->l3_trip); + ret |= adp5520_write(master, L3_HYS, pdata->l3_hyst); + ret |= adp5520_write(master, ALS_CMPR_CFG, + ALS_CMPR_CFG_VAL(pdata->abml_filt, L3_EN)); + } + + ret |= adp5520_write(master, BL_CONTROL, + BL_CTRL_VAL(pdata->fade_led_law, pdata->en_ambl_sens)); + + ret |= adp5520_write(master, BL_FADE, FADE_VAL(pdata->fade_in, + pdata->fade_out)); + + ret |= adp5520_set_bits(master, MODE_STATUS, BL_EN | DIM_EN); + + return ret; +} + +static ssize_t adp5520_show(struct device *dev, char *buf, int reg) +{ + struct adp5520_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + + mutex_lock(&data->lock); + error = adp5520_read(data->master, reg, ®_val); + mutex_unlock(&data->lock); + + return sprintf(buf, "%u\n", reg_val); +} + +static ssize_t adp5520_store(struct device *dev, const char *buf, + size_t count, int reg) +{ + struct adp5520_bl *data = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = strict_strtoul(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&data->lock); + adp5520_write(data->master, reg, val); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t adp5520_bl_dark_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, DARK_MAX); +} + +static ssize_t adp5520_bl_dark_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, DARK_MAX); +} +static DEVICE_ATTR(dark_max, 0664, adp5520_bl_dark_max_show, + adp5520_bl_dark_max_store); + +static ssize_t adp5520_bl_office_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, OFFICE_MAX); +} + +static ssize_t adp5520_bl_office_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, OFFICE_MAX); +} +static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show, + adp5520_bl_office_max_store); + +static ssize_t adp5520_bl_daylight_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, DAYLIGHT_MAX); +} + +static ssize_t adp5520_bl_daylight_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct adp5520_bl *data = dev_get_drvdata(dev); + + strict_strtoul(buf, 10, &data->cached_daylight_max); + return adp5520_store(dev, buf, count, DAYLIGHT_MAX); +} +static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show, + adp5520_bl_daylight_max_store); + +static ssize_t adp5520_bl_dark_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, DARK_DIM); +} + +static ssize_t adp5520_bl_dark_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, DARK_DIM); +} +static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show, + adp5520_bl_dark_dim_store); + +static ssize_t adp5520_bl_office_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, OFFICE_DIM); +} + +static ssize_t adp5520_bl_office_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, OFFICE_DIM); +} +static DEVICE_ATTR(office_dim, 0664, adp5520_bl_office_dim_show, + adp5520_bl_office_dim_store); + +static ssize_t adp5520_bl_daylight_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, DAYLIGHT_DIM); +} + +static ssize_t adp5520_bl_daylight_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, DAYLIGHT_DIM); +} +static DEVICE_ATTR(daylight_dim, 0664, adp5520_bl_daylight_dim_show, + adp5520_bl_daylight_dim_store); + +static struct attribute *adp5520_bl_attributes[] = { + &dev_attr_dark_max.attr, + &dev_attr_dark_dim.attr, + &dev_attr_office_max.attr, + &dev_attr_office_dim.attr, + &dev_attr_daylight_max.attr, + &dev_attr_daylight_dim.attr, + NULL +}; + +static const struct attribute_group adp5520_bl_attr_group = { + .attrs = adp5520_bl_attributes, +}; + +static int __devinit adp5520_bl_probe(struct platform_device *pdev) +{ + struct backlight_device *bl; + struct adp5520_bl *data; + int ret = 0; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->master = pdev->dev.parent; + data->pdata = pdev->dev.platform_data; + + if (data->pdata == NULL) { + dev_err(&pdev->dev, "missing platform data\n"); + kfree(data); + return -ENODEV; + } + + data->id = pdev->id; + data->current_brightness = 0; + + mutex_init(&data->lock); + + bl = backlight_device_register(pdev->name, data->master, + data, &adp5520_bl_ops); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + kfree(data); + return PTR_ERR(bl); + } + + bl->props.max_brightness = + bl->props.brightness = ADP5020_MAX_BRIGHTNESS; + + if (data->pdata->en_ambl_sens) + ret = sysfs_create_group(&bl->dev.kobj, + &adp5520_bl_attr_group); + + if (ret) { + dev_err(&pdev->dev, "failed to register sysfs\n"); + backlight_device_unregister(bl); + kfree(data); + } + + platform_set_drvdata(pdev, bl); + ret |= adp5520_bl_setup(bl); + backlight_update_status(bl); + + return ret; +} + +static int __devexit adp5520_bl_remove(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct adp5520_bl *data = bl_get_data(bl); + + adp5520_clr_bits(data->master, MODE_STATUS, BL_EN); + + if (data->pdata->en_ambl_sens) + sysfs_remove_group(&bl->dev.kobj, + &adp5520_bl_attr_group); + + backlight_device_unregister(bl); + kfree(data); + + return 0; +} + +#ifdef CONFIG_PM +static int adp5520_bl_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + return adp5520_bl_set(bl, 0); +} + +static int adp5520_bl_resume(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + + backlight_update_status(bl); + return 0; +} +#else +#define adp5520_bl_suspend NULL +#define adp5520_bl_resume NULL +#endif + +static struct platform_driver adp5520_bl_driver = { + .driver = { + .name = "adp5520-backlight", + .owner = THIS_MODULE, + }, + .probe = adp5520_bl_probe, + .remove = __devexit_p(adp5520_bl_remove), + .suspend = adp5520_bl_suspend, + .resume = adp5520_bl_resume, +}; + +static int __init adp5520_bl_init(void) +{ + return platform_driver_register(&adp5520_bl_driver); +} +module_init(adp5520_bl_init); + +static void __exit adp5520_bl_exit(void) +{ + platform_driver_unregister(&adp5520_bl_driver); +} +module_exit(adp5520_bl_exit); + +MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_DESCRIPTION("ADP5520(01) Backlight Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:adp5520-backlight"); diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c new file mode 100644 index 000000000000..2c3bdfc620b7 --- /dev/null +++ b/drivers/video/backlight/adx_bl.c @@ -0,0 +1,178 @@ +/* + * linux/drivers/video/backlight/adx.c + * + * Copyright (C) 2009 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding <thierry.reding@avionic-design.de> + */ + +#include <linux/backlight.h> +#include <linux/fb.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +/* register definitions */ +#define ADX_BACKLIGHT_CONTROL 0x00 +#define ADX_BACKLIGHT_CONTROL_ENABLE (1 << 0) +#define ADX_BACKLIGHT_BRIGHTNESS 0x08 +#define ADX_BACKLIGHT_STATUS 0x10 +#define ADX_BACKLIGHT_ERROR 0x18 + +struct adxbl { + void __iomem *base; +}; + +static int adx_backlight_update_status(struct backlight_device *bldev) +{ + struct adxbl *bl = bl_get_data(bldev); + u32 value; + + value = bldev->props.brightness; + writel(value, bl->base + ADX_BACKLIGHT_BRIGHTNESS); + + value = readl(bl->base + ADX_BACKLIGHT_CONTROL); + + if (bldev->props.state & BL_CORE_FBBLANK) + value &= ~ADX_BACKLIGHT_CONTROL_ENABLE; + else + value |= ADX_BACKLIGHT_CONTROL_ENABLE; + + writel(value, bl->base + ADX_BACKLIGHT_CONTROL); + + return 0; +} + +static int adx_backlight_get_brightness(struct backlight_device *bldev) +{ + struct adxbl *bl = bl_get_data(bldev); + u32 brightness; + + brightness = readl(bl->base + ADX_BACKLIGHT_BRIGHTNESS); + return brightness & 0xff; +} + +static int adx_backlight_check_fb(struct fb_info *fb) +{ + return 1; +} + +static struct backlight_ops adx_backlight_ops = { + .options = 0, + .update_status = adx_backlight_update_status, + .get_brightness = adx_backlight_get_brightness, + .check_fb = adx_backlight_check_fb, +}; + +static int __devinit adx_backlight_probe(struct platform_device *pdev) +{ + struct backlight_device *bldev; + struct resource *res; + struct adxbl *bl; + int ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENXIO; + goto out; + } + + res = devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), res->name); + if (!res) { + ret = -ENXIO; + goto out; + } + + bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL); + if (!bl) { + ret = -ENOMEM; + goto out; + } + + bl->base = devm_ioremap_nocache(&pdev->dev, res->start, + resource_size(res)); + if (!bl->base) { + ret = -ENXIO; + goto out; + } + + bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, bl, + &adx_backlight_ops); + if (!bldev) { + ret = -ENOMEM; + goto out; + } + + bldev->props.max_brightness = 0xff; + bldev->props.brightness = 0xff; + bldev->props.power = FB_BLANK_UNBLANK; + + platform_set_drvdata(pdev, bldev); + +out: + return ret; +} + +static int __devexit adx_backlight_remove(struct platform_device *pdev) +{ + struct backlight_device *bldev; + int ret = 0; + + bldev = platform_get_drvdata(pdev); + bldev->props.power = FB_BLANK_UNBLANK; + bldev->props.brightness = 0xff; + backlight_update_status(bldev); + backlight_device_unregister(bldev); + platform_set_drvdata(pdev, NULL); + + return ret; +} + +#ifdef CONFIG_PM +static int adx_backlight_suspend(struct platform_device *pdev, + pm_message_t state) +{ + return 0; +} + +static int adx_backlight_resume(struct platform_device *pdev) +{ + return 0; +} +#else +#define adx_backlight_suspend NULL +#define adx_backlight_resume NULL +#endif + +static struct platform_driver adx_backlight_driver = { + .probe = adx_backlight_probe, + .remove = __devexit_p(adx_backlight_remove), + .suspend = adx_backlight_suspend, + .resume = adx_backlight_resume, + .driver = { + .name = "adx-backlight", + .owner = THIS_MODULE, + }, +}; + +static int __init adx_backlight_init(void) +{ + return platform_driver_register(&adx_backlight_driver); +} + +static void __exit adx_backlight_exit(void) +{ + platform_driver_unregister(&adx_backlight_driver); +} + +module_init(adx_backlight_init); +module_exit(adx_backlight_exit); + +MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); +MODULE_DESCRIPTION("Avionic Design Xanthos Backlight Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 157057c79ca3..6615ac7fa60a 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -73,6 +73,27 @@ static inline void backlight_unregister_fb(struct backlight_device *bd) } #endif /* CONFIG_FB */ +static void backlight_generate_event(struct backlight_device *bd, + enum backlight_update_reason reason) +{ + char *envp[2]; + + switch (reason) { + case BACKLIGHT_UPDATE_SYSFS: + envp[0] = "SOURCE=sysfs"; + break; + case BACKLIGHT_UPDATE_HOTKEY: + envp[0] = "SOURCE=hotkey"; + break; + default: + envp[0] = "SOURCE=unknown"; + break; + } + envp[1] = NULL; + kobject_uevent_env(&bd->dev.kobj, KOBJ_CHANGE, envp); + sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness"); +} + static ssize_t backlight_show_power(struct device *dev, struct device_attribute *attr,char *buf) { @@ -142,6 +163,8 @@ static ssize_t backlight_store_brightness(struct device *dev, } mutex_unlock(&bd->ops_lock); + backlight_generate_event(bd, BACKLIGHT_UPDATE_SYSFS); + return rc; } @@ -214,6 +237,25 @@ static struct device_attribute bl_device_attributes[] = { }; /** + * backlight_force_update - tell the backlight subsystem that hardware state + * has changed + * @bd: the backlight device to update + * + * Updates the internal state of the backlight in response to a hardware event, + * and generate a uevent to notify userspace + */ +void backlight_force_update(struct backlight_device *bd, + enum backlight_update_reason reason) +{ + mutex_lock(&bd->ops_lock); + if (bd->ops && bd->ops->get_brightness) + bd->props.brightness = bd->ops->get_brightness(bd); + mutex_unlock(&bd->ops_lock); + backlight_generate_event(bd, reason); +} +EXPORT_SYMBOL(backlight_force_update); + +/** * backlight_device_register - create and register a new object of * backlight_device class. * @name: the name of the new object(must be the same as the name of the diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index f8a4bb20f41a..2211a852af9c 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -639,3 +639,4 @@ module_exit(corgi_lcd_exit); MODULE_DESCRIPTION("LCD and backlight driver for SHARP C7x0/Cxx00"); MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:corgi-lcd"); diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 93bb4340cc64..701a1081e199 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c @@ -154,34 +154,38 @@ static int da903x_backlight_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int da903x_backlight_suspend(struct platform_device *pdev, - pm_message_t state) +static int da903x_backlight_suspend(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct backlight_device *bl = platform_get_drvdata(pdev); return da903x_backlight_set(bl, 0); } -static int da903x_backlight_resume(struct platform_device *pdev) +static int da903x_backlight_resume(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct backlight_device *bl = platform_get_drvdata(pdev); backlight_update_status(bl); return 0; } -#else -#define da903x_backlight_suspend NULL -#define da903x_backlight_resume NULL + +static struct dev_pm_ops da903x_backlight_pm_ops = { + .suspend = da903x_backlight_suspend, + .resume = da903x_backlight_resume, +}; #endif static struct platform_driver da903x_backlight_driver = { .driver = { .name = "da903x-backlight", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &da903x_backlight_pm_ops, +#endif }, .probe = da903x_backlight_probe, .remove = da903x_backlight_remove, - .suspend = da903x_backlight_suspend, - .resume = da903x_backlight_resume, }; static int __init da903x_backlight_init(void) diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index 5be55a20d8c7..7fb4eefff80d 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -103,7 +103,7 @@ static struct backlight_ops hp680bl_ops = { .update_status = hp680bl_set_intensity, }; -static int __init hp680bl_probe(struct platform_device *pdev) +static int __devinit hp680bl_probe(struct platform_device *pdev) { struct backlight_device *bd; diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c new file mode 100644 index 000000000000..447b542a20ca --- /dev/null +++ b/drivers/video/backlight/lms283gf05.c @@ -0,0 +1,242 @@ +/* + * lms283gf05.c -- support for Samsung LMS283GF05 LCD + * + * Copyright (c) 2009 Marek Vasut <marek.vasut@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/lcd.h> + +#include <linux/spi/spi.h> +#include <linux/spi/lms283gf05.h> + +struct lms283gf05_state { + struct spi_device *spi; + struct lcd_device *ld; +}; + +struct lms283gf05_seq { + unsigned char reg; + unsigned short value; + unsigned char delay; +}; + +/* Magic sequences supplied by manufacturer, for details refer to datasheet */ +static struct lms283gf05_seq disp_initseq[] = { + /* REG, VALUE, DELAY */ + { 0x07, 0x0000, 0 }, + { 0x13, 0x0000, 10 }, + + { 0x11, 0x3004, 0 }, + { 0x14, 0x200F, 0 }, + { 0x10, 0x1a20, 0 }, + { 0x13, 0x0040, 50 }, + + { 0x13, 0x0060, 0 }, + { 0x13, 0x0070, 200 }, + + { 0x01, 0x0127, 0 }, + { 0x02, 0x0700, 0 }, + { 0x03, 0x1030, 0 }, + { 0x08, 0x0208, 0 }, + { 0x0B, 0x0620, 0 }, + { 0x0C, 0x0110, 0 }, + { 0x30, 0x0120, 0 }, + { 0x31, 0x0127, 0 }, + { 0x32, 0x0000, 0 }, + { 0x33, 0x0503, 0 }, + { 0x34, 0x0727, 0 }, + { 0x35, 0x0124, 0 }, + { 0x36, 0x0706, 0 }, + { 0x37, 0x0701, 0 }, + { 0x38, 0x0F00, 0 }, + { 0x39, 0x0F00, 0 }, + { 0x40, 0x0000, 0 }, + { 0x41, 0x0000, 0 }, + { 0x42, 0x013f, 0 }, + { 0x43, 0x0000, 0 }, + { 0x44, 0x013f, 0 }, + { 0x45, 0x0000, 0 }, + { 0x46, 0xef00, 0 }, + { 0x47, 0x013f, 0 }, + { 0x48, 0x0000, 0 }, + { 0x07, 0x0015, 30 }, + + { 0x07, 0x0017, 0 }, + + { 0x20, 0x0000, 0 }, + { 0x21, 0x0000, 0 }, + { 0x22, 0x0000, 0 } +}; + +static struct lms283gf05_seq disp_pdwnseq[] = { + { 0x07, 0x0016, 30 }, + + { 0x07, 0x0004, 0 }, + { 0x10, 0x0220, 20 }, + + { 0x13, 0x0060, 50 }, + + { 0x13, 0x0040, 50 }, + + { 0x13, 0x0000, 0 }, + { 0x10, 0x0000, 0 } +}; + + +static void lms283gf05_reset(unsigned long gpio, bool inverted) +{ + gpio_set_value(gpio, !inverted); + mdelay(100); + gpio_set_value(gpio, inverted); + mdelay(20); + gpio_set_value(gpio, !inverted); + mdelay(20); +} + +static void lms283gf05_toggle(struct spi_device *spi, + struct lms283gf05_seq *seq, int sz) +{ + char buf[3]; + int i; + + for (i = 0; i < sz; i++) { + buf[0] = 0x74; + buf[1] = 0x00; + buf[2] = seq[i].reg; + spi_write(spi, buf, 3); + + buf[0] = 0x76; + buf[1] = seq[i].value >> 8; + buf[2] = seq[i].value & 0xff; + spi_write(spi, buf, 3); + + mdelay(seq[i].delay); + } +} + +static int lms283gf05_power_set(struct lcd_device *ld, int power) +{ + struct lms283gf05_state *st = lcd_get_data(ld); + struct spi_device *spi = st->spi; + struct lms283gf05_pdata *pdata = spi->dev.platform_data; + + if (power) { + if (pdata) + lms283gf05_reset(pdata->reset_gpio, + pdata->reset_inverted); + lms283gf05_toggle(spi, disp_initseq, ARRAY_SIZE(disp_initseq)); + } else { + lms283gf05_toggle(spi, disp_pdwnseq, ARRAY_SIZE(disp_pdwnseq)); + if (pdata) + gpio_set_value(pdata->reset_gpio, + pdata->reset_inverted); + } + + return 0; +} + +static struct lcd_ops lms_ops = { + .set_power = lms283gf05_power_set, + .get_power = NULL, +}; + +static int __devinit lms283gf05_probe(struct spi_device *spi) +{ + struct lms283gf05_state *st; + struct lms283gf05_pdata *pdata = spi->dev.platform_data; + struct lcd_device *ld; + int ret = 0; + + if (pdata != NULL) { + ret = gpio_request(pdata->reset_gpio, "LMS285GF05 RESET"); + if (ret) + return ret; + + ret = gpio_direction_output(pdata->reset_gpio, + !pdata->reset_inverted); + if (ret) + goto err; + } + + st = kzalloc(sizeof(struct lms283gf05_state), GFP_KERNEL); + if (st == NULL) { + dev_err(&spi->dev, "No memory for device state\n"); + ret = -ENOMEM; + goto err; + } + + ld = lcd_device_register("lms283gf05", &spi->dev, st, &lms_ops); + if (IS_ERR(ld)) { + ret = PTR_ERR(ld); + goto err2; + } + + st->spi = spi; + st->ld = ld; + + dev_set_drvdata(&spi->dev, st); + + /* kick in the LCD */ + if (pdata) + lms283gf05_reset(pdata->reset_gpio, pdata->reset_inverted); + lms283gf05_toggle(spi, disp_initseq, ARRAY_SIZE(disp_initseq)); + + return 0; + +err2: + kfree(st); +err: + if (pdata != NULL) + gpio_free(pdata->reset_gpio); + + return ret; +} + +static int __devexit lms283gf05_remove(struct spi_device *spi) +{ + struct lms283gf05_state *st = dev_get_drvdata(&spi->dev); + struct lms283gf05_pdata *pdata = st->spi->dev.platform_data; + + lcd_device_unregister(st->ld); + + if (pdata != NULL) + gpio_free(pdata->reset_gpio); + + kfree(st); + + return 0; +} + +static struct spi_driver lms283gf05_driver = { + .driver = { + .name = "lms283gf05", + .owner = THIS_MODULE, + }, + .probe = lms283gf05_probe, + .remove = __devexit_p(lms283gf05_remove), +}; + +static __init int lms283gf05_init(void) +{ + return spi_register_driver(&lms283gf05_driver); +} + +static __exit void lms283gf05_exit(void) +{ + spi_unregister_driver(&lms283gf05_driver); +} + +module_init(lms283gf05_init); +module_exit(lms283gf05_exit); + +MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); +MODULE_DESCRIPTION("LCD283GF05 LCD"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c index 2eb206bf73e6..4631ca8fa4a4 100644 --- a/drivers/video/backlight/ltv350qv.c +++ b/drivers/video/backlight/ltv350qv.c @@ -328,3 +328,4 @@ module_exit(ltv350qv_exit); MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:ltv350qv"); diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c index 3bb4c0a50c62..9edb8d7c295f 100644 --- a/drivers/video/backlight/mbp_nvidia_bl.c +++ b/drivers/video/backlight/mbp_nvidia_bl.c @@ -166,6 +166,15 @@ static const struct dmi_system_id __initdata mbp_device_table[] = { }, { .callback = mbp_dmi_match, + .ident = "MacBookAir 1,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir1,1"), + }, + .driver_data = (void *)&intel_chipset_data, + }, + { + .callback = mbp_dmi_match, .ident = "MacBook 5,1", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), @@ -175,6 +184,15 @@ static const struct dmi_system_id __initdata mbp_device_table[] = { }, { .callback = mbp_dmi_match, + .ident = "MacBook 5,2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,2"), + }, + .driver_data = (void *)&nvidia_chipset_data, + }, + { + .callback = mbp_dmi_match, .ident = "MacBookAir 2,1", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), @@ -191,6 +209,24 @@ static const struct dmi_system_id __initdata mbp_device_table[] = { }, .driver_data = (void *)&nvidia_chipset_data, }, + { + .callback = mbp_dmi_match, + .ident = "MacBookPro 5,2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,2"), + }, + .driver_data = (void *)&nvidia_chipset_data, + }, + { + .callback = mbp_dmi_match, + .ident = "MacBookPro 5,5", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,5"), + }, + .driver_data = (void *)&nvidia_chipset_data, + }, { } }; diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 51422fc4f606..bbfb502add67 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c @@ -472,3 +472,4 @@ module_exit(tdo24m_exit); MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); MODULE_DESCRIPTION("Driver for Toppoly TDO24M LCD Panel"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:tdo24m"); diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index b7fbc75a62fc..50ec17dfc517 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c @@ -300,4 +300,4 @@ module_exit(tosa_lcd_exit); MODULE_AUTHOR("Dmitry Baryshkov"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA"); - +MODULE_ALIAS("spi:tosa-lcd"); diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c index 8e653b8a6f17..b49063c831e7 100644 --- a/drivers/video/backlight/vgg2432a4.c +++ b/drivers/video/backlight/vgg2432a4.c @@ -280,5 +280,4 @@ module_exit(vgg2432a4_exit); MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); MODULE_DESCRIPTION("VGG2432A4 LCD Driver"); MODULE_LICENSE("GPL v2"); - - +MODULE_ALIAS("spi:VGG2432A4"); diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c new file mode 100644 index 000000000000..467bdb7efb23 --- /dev/null +++ b/drivers/video/backlight/wm831x_bl.c @@ -0,0 +1,250 @@ +/* + * Backlight driver for Wolfson Microelectronics WM831x PMICs + * + * Copyright 2009 Wolfson Microelectonics plc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/fb.h> +#include <linux/backlight.h> + +#include <linux/mfd/wm831x/core.h> +#include <linux/mfd/wm831x/pdata.h> +#include <linux/mfd/wm831x/regulator.h> + +struct wm831x_backlight_data { + struct wm831x *wm831x; + int isink_reg; + int current_brightness; +}; + +static int wm831x_backlight_set(struct backlight_device *bl, int brightness) +{ + struct wm831x_backlight_data *data = bl_get_data(bl); + struct wm831x *wm831x = data->wm831x; + int power_up = !data->current_brightness && brightness; + int power_down = data->current_brightness && !brightness; + int ret; + + if (power_up) { + /* Enable the ISINK */ + ret = wm831x_set_bits(wm831x, data->isink_reg, + WM831X_CS1_ENA, WM831X_CS1_ENA); + if (ret < 0) + goto err; + + /* Enable the DC-DC */ + ret = wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, + WM831X_DC4_ENA, WM831X_DC4_ENA); + if (ret < 0) + goto err; + } + + if (power_down) { + /* DCDC first */ + ret = wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, + WM831X_DC4_ENA, 0); + if (ret < 0) + goto err; + + /* ISINK */ + ret = wm831x_set_bits(wm831x, data->isink_reg, + WM831X_CS1_DRIVE | WM831X_CS1_ENA, 0); + if (ret < 0) + goto err; + } + + /* Set the new brightness */ + ret = wm831x_set_bits(wm831x, data->isink_reg, + WM831X_CS1_ISEL_MASK, brightness); + if (ret < 0) + goto err; + + if (power_up) { + /* Drive current through the ISINK */ + ret = wm831x_set_bits(wm831x, data->isink_reg, + WM831X_CS1_DRIVE, WM831X_CS1_DRIVE); + if (ret < 0) + return ret; + } + + data->current_brightness = brightness; + + return 0; + +err: + /* If we were in the middle of a power transition always shut down + * for safety. + */ + if (power_up || power_down) { + wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, WM831X_DC4_ENA, 0); + wm831x_set_bits(wm831x, data->isink_reg, WM831X_CS1_ENA, 0); + } + + return ret; +} + +static int wm831x_backlight_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.state & BL_CORE_SUSPENDED) + brightness = 0; + + return wm831x_backlight_set(bl, brightness); +} + +static int wm831x_backlight_get_brightness(struct backlight_device *bl) +{ + struct wm831x_backlight_data *data = bl_get_data(bl); + return data->current_brightness; +} + +static struct backlight_ops wm831x_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = wm831x_backlight_update_status, + .get_brightness = wm831x_backlight_get_brightness, +}; + +static int wm831x_backlight_probe(struct platform_device *pdev) +{ + struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); + struct wm831x_pdata *wm831x_pdata; + struct wm831x_backlight_pdata *pdata; + struct wm831x_backlight_data *data; + struct backlight_device *bl; + int ret, i, max_isel, isink_reg, dcdc_cfg; + + /* We need platform data */ + if (pdev->dev.parent->platform_data) { + wm831x_pdata = pdev->dev.parent->platform_data; + pdata = wm831x_pdata->backlight; + } else { + pdata = NULL; + } + + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied\n"); + return -EINVAL; + } + + /* Figure out the maximum current we can use */ + for (i = 0; i < WM831X_ISINK_MAX_ISEL; i++) { + if (wm831x_isinkv_values[i] > pdata->max_uA) + break; + } + + if (i == 0) { + dev_err(&pdev->dev, "Invalid max_uA: %duA\n", pdata->max_uA); + return -EINVAL; + } + max_isel = i - 1; + + if (pdata->max_uA != wm831x_isinkv_values[max_isel]) + dev_warn(&pdev->dev, + "Maximum current is %duA not %duA as requested\n", + wm831x_isinkv_values[max_isel], pdata->max_uA); + + switch (pdata->isink) { + case 1: + isink_reg = WM831X_CURRENT_SINK_1; + dcdc_cfg = 0; + break; + case 2: + isink_reg = WM831X_CURRENT_SINK_2; + dcdc_cfg = WM831X_DC4_FBSRC; + break; + default: + dev_err(&pdev->dev, "Invalid ISINK %d\n", pdata->isink); + return -EINVAL; + } + + /* Configure the ISINK to use for feedback */ + ret = wm831x_reg_unlock(wm831x); + if (ret < 0) + return ret; + + ret = wm831x_set_bits(wm831x, WM831X_DC4_CONTROL, WM831X_DC4_FBSRC, + dcdc_cfg); + + wm831x_reg_lock(wm831x); + if (ret < 0) + return ret; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->wm831x = wm831x; + data->current_brightness = 0; + data->isink_reg = isink_reg; + + bl = backlight_device_register("wm831x", &pdev->dev, + data, &wm831x_backlight_ops); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + kfree(data); + return PTR_ERR(bl); + } + + bl->props.max_brightness = max_isel; + bl->props.brightness = max_isel; + + platform_set_drvdata(pdev, bl); + + /* Disable the DCDC if it was started so we can bootstrap */ + wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, WM831X_DC4_ENA, 0); + + + backlight_update_status(bl); + + return 0; +} + +static int wm831x_backlight_remove(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct wm831x_backlight_data *data = bl_get_data(bl); + + backlight_device_unregister(bl); + kfree(data); + return 0; +} + +static struct platform_driver wm831x_backlight_driver = { + .driver = { + .name = "wm831x-backlight", + .owner = THIS_MODULE, + }, + .probe = wm831x_backlight_probe, + .remove = wm831x_backlight_remove, +}; + +static int __init wm831x_backlight_init(void) +{ + return platform_driver_register(&wm831x_backlight_driver); +} +module_init(wm831x_backlight_init); + +static void __exit wm831x_backlight_exit(void) +{ + platform_driver_unregister(&wm831x_backlight_driver); +} +module_exit(wm831x_backlight_exit); + +MODULE_DESCRIPTION("Backlight Driver for WM831x PMICs"); +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:wm831x-backlight"); diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c index df03f3776dcc..79e5f40e6486 100644 --- a/drivers/video/cfbcopyarea.c +++ b/drivers/video/cfbcopyarea.c @@ -114,7 +114,7 @@ bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, d0 >>= right; } else if (src_idx+n <= bits) { // Single source word - d0 <<= left;; + d0 <<= left; } else { // 2 source words d1 = FB_READL(src + 1); diff --git a/drivers/video/console/.gitignore b/drivers/video/console/.gitignore deleted file mode 100644 index 0c258b45439c..000000000000 --- a/drivers/video/console/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# conmakehash generated file -promcon_tbl.c diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 2f50a80b413e..fc7d9bbb548c 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -67,16 +67,9 @@ config SGI_NEWPORT_CONSOLE # bool 'IODC console' CONFIG_IODC_CONSOLE -config PROM_CONSOLE - bool "PROM console" - depends on SPARC - help - Say Y to build a console driver for Sun machines that uses the - terminal emulation built into their console PROMS. - config DUMMY_CONSOLE bool - depends on PROM_CONSOLE!=y || VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y + depends on VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y default y config DUMMY_CONSOLE_COLUMNS diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index ac46cc3f6a2a..a862e9173ebe 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -22,7 +22,6 @@ font-objs += $(font-objs-y) obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o -obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o @@ -40,14 +39,3 @@ obj-$(CONFIG_FB_STI) += sticore.o font.o ifeq ($(CONFIG_USB_SISUSBVGA_CON),y) obj-$(CONFIG_USB_SISUSBVGA) += font.o endif - -# Targets that kbuild needs to know about -targets := promcon_tbl.c - -quiet_cmd_conmakehash = CNMKHSH $@ - cmd_conmakehash = scripts/conmakehash $< | \ - sed -e '/\#include <[^>]*>/p' -e 's/types/init/' \ - -e 's/dfont\(_uni.*\]\)/promfont\1 /' > $@ - -$(obj)/promcon_tbl.c: $(src)/prom.uni - $(call cmd,conmakehash) diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 69864b1b3f9e..6b7c8fbc5495 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -25,7 +25,7 @@ static inline void update_attr(u8 *dst, u8 *src, int attribute, struct vc_data *vc) { int i, offset = (vc->vc_font.height < 10) ? 1 : 2; - int width = (vc->vc_font.width + 7) >> 3; + int width = DIV_ROUND_UP(vc->vc_font.width, 8); unsigned int cellsize = vc->vc_font.height * width; u8 c; @@ -144,7 +144,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, int fg, int bg) { struct fb_image image; - u32 width = (vc->vc_font.width + 7)/8; + u32 width = DIV_ROUND_UP(vc->vc_font.width, 8); u32 cellsize = width * vc->vc_font.height; u32 maxcnt = info->pixmap.size/cellsize; u32 scan_align = info->pixmap.scan_align - 1; @@ -173,7 +173,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, cnt = count; image.width = vc->vc_font.width * cnt; - pitch = ((image.width + 7) >> 3) + scan_align; + pitch = DIV_ROUND_UP(image.width, 8) + scan_align; pitch &= ~scan_align; size = pitch * image.height + buf_align; size &= ~buf_align; @@ -239,7 +239,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fb_cursor cursor; struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; - int w = (vc->vc_font.width + 7) >> 3, c; + int w = DIV_ROUND_UP(vc->vc_font.width, 8), c; int y = real_y(ops->p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1; diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 3a44695b9c09..5a686cea23f4 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -114,6 +114,7 @@ static int last_fb_vc = MAX_NR_CONSOLES - 1; static int fbcon_is_default = 1; static int fbcon_has_exited; static int primary_device = -1; +static int fbcon_has_console_bind; #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY static int map_override; @@ -544,6 +545,8 @@ static int fbcon_takeover(int show_logo) con2fb_map[i] = -1; } info_idx = -1; + } else { + fbcon_has_console_bind = 1; } return err; @@ -725,7 +728,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, int oldidx, int found) { struct fbcon_ops *ops = oldinfo->fbcon_par; - int err = 0; + int err = 0, ret; if (oldinfo->fbops->fb_release && oldinfo->fbops->fb_release(oldinfo, 0)) { @@ -752,8 +755,14 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, newinfo in an undefined state. Thus, a call to fb_set_par() may be needed for the newinfo. */ - if (newinfo->fbops->fb_set_par) - newinfo->fbops->fb_set_par(newinfo); + if (newinfo->fbops->fb_set_par) { + ret = newinfo->fbops->fb_set_par(newinfo); + + if (ret) + printk(KERN_ERR "con2fb_release_oldinfo: " + "detected unhandled fb_set_par error, " + "error code %d\n", ret); + } } return err; @@ -763,11 +772,18 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, int unit, int show_logo) { struct fbcon_ops *ops = info->fbcon_par; + int ret; ops->currcon = fg_console; - if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT)) - info->fbops->fb_set_par(info); + if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT)) { + ret = info->fbops->fb_set_par(info); + + if (ret) + printk(KERN_ERR "con2fb_init_display: detected " + "unhandled fb_set_par error, " + "error code %d\n", ret); + } ops->flags |= FBCON_FLAGS_INIT; ops->graphics = 0; @@ -1006,7 +1022,7 @@ static void fbcon_init(struct vc_data *vc, int init) struct vc_data *svc = *default_mode; struct display *t, *p = &fb_display[vc->vc_num]; int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256; - int cap; + int cap, ret; if (info_idx == -1 || info == NULL) return; @@ -1092,8 +1108,15 @@ static void fbcon_init(struct vc_data *vc, int init) */ if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) { if (info->fbops->fb_set_par && - !(ops->flags & FBCON_FLAGS_INIT)) - info->fbops->fb_set_par(info); + !(ops->flags & FBCON_FLAGS_INIT)) { + ret = info->fbops->fb_set_par(info); + + if (ret) + printk(KERN_ERR "fbcon_init: detected " + "unhandled fb_set_par error, " + "error code %d\n", ret); + } + ops->flags |= FBCON_FLAGS_INIT; } @@ -2119,7 +2142,7 @@ static int fbcon_switch(struct vc_data *vc) struct fbcon_ops *ops; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var; - int i, prev_console, charcnt = 256; + int i, ret, prev_console, charcnt = 256; info = registered_fb[con2fb_map[vc->vc_num]]; ops = info->fbcon_par; @@ -2174,8 +2197,14 @@ static int fbcon_switch(struct vc_data *vc) if (old_info != NULL && (old_info != info || info->flags & FBINFO_MISC_ALWAYS_SETPAR)) { - if (info->fbops->fb_set_par) - info->fbops->fb_set_par(info); + if (info->fbops->fb_set_par) { + ret = info->fbops->fb_set_par(info); + + if (ret) + printk(KERN_ERR "fbcon_switch: detected " + "unhandled fb_set_par error, " + "error code %d\n", ret); + } if (old_info != info) fbcon_del_cursor_timer(old_info); @@ -2923,6 +2952,10 @@ static int fbcon_unbind(void) ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); + + if (!ret) + fbcon_has_console_bind = 0; + return ret; } #else @@ -2936,6 +2969,9 @@ static int fbcon_fb_unbind(int idx) { int i, new_idx = -1, ret = 0; + if (!fbcon_has_console_bind) + return 0; + for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map[i] != idx && con2fb_map[i] != -1) { diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index d31b203bf654..3772433c49d1 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -216,7 +216,7 @@ static void newport_get_screensize(void) } newport_xsize = newport_ysize = 0; - for (i = 0; linetable[i + 1] && (i < sizeof(linetable)); i += 2) { + for (i = 0; i < ARRAY_SIZE(linetable) - 1 && linetable[i + 1]; i += 2) { cols = 0; newport_vc2_set(npregs, VC2_IREG_RADDR, linetable[i]); npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | diff --git a/drivers/video/console/prom.uni b/drivers/video/console/prom.uni deleted file mode 100644 index 58f9c04ed9d3..000000000000 --- a/drivers/video/console/prom.uni +++ /dev/null @@ -1,11 +0,0 @@ -# -# Unicode mapping table for font in Sun PROM -# -# -0x20-0x7e idem -0xa0-0xff idem -# -0x7c U+2502 -0x2d U+2500 -0x2b U+250c U+2510 U+2514 U+2518 U+251c U+2524 U+252c U+2534 U+253c -0xa4 U+fffd diff --git a/drivers/video/console/promcon.c b/drivers/video/console/promcon.c deleted file mode 100644 index ae02e4eb18e7..000000000000 --- a/drivers/video/console/promcon.c +++ /dev/null @@ -1,598 +0,0 @@ -/* $Id: promcon.c,v 1.17 2000/07/26 23:02:52 davem Exp $ - * Console driver utilizing PROM sun terminal emulation - * - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/console.h> -#include <linux/vt_kern.h> -#include <linux/selection.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/kd.h> - -#include <asm/oplib.h> -#include <asm/uaccess.h> - -static short pw = 80 - 1, ph = 34 - 1; -static short px, py; -static unsigned long promcon_uni_pagedir[2]; - -extern u8 promfont_unicount[]; -extern u16 promfont_unitable[]; - -#define PROMCON_COLOR 0 - -#if PROMCON_COLOR -#define inverted(s) ((((s) & 0x7700) == 0x0700) ? 0 : 1) -#else -#define inverted(s) (((s) & 0x0800) ? 1 : 0) -#endif - -static __inline__ void -promcon_puts(char *buf, int cnt) -{ - prom_printf("%*.*s", cnt, cnt, buf); -} - -static int -promcon_start(struct vc_data *conp, char *b) -{ - unsigned short *s = (unsigned short *) - (conp->vc_origin + py * conp->vc_size_row + (px << 1)); - u16 cs; - - cs = scr_readw(s); - if (px == pw) { - unsigned short *t = s - 1; - u16 ct = scr_readw(t); - - if (inverted(cs) && inverted(ct)) - return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs, - ct); - else if (inverted(cs)) - return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs, - ct); - else if (inverted(ct)) - return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs, - ct); - else - return sprintf(b, "\b%c\b\033[@%c", cs, ct); - } - - if (inverted(cs)) - return sprintf(b, "\033[7m%c\033[m\b", cs); - else - return sprintf(b, "%c\b", cs); -} - -static int -promcon_end(struct vc_data *conp, char *b) -{ - unsigned short *s = (unsigned short *) - (conp->vc_origin + py * conp->vc_size_row + (px << 1)); - char *p = b; - u16 cs; - - b += sprintf(b, "\033[%d;%dH", py + 1, px + 1); - - cs = scr_readw(s); - if (px == pw) { - unsigned short *t = s - 1; - u16 ct = scr_readw(t); - - if (inverted(cs) && inverted(ct)) - b += sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs, ct); - else if (inverted(cs)) - b += sprintf(b, "\b%c\b\033[@%c", cs, ct); - else if (inverted(ct)) - b += sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs, ct); - else - b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs, ct); - return b - p; - } - - if (inverted(cs)) - b += sprintf(b, "%c\b", cs); - else - b += sprintf(b, "\033[7m%c\033[m\b", cs); - return b - p; -} - -const char *promcon_startup(void) -{ - const char *display_desc = "PROM"; - int node; - char buf[40]; - - node = prom_getchild(prom_root_node); - node = prom_searchsiblings(node, "options"); - if (prom_getproperty(node, "screen-#columns", buf, 40) != -1) { - pw = simple_strtoul(buf, NULL, 0); - if (pw < 10 || pw > 256) - pw = 80; - pw--; - } - if (prom_getproperty(node, "screen-#rows", buf, 40) != -1) { - ph = simple_strtoul(buf, NULL, 0); - if (ph < 10 || ph > 256) - ph = 34; - ph--; - } - promcon_puts("\033[H\033[J", 6); - return display_desc; -} - -static void -promcon_init_unimap(struct vc_data *conp) -{ - mm_segment_t old_fs = get_fs(); - struct unipair *p, *p1; - u16 *q; - int i, j, k; - - p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL); - if (!p) return; - - q = promfont_unitable; - p1 = p; - k = 0; - for (i = 0; i < 256; i++) - for (j = promfont_unicount[i]; j; j--) { - p1->unicode = *q++; - p1->fontpos = i; - p1++; - k++; - } - set_fs(KERNEL_DS); - con_clear_unimap(conp, NULL); - con_set_unimap(conp, k, p); - con_protect_unimap(conp, 1); - set_fs(old_fs); - kfree(p); -} - -static void -promcon_init(struct vc_data *conp, int init) -{ - unsigned long p; - - conp->vc_can_do_color = PROMCON_COLOR; - if (init) { - conp->vc_cols = pw + 1; - conp->vc_rows = ph + 1; - } - p = *conp->vc_uni_pagedir_loc; - if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir || - !--conp->vc_uni_pagedir_loc[1]) - con_free_unimap(conp); - conp->vc_uni_pagedir_loc = promcon_uni_pagedir; - promcon_uni_pagedir[1]++; - if (!promcon_uni_pagedir[0] && p) { - promcon_init_unimap(conp); - } - if (!init) { - if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1) - vc_resize(conp, pw + 1, ph + 1); - } -} - -static void -promcon_deinit(struct vc_data *conp) -{ - /* When closing the last console, reset video origin */ - if (!--promcon_uni_pagedir[1]) - con_free_unimap(conp); - conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir; - con_set_default_unimap(conp); -} - -static int -promcon_switch(struct vc_data *conp) -{ - return 1; -} - -static unsigned short * -promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp) -{ - int cnt = pw + 1; - int attr = -1; - unsigned char *b = *bp; - - while (cnt--) { - u16 c = scr_readw(s); - if (attr != inverted(c)) { - attr = inverted(c); - if (attr) { - strcpy (b, "\033[7m"); - b += 4; - } else { - strcpy (b, "\033[m"); - b += 3; - } - } - *b++ = c; - s++; - if (b - buf >= 224) { - promcon_puts(buf, b - buf); - b = buf; - } - } - *bp = b; - return s; -} - -static void -promcon_putcs(struct vc_data *conp, const unsigned short *s, - int count, int y, int x) -{ - unsigned char buf[256], *b = buf; - unsigned short attr = scr_readw(s); - unsigned char save; - int i, last = 0; - - if (console_blanked) - return; - - if (count <= 0) - return; - - b += promcon_start(conp, b); - - if (x + count >= pw + 1) { - if (count == 1) { - x -= 1; - save = scr_readw((unsigned short *)(conp->vc_origin - + y * conp->vc_size_row - + (x << 1))); - - if (px != x || py != y) { - b += sprintf(b, "\033[%d;%dH", y + 1, x + 1); - px = x; - py = y; - } - - if (inverted(attr)) - b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++)); - else - b += sprintf(b, "%c", scr_readw(s++)); - - strcpy(b, "\b\033[@"); - b += 4; - - if (inverted(save)) - b += sprintf(b, "\033[7m%c\033[m", save); - else - b += sprintf(b, "%c", save); - - px++; - - b += promcon_end(conp, b); - promcon_puts(buf, b - buf); - return; - } else { - last = 1; - count = pw - x - 1; - } - } - - if (inverted(attr)) { - strcpy(b, "\033[7m"); - b += 4; - } - - if (px != x || py != y) { - b += sprintf(b, "\033[%d;%dH", y + 1, x + 1); - px = x; - py = y; - } - - for (i = 0; i < count; i++) { - if (b - buf >= 224) { - promcon_puts(buf, b - buf); - b = buf; - } - *b++ = scr_readw(s++); - } - - px += count; - - if (last) { - save = scr_readw(s++); - b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save); - px++; - } - - if (inverted(attr)) { - strcpy(b, "\033[m"); - b += 3; - } - - b += promcon_end(conp, b); - promcon_puts(buf, b - buf); -} - -static void -promcon_putc(struct vc_data *conp, int c, int y, int x) -{ - unsigned short s; - - if (console_blanked) - return; - - scr_writew(c, &s); - promcon_putcs(conp, &s, 1, y, x); -} - -static void -promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width) -{ - unsigned char buf[256], *b = buf; - int i, j; - - if (console_blanked) - return; - - b += promcon_start(conp, b); - - if (!sx && width == pw + 1) { - - if (!sy && height == ph + 1) { - strcpy(b, "\033[H\033[J"); - b += 6; - b += promcon_end(conp, b); - promcon_puts(buf, b - buf); - return; - } else if (sy + height == ph + 1) { - b += sprintf(b, "\033[%dH\033[J", sy + 1); - b += promcon_end(conp, b); - promcon_puts(buf, b - buf); - return; - } - - b += sprintf(b, "\033[%dH", sy + 1); - for (i = 1; i < height; i++) { - strcpy(b, "\033[K\n"); - b += 4; - } - - strcpy(b, "\033[K"); - b += 3; - - b += promcon_end(conp, b); - promcon_puts(buf, b - buf); - return; - - } else if (sx + width == pw + 1) { - - b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1); - for (i = 1; i < height; i++) { - strcpy(b, "\033[K\n"); - b += 4; - } - - strcpy(b, "\033[K"); - b += 3; - - b += promcon_end(conp, b); - promcon_puts(buf, b - buf); - return; - } - - for (i = sy + 1; i <= sy + height; i++) { - b += sprintf(b, "\033[%d;%dH", i, sx + 1); - for (j = 0; j < width; j++) - *b++ = ' '; - if (b - buf + width >= 224) { - promcon_puts(buf, b - buf); - b = buf; - } - } - - b += promcon_end(conp, b); - promcon_puts(buf, b - buf); -} - -static void -promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, - int height, int width) -{ - char buf[256], *b = buf; - - if (console_blanked) - return; - - b += promcon_start(conp, b); - if (sy == dy && height == 1) { - if (dx > sx && dx + width == conp->vc_cols) - b += sprintf(b, "\033[%d;%dH\033[%d@\033[%d;%dH", - sy + 1, sx + 1, dx - sx, py + 1, px + 1); - else if (dx < sx && sx + width == conp->vc_cols) - b += sprintf(b, "\033[%d;%dH\033[%dP\033[%d;%dH", - dy + 1, dx + 1, sx - dx, py + 1, px + 1); - - b += promcon_end(conp, b); - promcon_puts(buf, b - buf); - return; - } - - /* - * FIXME: What to do here??? - * Current console.c should not call it like that ever. - */ - prom_printf("\033[7mFIXME: bmove not handled\033[m\n"); -} - -static void -promcon_cursor(struct vc_data *conp, int mode) -{ - char buf[32], *b = buf; - - switch (mode) { - case CM_ERASE: - break; - - case CM_MOVE: - case CM_DRAW: - b += promcon_start(conp, b); - if (px != conp->vc_x || py != conp->vc_y) { - px = conp->vc_x; - py = conp->vc_y; - b += sprintf(b, "\033[%d;%dH", py + 1, px + 1); - } - promcon_puts(buf, b - buf); - break; - } -} - -static int -promcon_blank(struct vc_data *conp, int blank, int mode_switch) -{ - if (blank) { - promcon_puts("\033[H\033[J\033[7m \033[m\b", 15); - return 0; - } else { - /* Let console.c redraw */ - return 1; - } -} - -static int -promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count) -{ - unsigned char buf[256], *p = buf; - unsigned short *s; - int i; - - if (console_blanked) - return 0; - - p += promcon_start(conp, p); - - switch (dir) { - case SM_UP: - if (b == ph + 1) { - p += sprintf(p, "\033[%dH\033[%dM", t + 1, count); - px = 0; - py = t; - p += promcon_end(conp, p); - promcon_puts(buf, p - buf); - break; - } - - s = (unsigned short *)(conp->vc_origin - + (t + count) * conp->vc_size_row); - - p += sprintf(p, "\033[%dH", t + 1); - - for (i = t; i < b - count; i++) - s = promcon_repaint_line(s, buf, &p); - - for (; i < b - 1; i++) { - strcpy(p, "\033[K\n"); - p += 4; - if (p - buf >= 224) { - promcon_puts(buf, p - buf); - p = buf; - } - } - - strcpy(p, "\033[K"); - p += 3; - - p += promcon_end(conp, p); - promcon_puts(buf, p - buf); - break; - - case SM_DOWN: - if (b == ph + 1) { - p += sprintf(p, "\033[%dH\033[%dL", t + 1, count); - px = 0; - py = t; - p += promcon_end(conp, p); - promcon_puts(buf, p - buf); - break; - } - - s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row); - - p += sprintf(p, "\033[%dH", t + 1); - - for (i = t; i < t + count; i++) { - strcpy(p, "\033[K\n"); - p += 4; - if (p - buf >= 224) { - promcon_puts(buf, p - buf); - p = buf; - } - } - - for (; i < b; i++) - s = promcon_repaint_line(s, buf, &p); - - p += promcon_end(conp, p); - promcon_puts(buf, p - buf); - break; - } - - return 0; -} - -#if !(PROMCON_COLOR) -static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity, - u8 _blink, u8 _underline, u8 _reverse, u8 _italic) -{ - return (_reverse) ? 0xf : 0x7; -} -#endif - -/* - * The console 'switch' structure for the VGA based console - */ - -static int promcon_dummy(void) -{ - return 0; -} - -#define DUMMY (void *) promcon_dummy - -const struct consw prom_con = { - .owner = THIS_MODULE, - .con_startup = promcon_startup, - .con_init = promcon_init, - .con_deinit = promcon_deinit, - .con_clear = promcon_clear, - .con_putc = promcon_putc, - .con_putcs = promcon_putcs, - .con_cursor = promcon_cursor, - .con_scroll = promcon_scroll, - .con_bmove = promcon_bmove, - .con_switch = promcon_switch, - .con_blank = promcon_blank, - .con_set_palette = DUMMY, - .con_scrolldelta = DUMMY, -#if !(PROMCON_COLOR) - .con_build_attr = promcon_build_attr, -#endif -}; - -void __init prom_con_init(void) -{ -#ifdef CONFIG_DUMMY_CONSOLE - if (conswitchp == &dummy_con) - take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1); - else -#endif - if (conswitchp == &prom_con) - promcon_init_unimap(vc_cons[fg_console].d); -} diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 59d7d5ec17a4..da55ccaf4d55 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -180,7 +180,6 @@ static inline void vga_set_mem_top(struct vc_data *c) } #ifdef CONFIG_VGACON_SOFT_SCROLLBACK -#include <linux/slab.h> /* software scrollback */ static void *vgacon_scrollback; static int vgacon_scrollback_tail; @@ -590,12 +589,14 @@ static void vgacon_init(struct vc_data *c, int init) static void vgacon_deinit(struct vc_data *c) { - /* When closing the last console, reset video origin */ - if (!--vgacon_uni_pagedir[1]) { + /* When closing the active console, reset video origin */ + if (CON_IS_VISIBLE(c)) { c->vc_visible_origin = vga_vram_base; vga_set_mem_top(c); - con_free_unimap(c); } + + if (!--vgacon_uni_pagedir[1]) + con_free_unimap(c); c->vc_uni_pagedir_loc = &c->vc_uni_pagedir; con_set_default_unimap(c); } diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c new file mode 100644 index 000000000000..42e1005e2916 --- /dev/null +++ b/drivers/video/da8xx-fb.c @@ -0,0 +1,890 @@ +/* + * Copyright (C) 2008-2009 MontaVista Software Inc. + * Copyright (C) 2008-2009 Texas Instruments Inc + * + * Based on the LCD driver for TI Avalanche processors written by + * Ajay Singh and Shalom Hai. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option)any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/fb.h> +#include <linux/dma-mapping.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/uaccess.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/clk.h> +#include <video/da8xx-fb.h> + +#define DRIVER_NAME "da8xx_lcdc" + +/* LCD Status Register */ +#define LCD_END_OF_FRAME0 BIT(8) +#define LCD_FIFO_UNDERFLOW BIT(5) +#define LCD_SYNC_LOST BIT(2) + +/* LCD DMA Control Register */ +#define LCD_DMA_BURST_SIZE(x) ((x) << 4) +#define LCD_DMA_BURST_1 0x0 +#define LCD_DMA_BURST_2 0x1 +#define LCD_DMA_BURST_4 0x2 +#define LCD_DMA_BURST_8 0x3 +#define LCD_DMA_BURST_16 0x4 +#define LCD_END_OF_FRAME_INT_ENA BIT(2) +#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) + +/* LCD Control Register */ +#define LCD_CLK_DIVISOR(x) ((x) << 8) +#define LCD_RASTER_MODE 0x01 + +/* LCD Raster Control Register */ +#define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) +#define PALETTE_AND_DATA 0x00 +#define PALETTE_ONLY 0x01 + +#define LCD_MONO_8BIT_MODE BIT(9) +#define LCD_RASTER_ORDER BIT(8) +#define LCD_TFT_MODE BIT(7) +#define LCD_UNDERFLOW_INT_ENA BIT(6) +#define LCD_MONOCHROME_MODE BIT(1) +#define LCD_RASTER_ENABLE BIT(0) +#define LCD_TFT_ALT_ENABLE BIT(23) +#define LCD_STN_565_ENABLE BIT(24) + +/* LCD Raster Timing 2 Register */ +#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) +#define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8) +#define LCD_SYNC_CTRL BIT(25) +#define LCD_SYNC_EDGE BIT(24) +#define LCD_INVERT_PIXEL_CLOCK BIT(22) +#define LCD_INVERT_LINE_CLOCK BIT(21) +#define LCD_INVERT_FRAME_CLOCK BIT(20) + +/* LCD Block */ +#define LCD_CTRL_REG 0x4 +#define LCD_STAT_REG 0x8 +#define LCD_RASTER_CTRL_REG 0x28 +#define LCD_RASTER_TIMING_0_REG 0x2C +#define LCD_RASTER_TIMING_1_REG 0x30 +#define LCD_RASTER_TIMING_2_REG 0x34 +#define LCD_DMA_CTRL_REG 0x40 +#define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 +#define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 + +#define WSI_TIMEOUT 50 +#define PALETTE_SIZE 256 +#define LEFT_MARGIN 64 +#define RIGHT_MARGIN 64 +#define UPPER_MARGIN 32 +#define LOWER_MARGIN 32 + +static resource_size_t da8xx_fb_reg_base; +static struct resource *lcdc_regs; + +static inline unsigned int lcdc_read(unsigned int addr) +{ + return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr)); +} + +static inline void lcdc_write(unsigned int val, unsigned int addr) +{ + __raw_writel(val, da8xx_fb_reg_base + (addr)); +} + +struct da8xx_fb_par { + resource_size_t p_palette_base; + unsigned char *v_palette_base; + struct clk *lcdc_clk; + int irq; + unsigned short pseudo_palette[16]; + unsigned int databuf_sz; + unsigned int palette_sz; +}; + +/* Variable Screen Information */ +static struct fb_var_screeninfo da8xx_fb_var __devinitdata = { + .xoffset = 0, + .yoffset = 0, + .transp = {0, 0, 0}, + .nonstd = 0, + .activate = 0, + .height = -1, + .width = -1, + .pixclock = 46666, /* 46us - AUO display */ + .accel_flags = 0, + .left_margin = LEFT_MARGIN, + .right_margin = RIGHT_MARGIN, + .upper_margin = UPPER_MARGIN, + .lower_margin = LOWER_MARGIN, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED +}; + +static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = { + .id = "DA8xx FB Drv", + .type = FB_TYPE_PACKED_PIXELS, + .type_aux = 0, + .visual = FB_VISUAL_PSEUDOCOLOR, + .xpanstep = 1, + .ypanstep = 1, + .ywrapstep = 1, + .accel = FB_ACCEL_NONE +}; + +struct da8xx_panel { + const char name[25]; /* Full name <vendor>_<model> */ + unsigned short width; + unsigned short height; + int hfp; /* Horizontal front porch */ + int hbp; /* Horizontal back porch */ + int hsw; /* Horizontal Sync Pulse Width */ + int vfp; /* Vertical front porch */ + int vbp; /* Vertical back porch */ + int vsw; /* Vertical Sync Pulse Width */ + int pxl_clk; /* Pixel clock */ + unsigned char invert_pxl_clk; /* Invert Pixel clock */ +}; + +static struct da8xx_panel known_lcd_panels[] = { + /* Sharp LCD035Q3DG01 */ + [0] = { + .name = "Sharp_LCD035Q3DG01", + .width = 320, + .height = 240, + .hfp = 8, + .hbp = 6, + .hsw = 0, + .vfp = 2, + .vbp = 2, + .vsw = 0, + .pxl_clk = 0x10, + .invert_pxl_clk = 1, + }, + /* Sharp LK043T1DG01 */ + [1] = { + .name = "Sharp_LK043T1DG01", + .width = 480, + .height = 272, + .hfp = 2, + .hbp = 2, + .hsw = 41, + .vfp = 2, + .vbp = 2, + .vsw = 10, + .pxl_clk = 0x12, + .invert_pxl_clk = 0, + }, +}; + +/* Disable the Raster Engine of the LCD Controller */ +static void lcd_disable_raster(struct da8xx_fb_par *par) +{ + u32 reg; + + reg = lcdc_read(LCD_RASTER_CTRL_REG); + if (reg & LCD_RASTER_ENABLE) + lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); +} + +static void lcd_blit(int load_mode, struct da8xx_fb_par *par) +{ + u32 tmp = par->p_palette_base + par->databuf_sz - 4; + u32 reg; + + /* Update the databuf in the hw. */ + lcdc_write(par->p_palette_base, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); + lcdc_write(tmp, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); + + /* Start the DMA. */ + reg = lcdc_read(LCD_RASTER_CTRL_REG); + reg &= ~(3 << 20); + if (load_mode == LOAD_DATA) + reg |= LCD_PALETTE_LOAD_MODE(PALETTE_AND_DATA); + else if (load_mode == LOAD_PALETTE) + reg |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); + + lcdc_write(reg, LCD_RASTER_CTRL_REG); +} + +/* Configure the Burst Size of DMA */ +static int lcd_cfg_dma(int burst_size) +{ + u32 reg; + + reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001; + switch (burst_size) { + case 1: + reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1); + break; + case 2: + reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2); + break; + case 4: + reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4); + break; + case 8: + reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); + break; + case 16: + reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); + break; + default: + return -EINVAL; + } + lcdc_write(reg, LCD_DMA_CTRL_REG); + + return 0; +} + +static void lcd_cfg_ac_bias(int period, int transitions_per_int) +{ + u32 reg; + + /* Set the AC Bias Period and Number of Transisitons per Interrupt */ + reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000; + reg |= LCD_AC_BIAS_FREQUENCY(period) | + LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int); + lcdc_write(reg, LCD_RASTER_TIMING_2_REG); +} + +static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width, + int front_porch) +{ + u32 reg; + + reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf; + reg |= ((back_porch & 0xff) << 24) + | ((front_porch & 0xff) << 16) + | ((pulse_width & 0x3f) << 10); + lcdc_write(reg, LCD_RASTER_TIMING_0_REG); +} + +static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, + int front_porch) +{ + u32 reg; + + reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff; + reg |= ((back_porch & 0xff) << 24) + | ((front_porch & 0xff) << 16) + | ((pulse_width & 0x3f) << 10); + lcdc_write(reg, LCD_RASTER_TIMING_1_REG); +} + +static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) +{ + u32 reg; + + reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | + LCD_MONO_8BIT_MODE | + LCD_MONOCHROME_MODE); + + switch (cfg->p_disp_panel->panel_shade) { + case MONOCHROME: + reg |= LCD_MONOCHROME_MODE; + if (cfg->mono_8bit_mode) + reg |= LCD_MONO_8BIT_MODE; + break; + case COLOR_ACTIVE: + reg |= LCD_TFT_MODE; + if (cfg->tft_alt_mode) + reg |= LCD_TFT_ALT_ENABLE; + break; + + case COLOR_PASSIVE: + if (cfg->stn_565_mode) + reg |= LCD_STN_565_ENABLE; + break; + + default: + return -EINVAL; + } + + /* enable additional interrupts here */ + reg |= LCD_UNDERFLOW_INT_ENA; + + lcdc_write(reg, LCD_RASTER_CTRL_REG); + + reg = lcdc_read(LCD_RASTER_TIMING_2_REG); + + if (cfg->sync_ctrl) + reg |= LCD_SYNC_CTRL; + else + reg &= ~LCD_SYNC_CTRL; + + if (cfg->sync_edge) + reg |= LCD_SYNC_EDGE; + else + reg &= ~LCD_SYNC_EDGE; + + if (cfg->invert_line_clock) + reg |= LCD_INVERT_LINE_CLOCK; + else + reg &= ~LCD_INVERT_LINE_CLOCK; + + if (cfg->invert_frm_clock) + reg |= LCD_INVERT_FRAME_CLOCK; + else + reg &= ~LCD_INVERT_FRAME_CLOCK; + + lcdc_write(reg, LCD_RASTER_TIMING_2_REG); + + return 0; +} + +static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, + u32 bpp, u32 raster_order) +{ + u32 bpl, reg; + + /* Disable Dual Frame Buffer. */ + reg = lcdc_read(LCD_DMA_CTRL_REG); + lcdc_write(reg & ~LCD_DUAL_FRAME_BUFFER_ENABLE, + LCD_DMA_CTRL_REG); + /* Set the Panel Width */ + /* Pixels per line = (PPL + 1)*16 */ + /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ + width &= 0x3f0; + reg = lcdc_read(LCD_RASTER_TIMING_0_REG); + reg &= 0xfffffc00; + reg |= ((width >> 4) - 1) << 4; + lcdc_write(reg, LCD_RASTER_TIMING_0_REG); + + /* Set the Panel Height */ + reg = lcdc_read(LCD_RASTER_TIMING_1_REG); + reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); + lcdc_write(reg, LCD_RASTER_TIMING_1_REG); + + /* Set the Raster Order of the Frame Buffer */ + reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); + if (raster_order) + reg |= LCD_RASTER_ORDER; + lcdc_write(reg, LCD_RASTER_CTRL_REG); + + switch (bpp) { + case 1: + case 2: + case 4: + case 16: + par->palette_sz = 16 * 2; + break; + + case 8: + par->palette_sz = 256 * 2; + break; + + default: + return -EINVAL; + } + + bpl = width * bpp / 8; + par->databuf_sz = height * bpl + par->palette_sz; + + return 0; +} + +static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + struct da8xx_fb_par *par = info->par; + unsigned short *palette = (unsigned short *)par->v_palette_base; + u_short pal; + + if (regno > 255) + return 1; + + if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) + return 1; + + if (info->var.bits_per_pixel == 8) { + red >>= 4; + green >>= 8; + blue >>= 12; + + pal = (red & 0x0f00); + pal |= (green & 0x00f0); + pal |= (blue & 0x000f); + + palette[regno] = pal; + + } else if ((info->var.bits_per_pixel == 16) && regno < 16) { + red >>= (16 - info->var.red.length); + red <<= info->var.red.offset; + + green >>= (16 - info->var.green.length); + green <<= info->var.green.offset; + + blue >>= (16 - info->var.blue.length); + blue <<= info->var.blue.offset; + + par->pseudo_palette[regno] = red | green | blue; + + palette[0] = 0x4000; + } + + return 0; +} + +static void lcd_reset(struct da8xx_fb_par *par) +{ + /* Disable the Raster if previously Enabled */ + if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE) + lcd_disable_raster(par); + + /* DMA has to be disabled */ + lcdc_write(0, LCD_DMA_CTRL_REG); + lcdc_write(0, LCD_RASTER_CTRL_REG); +} + +static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, + struct da8xx_panel *panel) +{ + u32 bpp; + int ret = 0; + + lcd_reset(par); + + /* Configure the LCD clock divisor. */ + lcdc_write(LCD_CLK_DIVISOR(panel->pxl_clk) | + (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); + + if (panel->invert_pxl_clk) + lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | + LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); + else + lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) & + ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); + + /* Configure the DMA burst size. */ + ret = lcd_cfg_dma(cfg->dma_burst_sz); + if (ret < 0) + return ret; + + /* Configure the AC bias properties. */ + lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); + + /* Configure the vertical and horizontal sync properties. */ + lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp); + lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp); + + /* Configure for disply */ + ret = lcd_cfg_display(cfg); + if (ret < 0) + return ret; + + if (QVGA != cfg->p_disp_panel->panel_type) + return -EINVAL; + + if (cfg->bpp <= cfg->p_disp_panel->max_bpp && + cfg->bpp >= cfg->p_disp_panel->min_bpp) + bpp = cfg->bpp; + else + bpp = cfg->p_disp_panel->max_bpp; + if (bpp == 12) + bpp = 16; + ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width, + (unsigned int)panel->height, bpp, + cfg->raster_order); + if (ret < 0) + return ret; + + /* Configure FDD */ + lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) | + (cfg->fdd << 12), LCD_RASTER_CTRL_REG); + + return 0; +} + +static irqreturn_t lcdc_irq_handler(int irq, void *arg) +{ + u32 stat = lcdc_read(LCD_STAT_REG); + u32 reg; + + if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { + reg = lcdc_read(LCD_RASTER_CTRL_REG); + lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); + lcdc_write(stat, LCD_STAT_REG); + lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); + } else + lcdc_write(stat, LCD_STAT_REG); + + return IRQ_HANDLED; +} + +static int fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + int err = 0; + + switch (var->bits_per_pixel) { + case 1: + case 8: + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 4: + var->red.offset = 0; + var->red.length = 4; + var->green.offset = 0; + var->green.length = 4; + var->blue.offset = 0; + var->blue.length = 4; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 16: /* RGB 565 */ + var->red.offset = 0; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 11; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + break; + default: + err = -EINVAL; + } + + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.msb_right = 0; + return err; +} + +static int __devexit fb_remove(struct platform_device *dev) +{ + struct fb_info *info = dev_get_drvdata(&dev->dev); + + if (info) { + struct da8xx_fb_par *par = info->par; + + if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE) + lcd_disable_raster(par); + lcdc_write(0, LCD_RASTER_CTRL_REG); + + /* disable DMA */ + lcdc_write(0, LCD_DMA_CTRL_REG); + + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, + info->screen_base, + info->fix.smem_start); + free_irq(par->irq, par); + clk_disable(par->lcdc_clk); + clk_put(par->lcdc_clk); + framebuffer_release(info); + iounmap((void __iomem *)da8xx_fb_reg_base); + release_mem_region(lcdc_regs->start, resource_size(lcdc_regs)); + + } + return 0; +} + +static int fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + struct lcd_sync_arg sync_arg; + + switch (cmd) { + case FBIOGET_CONTRAST: + case FBIOPUT_CONTRAST: + case FBIGET_BRIGHTNESS: + case FBIPUT_BRIGHTNESS: + case FBIGET_COLOR: + case FBIPUT_COLOR: + return -ENOTTY; + case FBIPUT_HSYNC: + if (copy_from_user(&sync_arg, (char *)arg, + sizeof(struct lcd_sync_arg))) + return -EFAULT; + lcd_cfg_horizontal_sync(sync_arg.back_porch, + sync_arg.pulse_width, + sync_arg.front_porch); + break; + case FBIPUT_VSYNC: + if (copy_from_user(&sync_arg, (char *)arg, + sizeof(struct lcd_sync_arg))) + return -EFAULT; + lcd_cfg_vertical_sync(sync_arg.back_porch, + sync_arg.pulse_width, + sync_arg.front_porch); + break; + default: + return -EINVAL; + } + return 0; +} + +static struct fb_ops da8xx_fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = fb_check_var, + .fb_setcolreg = fb_setcolreg, + .fb_ioctl = fb_ioctl, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int __init fb_probe(struct platform_device *device) +{ + struct da8xx_lcdc_platform_data *fb_pdata = + device->dev.platform_data; + struct lcd_ctrl_config *lcd_cfg; + struct da8xx_panel *lcdc_info; + struct fb_info *da8xx_fb_info; + struct clk *fb_clk = NULL; + struct da8xx_fb_par *par; + resource_size_t len; + int ret, i; + + if (fb_pdata == NULL) { + dev_err(&device->dev, "Can not get platform data\n"); + return -ENOENT; + } + + lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); + if (!lcdc_regs) { + dev_err(&device->dev, + "Can not get memory resource for LCD controller\n"); + return -ENOENT; + } + + len = resource_size(lcdc_regs); + + lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name); + if (!lcdc_regs) + return -EBUSY; + + da8xx_fb_reg_base = (resource_size_t)ioremap(lcdc_regs->start, len); + if (!da8xx_fb_reg_base) { + ret = -EBUSY; + goto err_request_mem; + } + + fb_clk = clk_get(&device->dev, NULL); + if (IS_ERR(fb_clk)) { + dev_err(&device->dev, "Can not get device clock\n"); + ret = -ENODEV; + goto err_ioremap; + } + ret = clk_enable(fb_clk); + if (ret) + goto err_clk_put; + + for (i = 0, lcdc_info = known_lcd_panels; + i < ARRAY_SIZE(known_lcd_panels); + i++, lcdc_info++) { + if (strcmp(fb_pdata->type, lcdc_info->name) == 0) + break; + } + + if (i == ARRAY_SIZE(known_lcd_panels)) { + dev_err(&device->dev, "GLCD: No valid panel found\n"); + ret = ENODEV; + goto err_clk_disable; + } else + dev_info(&device->dev, "GLCD: Found %s panel\n", + fb_pdata->type); + + lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; + + da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), + &device->dev); + if (!da8xx_fb_info) { + dev_dbg(&device->dev, "Memory allocation failed for fb_info\n"); + ret = -ENOMEM; + goto err_clk_disable; + } + + par = da8xx_fb_info->par; + + if (lcd_init(par, lcd_cfg, lcdc_info) < 0) { + dev_err(&device->dev, "lcd_init failed\n"); + ret = -EFAULT; + goto err_release_fb; + } + + /* allocate frame buffer */ + da8xx_fb_info->screen_base = dma_alloc_coherent(NULL, + par->databuf_sz + PAGE_SIZE, + (resource_size_t *) + &da8xx_fb_info->fix.smem_start, + GFP_KERNEL | GFP_DMA); + + if (!da8xx_fb_info->screen_base) { + dev_err(&device->dev, + "GLCD: kmalloc for frame buffer failed\n"); + ret = -EINVAL; + goto err_release_fb; + } + + /* move palette base pointer by (PAGE_SIZE - palette_sz) bytes */ + par->v_palette_base = da8xx_fb_info->screen_base + + (PAGE_SIZE - par->palette_sz); + par->p_palette_base = da8xx_fb_info->fix.smem_start + + (PAGE_SIZE - par->palette_sz); + + /* the rest of the frame buffer is pixel data */ + da8xx_fb_fix.smem_start = par->p_palette_base + par->palette_sz; + da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz; + da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; + + par->lcdc_clk = fb_clk; + + par->irq = platform_get_irq(device, 0); + if (par->irq < 0) { + ret = -ENOENT; + goto err_release_fb_mem; + } + + ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); + if (ret) + goto err_release_fb_mem; + + /* Initialize par */ + da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; + + da8xx_fb_var.xres = lcdc_info->width; + da8xx_fb_var.xres_virtual = lcdc_info->width; + + da8xx_fb_var.yres = lcdc_info->height; + da8xx_fb_var.yres_virtual = lcdc_info->height; + + da8xx_fb_var.grayscale = + lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; + da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; + + da8xx_fb_var.hsync_len = lcdc_info->hsw; + da8xx_fb_var.vsync_len = lcdc_info->vsw; + + /* Initialize fbinfo */ + da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; + da8xx_fb_info->fix = da8xx_fb_fix; + da8xx_fb_info->var = da8xx_fb_var; + da8xx_fb_info->fbops = &da8xx_fb_ops; + da8xx_fb_info->pseudo_palette = par->pseudo_palette; + + ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); + if (ret) + goto err_free_irq; + + /* First palette_sz byte of the frame buffer is the palette */ + da8xx_fb_info->cmap.len = par->palette_sz; + + /* Flush the buffer to the screen. */ + lcd_blit(LOAD_DATA, par); + + /* initialize var_screeninfo */ + da8xx_fb_var.activate = FB_ACTIVATE_FORCE; + fb_set_var(da8xx_fb_info, &da8xx_fb_var); + + dev_set_drvdata(&device->dev, da8xx_fb_info); + /* Register the Frame Buffer */ + if (register_framebuffer(da8xx_fb_info) < 0) { + dev_err(&device->dev, + "GLCD: Frame Buffer Registration Failed!\n"); + ret = -EINVAL; + goto err_dealloc_cmap; + } + + /* enable raster engine */ + lcdc_write(lcdc_read(LCD_RASTER_CTRL_REG) | + LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); + + return 0; + +err_dealloc_cmap: + fb_dealloc_cmap(&da8xx_fb_info->cmap); + +err_free_irq: + free_irq(par->irq, par); + +err_release_fb_mem: + dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, + da8xx_fb_info->screen_base, + da8xx_fb_info->fix.smem_start); + +err_release_fb: + framebuffer_release(da8xx_fb_info); + +err_clk_disable: + clk_disable(fb_clk); + +err_clk_put: + clk_put(fb_clk); + +err_ioremap: + iounmap((void __iomem *)da8xx_fb_reg_base); + +err_request_mem: + release_mem_region(lcdc_regs->start, len); + + return ret; +} + +#ifdef CONFIG_PM +static int fb_suspend(struct platform_device *dev, pm_message_t state) +{ + return -EBUSY; +} +static int fb_resume(struct platform_device *dev) +{ + return -EBUSY; +} +#else +#define fb_suspend NULL +#define fb_resume NULL +#endif + +static struct platform_driver da8xx_fb_driver = { + .probe = fb_probe, + .remove = fb_remove, + .suspend = fb_suspend, + .resume = fb_resume, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init da8xx_fb_init(void) +{ + return platform_driver_register(&da8xx_fb_driver); +} + +static void __exit da8xx_fb_cleanup(void) +{ + platform_driver_unregister(&da8xx_fb_driver); +} + +module_init(da8xx_fb_init); +module_exit(da8xx_fb_cleanup); + +MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx"); +MODULE_AUTHOR("Texas Instruments"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c new file mode 100644 index 000000000000..bd9d46f95291 --- /dev/null +++ b/drivers/video/ep93xx-fb.c @@ -0,0 +1,646 @@ +/* + * linux/drivers/video/ep93xx-fb.c + * + * Framebuffer support for the EP93xx series. + * + * Copyright (C) 2007 Bluewater Systems Ltd + * Author: Ryan Mallon <ryan@bluewatersys.com> + * + * Copyright (c) 2009 H Hartley Sweeten <hsweeten@visionengravers.com> + * + * Based on the Cirrus Logic ep93xxfb driver, and various other ep93xxfb + * drivers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> +#include <linux/fb.h> + +#include <mach/fb.h> + +/* Vertical Frame Timing Registers */ +#define EP93XXFB_VLINES_TOTAL 0x0000 /* SW locked */ +#define EP93XXFB_VSYNC 0x0004 /* SW locked */ +#define EP93XXFB_VACTIVE 0x0008 /* SW locked */ +#define EP93XXFB_VBLANK 0x0228 /* SW locked */ +#define EP93XXFB_VCLK 0x000c /* SW locked */ + +/* Horizontal Frame Timing Registers */ +#define EP93XXFB_HCLKS_TOTAL 0x0010 /* SW locked */ +#define EP93XXFB_HSYNC 0x0014 /* SW locked */ +#define EP93XXFB_HACTIVE 0x0018 /* SW locked */ +#define EP93XXFB_HBLANK 0x022c /* SW locked */ +#define EP93XXFB_HCLK 0x001c /* SW locked */ + +/* Frame Buffer Memory Configuration Registers */ +#define EP93XXFB_SCREEN_PAGE 0x0028 +#define EP93XXFB_SCREEN_HPAGE 0x002c +#define EP93XXFB_SCREEN_LINES 0x0030 +#define EP93XXFB_LINE_LENGTH 0x0034 +#define EP93XXFB_VLINE_STEP 0x0038 +#define EP93XXFB_LINE_CARRY 0x003c /* SW locked */ +#define EP93XXFB_EOL_OFFSET 0x0230 + +/* Other Video Registers */ +#define EP93XXFB_BRIGHTNESS 0x0020 +#define EP93XXFB_ATTRIBS 0x0024 /* SW locked */ +#define EP93XXFB_SWLOCK 0x007c /* SW locked */ +#define EP93XXFB_AC_RATE 0x0214 +#define EP93XXFB_FIFO_LEVEL 0x0234 +#define EP93XXFB_PIXELMODE 0x0054 +#define EP93XXFB_PIXELMODE_32BPP (0x7 << 0) +#define EP93XXFB_PIXELMODE_24BPP (0x6 << 0) +#define EP93XXFB_PIXELMODE_16BPP (0x4 << 0) +#define EP93XXFB_PIXELMODE_8BPP (0x2 << 0) +#define EP93XXFB_PIXELMODE_SHIFT_1P_24B (0x0 << 3) +#define EP93XXFB_PIXELMODE_SHIFT_1P_18B (0x1 << 3) +#define EP93XXFB_PIXELMODE_COLOR_LUT (0x0 << 10) +#define EP93XXFB_PIXELMODE_COLOR_888 (0x4 << 10) +#define EP93XXFB_PIXELMODE_COLOR_555 (0x5 << 10) +#define EP93XXFB_PARL_IF_OUT 0x0058 +#define EP93XXFB_PARL_IF_IN 0x005c + +/* Blink Control Registers */ +#define EP93XXFB_BLINK_RATE 0x0040 +#define EP93XXFB_BLINK_MASK 0x0044 +#define EP93XXFB_BLINK_PATTRN 0x0048 +#define EP93XXFB_PATTRN_MASK 0x004c +#define EP93XXFB_BKGRND_OFFSET 0x0050 + +/* Hardware Cursor Registers */ +#define EP93XXFB_CURSOR_ADR_START 0x0060 +#define EP93XXFB_CURSOR_ADR_RESET 0x0064 +#define EP93XXFB_CURSOR_SIZE 0x0068 +#define EP93XXFB_CURSOR_COLOR1 0x006c +#define EP93XXFB_CURSOR_COLOR2 0x0070 +#define EP93XXFB_CURSOR_BLINK_COLOR1 0x021c +#define EP93XXFB_CURSOR_BLINK_COLOR2 0x0220 +#define EP93XXFB_CURSOR_XY_LOC 0x0074 +#define EP93XXFB_CURSOR_DSCAN_HY_LOC 0x0078 +#define EP93XXFB_CURSOR_BLINK_RATE_CTRL 0x0224 + +/* LUT Registers */ +#define EP93XXFB_GRY_SCL_LUTR 0x0080 +#define EP93XXFB_GRY_SCL_LUTG 0x0280 +#define EP93XXFB_GRY_SCL_LUTB 0x0300 +#define EP93XXFB_LUT_SW_CONTROL 0x0218 +#define EP93XXFB_LUT_SW_CONTROL_SWTCH (1 << 0) +#define EP93XXFB_LUT_SW_CONTROL_SSTAT (1 << 1) +#define EP93XXFB_COLOR_LUT 0x0400 + +/* Video Signature Registers */ +#define EP93XXFB_VID_SIG_RSLT_VAL 0x0200 +#define EP93XXFB_VID_SIG_CTRL 0x0204 +#define EP93XXFB_VSIG 0x0208 +#define EP93XXFB_HSIG 0x020c +#define EP93XXFB_SIG_CLR_STR 0x0210 + +/* Minimum / Maximum resolutions supported */ +#define EP93XXFB_MIN_XRES 64 +#define EP93XXFB_MIN_YRES 64 +#define EP93XXFB_MAX_XRES 1024 +#define EP93XXFB_MAX_YRES 768 + +struct ep93xx_fbi { + struct ep93xxfb_mach_info *mach_info; + struct clk *clk; + struct resource *res; + void __iomem *mmio_base; + unsigned int pseudo_palette[256]; +}; + +static int check_screenpage_bug = 1; +module_param(check_screenpage_bug, int, 0644); +MODULE_PARM_DESC(check_screenpage_bug, + "Check for bit 27 screen page bug. Default = 1"); + +static inline unsigned int ep93xxfb_readl(struct ep93xx_fbi *fbi, + unsigned int off) +{ + return __raw_readl(fbi->mmio_base + off); +} + +static inline void ep93xxfb_writel(struct ep93xx_fbi *fbi, + unsigned int val, unsigned int off) +{ + __raw_writel(val, fbi->mmio_base + off); +} + +/* + * Write to one of the locked raster registers. + */ +static inline void ep93xxfb_out_locked(struct ep93xx_fbi *fbi, + unsigned int val, unsigned int reg) +{ + /* + * We don't need a lock or delay here since the raster register + * block will remain unlocked until the next access. + */ + ep93xxfb_writel(fbi, 0xaa, EP93XXFB_SWLOCK); + ep93xxfb_writel(fbi, val, reg); +} + +static void ep93xxfb_set_video_attribs(struct fb_info *info) +{ + struct ep93xx_fbi *fbi = info->par; + unsigned int attribs; + + attribs = EP93XXFB_ENABLE; + attribs |= fbi->mach_info->flags; + ep93xxfb_out_locked(fbi, attribs, EP93XXFB_ATTRIBS); +} + +static int ep93xxfb_set_pixelmode(struct fb_info *info) +{ + struct ep93xx_fbi *fbi = info->par; + unsigned int val; + + info->var.transp.offset = 0; + info->var.transp.length = 0; + + switch (info->var.bits_per_pixel) { + case 8: + val = EP93XXFB_PIXELMODE_8BPP | EP93XXFB_PIXELMODE_COLOR_LUT | + EP93XXFB_PIXELMODE_SHIFT_1P_18B; + + info->var.red.offset = 0; + info->var.red.length = 8; + info->var.green.offset = 0; + info->var.green.length = 8; + info->var.blue.offset = 0; + info->var.blue.length = 8; + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + break; + + case 16: + val = EP93XXFB_PIXELMODE_16BPP | EP93XXFB_PIXELMODE_COLOR_555 | + EP93XXFB_PIXELMODE_SHIFT_1P_18B; + + info->var.red.offset = 11; + info->var.red.length = 5; + info->var.green.offset = 5; + info->var.green.length = 6; + info->var.blue.offset = 0; + info->var.blue.length = 5; + info->fix.visual = FB_VISUAL_TRUECOLOR; + break; + + case 24: + val = EP93XXFB_PIXELMODE_24BPP | EP93XXFB_PIXELMODE_COLOR_888 | + EP93XXFB_PIXELMODE_SHIFT_1P_24B; + + info->var.red.offset = 16; + info->var.red.length = 8; + info->var.green.offset = 8; + info->var.green.length = 8; + info->var.blue.offset = 0; + info->var.blue.length = 8; + info->fix.visual = FB_VISUAL_TRUECOLOR; + break; + + case 32: + val = EP93XXFB_PIXELMODE_32BPP | EP93XXFB_PIXELMODE_COLOR_888 | + EP93XXFB_PIXELMODE_SHIFT_1P_24B; + + info->var.red.offset = 16; + info->var.red.length = 8; + info->var.green.offset = 8; + info->var.green.length = 8; + info->var.blue.offset = 0; + info->var.blue.length = 8; + info->fix.visual = FB_VISUAL_TRUECOLOR; + break; + + default: + return -EINVAL; + } + + ep93xxfb_writel(fbi, val, EP93XXFB_PIXELMODE); + return 0; +} + +static void ep93xxfb_set_timing(struct fb_info *info) +{ + struct ep93xx_fbi *fbi = info->par; + unsigned int vlines_total, hclks_total, start, stop; + + vlines_total = info->var.yres + info->var.upper_margin + + info->var.lower_margin + info->var.vsync_len - 1; + + hclks_total = info->var.xres + info->var.left_margin + + info->var.right_margin + info->var.hsync_len - 1; + + ep93xxfb_out_locked(fbi, vlines_total, EP93XXFB_VLINES_TOTAL); + ep93xxfb_out_locked(fbi, hclks_total, EP93XXFB_HCLKS_TOTAL); + + start = vlines_total; + stop = vlines_total - info->var.vsync_len; + ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VSYNC); + + start = vlines_total - info->var.vsync_len - info->var.upper_margin; + stop = info->var.lower_margin - 1; + ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VBLANK); + ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VACTIVE); + + start = vlines_total; + stop = vlines_total + 1; + ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VCLK); + + start = hclks_total; + stop = hclks_total - info->var.hsync_len; + ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HSYNC); + + start = hclks_total - info->var.hsync_len - info->var.left_margin; + stop = info->var.right_margin - 1; + ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HBLANK); + ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HACTIVE); + + start = hclks_total; + stop = hclks_total; + ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HCLK); + + ep93xxfb_out_locked(fbi, 0x0, EP93XXFB_LINE_CARRY); +} + +static int ep93xxfb_set_par(struct fb_info *info) +{ + struct ep93xx_fbi *fbi = info->par; + + clk_set_rate(fbi->clk, 1000 * PICOS2KHZ(info->var.pixclock)); + + ep93xxfb_set_timing(info); + + info->fix.line_length = info->var.xres_virtual * + info->var.bits_per_pixel / 8; + + ep93xxfb_writel(fbi, info->fix.smem_start, EP93XXFB_SCREEN_PAGE); + ep93xxfb_writel(fbi, info->var.yres - 1, EP93XXFB_SCREEN_LINES); + ep93xxfb_writel(fbi, ((info->var.xres * info->var.bits_per_pixel) + / 32) - 1, EP93XXFB_LINE_LENGTH); + ep93xxfb_writel(fbi, info->fix.line_length / 4, EP93XXFB_VLINE_STEP); + ep93xxfb_set_video_attribs(info); + return 0; +} + +static int ep93xxfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + int err; + + err = ep93xxfb_set_pixelmode(info); + if (err) + return err; + + var->xres = max_t(unsigned int, var->xres, EP93XXFB_MIN_XRES); + var->xres = min_t(unsigned int, var->xres, EP93XXFB_MAX_XRES); + var->xres_virtual = max(var->xres_virtual, var->xres); + + var->yres = max_t(unsigned int, var->yres, EP93XXFB_MIN_YRES); + var->yres = min_t(unsigned int, var->yres, EP93XXFB_MAX_YRES); + var->yres_virtual = max(var->yres_virtual, var->yres); + + return 0; +} + +static int ep93xxfb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + unsigned int offset = vma->vm_pgoff << PAGE_SHIFT; + + if (offset < info->fix.smem_len) { + return dma_mmap_writecombine(info->dev, vma, info->screen_base, + info->fix.smem_start, + info->fix.smem_len); + } + + return -EINVAL; +} + +static int ep93xxfb_blank(int blank_mode, struct fb_info *info) +{ + struct ep93xx_fbi *fbi = info->par; + unsigned int attribs = ep93xxfb_readl(fbi, EP93XXFB_ATTRIBS); + + if (blank_mode) { + if (fbi->mach_info->blank) + fbi->mach_info->blank(blank_mode, info); + ep93xxfb_out_locked(fbi, attribs & ~EP93XXFB_ENABLE, + EP93XXFB_ATTRIBS); + clk_disable(fbi->clk); + } else { + clk_enable(fbi->clk); + ep93xxfb_out_locked(fbi, attribs | EP93XXFB_ENABLE, + EP93XXFB_ATTRIBS); + if (fbi->mach_info->blank) + fbi->mach_info->blank(blank_mode, info); + } + + return 0; +} + +static inline int ep93xxfb_convert_color(int val, int width) +{ + return ((val << width) + 0x7fff - val) >> 16; +} + +static int ep93xxfb_setcolreg(unsigned int regno, unsigned int red, + unsigned int green, unsigned int blue, + unsigned int transp, struct fb_info *info) +{ + struct ep93xx_fbi *fbi = info->par; + unsigned int *pal = info->pseudo_palette; + unsigned int ctrl, i, rgb, lut_current, lut_stat; + + switch (info->fix.visual) { + case FB_VISUAL_PSEUDOCOLOR: + rgb = ((red & 0xff00) << 8) | (green & 0xff00) | + ((blue & 0xff00) >> 8); + + pal[regno] = rgb; + ep93xxfb_writel(fbi, rgb, (EP93XXFB_COLOR_LUT + (regno << 2))); + ctrl = ep93xxfb_readl(fbi, EP93XXFB_LUT_SW_CONTROL); + lut_stat = !!(ctrl & EP93XXFB_LUT_SW_CONTROL_SSTAT); + lut_current = !!(ctrl & EP93XXFB_LUT_SW_CONTROL_SWTCH); + + if (lut_stat == lut_current) { + for (i = 0; i < 256; i++) { + ep93xxfb_writel(fbi, pal[i], + EP93XXFB_COLOR_LUT + (i << 2)); + } + + ep93xxfb_writel(fbi, + ctrl ^ EP93XXFB_LUT_SW_CONTROL_SWTCH, + EP93XXFB_LUT_SW_CONTROL); + } + break; + + case FB_VISUAL_TRUECOLOR: + if (regno > 16) + return 1; + + red = ep93xxfb_convert_color(red, info->var.red.length); + green = ep93xxfb_convert_color(green, info->var.green.length); + blue = ep93xxfb_convert_color(blue, info->var.blue.length); + transp = ep93xxfb_convert_color(transp, + info->var.transp.length); + + pal[regno] = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + break; + + default: + return 1; + } + + return 0; +} + +static struct fb_ops ep93xxfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = ep93xxfb_check_var, + .fb_set_par = ep93xxfb_set_par, + .fb_blank = ep93xxfb_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_setcolreg = ep93xxfb_setcolreg, + .fb_mmap = ep93xxfb_mmap, +}; + +static int __init ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info) +{ + int i, fb_size = 0; + + if (mach_info->num_modes == EP93XXFB_USE_MODEDB) { + fb_size = EP93XXFB_MAX_XRES * EP93XXFB_MAX_YRES * + mach_info->bpp / 8; + } else { + for (i = 0; i < mach_info->num_modes; i++) { + const struct fb_videomode *mode; + int size; + + mode = &mach_info->modes[i]; + size = mode->xres * mode->yres * mach_info->bpp / 8; + if (size > fb_size) + fb_size = size; + } + } + + return fb_size; +} + +static int __init ep93xxfb_alloc_videomem(struct fb_info *info) +{ + struct ep93xx_fbi *fbi = info->par; + char __iomem *virt_addr; + dma_addr_t phys_addr; + unsigned int fb_size; + + fb_size = ep93xxfb_calc_fbsize(fbi->mach_info); + virt_addr = dma_alloc_writecombine(info->dev, fb_size, + &phys_addr, GFP_KERNEL); + if (!virt_addr) + return -ENOMEM; + + /* + * There is a bug in the ep93xx framebuffer which causes problems + * if bit 27 of the physical address is set. + * See: http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2 + * There does not seem to be any offical errata for this, but I + * have confirmed the problem exists on my hardware (ep9315) at + * least. + */ + if (check_screenpage_bug && phys_addr & (1 << 27)) { + dev_err(info->dev, "ep93xx framebuffer bug. phys addr (0x%x) " + "has bit 27 set: cannot init framebuffer\n", + phys_addr); + + dma_free_coherent(info->dev, fb_size, virt_addr, phys_addr); + return -ENOMEM; + } + + info->fix.smem_start = phys_addr; + info->fix.smem_len = fb_size; + info->screen_base = virt_addr; + + return 0; +} + +static void ep93xxfb_dealloc_videomem(struct fb_info *info) +{ + if (info->screen_base) + dma_free_coherent(info->dev, info->fix.smem_len, + info->screen_base, info->fix.smem_start); +} + +static int __init ep93xxfb_probe(struct platform_device *pdev) +{ + struct ep93xxfb_mach_info *mach_info = pdev->dev.platform_data; + struct fb_info *info; + struct ep93xx_fbi *fbi; + struct resource *res; + char *video_mode; + int err; + + if (!mach_info) + return -EINVAL; + + info = framebuffer_alloc(sizeof(struct ep93xx_fbi), &pdev->dev); + if (!info) + return -ENOMEM; + + info->dev = &pdev->dev; + platform_set_drvdata(pdev, info); + fbi = info->par; + fbi->mach_info = mach_info; + + err = fb_alloc_cmap(&info->cmap, 256, 0); + if (err) + goto failed; + + err = ep93xxfb_alloc_videomem(info); + if (err) + goto failed; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -ENXIO; + goto failed; + } + + res = request_mem_region(res->start, resource_size(res), pdev->name); + if (!res) { + err = -EBUSY; + goto failed; + } + + fbi->res = res; + fbi->mmio_base = ioremap(res->start, resource_size(res)); + if (!fbi->mmio_base) { + err = -ENXIO; + goto failed; + } + + strcpy(info->fix.id, pdev->name); + info->fbops = &ep93xxfb_ops; + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.accel = FB_ACCEL_NONE; + info->var.activate = FB_ACTIVATE_NOW; + info->var.vmode = FB_VMODE_NONINTERLACED; + info->flags = FBINFO_DEFAULT; + info->node = -1; + info->state = FBINFO_STATE_RUNNING; + info->pseudo_palette = &fbi->pseudo_palette; + + fb_get_options("ep93xx-fb", &video_mode); + err = fb_find_mode(&info->var, info, video_mode, + fbi->mach_info->modes, fbi->mach_info->num_modes, + fbi->mach_info->default_mode, fbi->mach_info->bpp); + if (err == 0) { + dev_err(info->dev, "No suitable video mode found\n"); + err = -EINVAL; + goto failed; + } + + if (mach_info->setup) { + err = mach_info->setup(pdev); + if (err) + return err; + } + + err = ep93xxfb_check_var(&info->var, info); + if (err) + goto failed; + + fbi->clk = clk_get(info->dev, NULL); + if (IS_ERR(fbi->clk)) { + err = PTR_ERR(fbi->clk); + fbi->clk = NULL; + goto failed; + } + + ep93xxfb_set_par(info); + clk_enable(fbi->clk); + + err = register_framebuffer(info); + if (err) + goto failed; + + dev_info(info->dev, "registered. Mode = %dx%d-%d\n", + info->var.xres, info->var.yres, info->var.bits_per_pixel); + return 0; + +failed: + if (fbi->clk) + clk_put(fbi->clk); + if (fbi->mmio_base) + iounmap(fbi->mmio_base); + if (fbi->res) + release_mem_region(fbi->res->start, resource_size(fbi->res)); + ep93xxfb_dealloc_videomem(info); + if (&info->cmap) + fb_dealloc_cmap(&info->cmap); + if (fbi->mach_info->teardown) + fbi->mach_info->teardown(pdev); + kfree(info); + platform_set_drvdata(pdev, NULL); + + return err; +} + +static int ep93xxfb_remove(struct platform_device *pdev) +{ + struct fb_info *info = platform_get_drvdata(pdev); + struct ep93xx_fbi *fbi = info->par; + + unregister_framebuffer(info); + clk_disable(fbi->clk); + clk_put(fbi->clk); + iounmap(fbi->mmio_base); + release_mem_region(fbi->res->start, resource_size(fbi->res)); + ep93xxfb_dealloc_videomem(info); + fb_dealloc_cmap(&info->cmap); + + if (fbi->mach_info->teardown) + fbi->mach_info->teardown(pdev); + + kfree(info); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver ep93xxfb_driver = { + .probe = ep93xxfb_probe, + .remove = ep93xxfb_remove, + .driver = { + .name = "ep93xx-fb", + .owner = THIS_MODULE, + }, +}; + +static int __devinit ep93xxfb_init(void) +{ + return platform_driver_register(&ep93xxfb_driver); +} + +static void __exit ep93xxfb_exit(void) +{ + platform_driver_unregister(&ep93xxfb_driver); +} + +module_init(ep93xxfb_init); +module_exit(ep93xxfb_exit); + +MODULE_DESCRIPTION("EP93XX Framebuffer Driver"); +MODULE_ALIAS("platform:ep93xx-fb"); +MODULE_AUTHOR("Ryan Mallon <ryan&bluewatersys.com>, " + "H Hartley Sweeten <hsweeten@visionengravers.com"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 0a7a6679ee6e..c27ab1ed9604 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c @@ -125,7 +125,7 @@ page_already_added: return 0; } -static struct vm_operations_struct fb_deferred_io_vm_ops = { +static const struct vm_operations_struct fb_deferred_io_vm_ops = { .fault = fb_deferred_io_fault, .page_mkwrite = fb_deferred_io_mkwrite, }; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 750c71f141f4..99bbd282ce63 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -871,8 +871,8 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) err = -EINVAL; if (err || !info->fbops->fb_pan_display || - var->yoffset + yres > info->var.yres_virtual || - var->xoffset + info->var.xres > info->var.xres_virtual) + var->yoffset > info->var.yres_virtual - yres || + var->xoffset > info->var.xres_virtual - info->var.xres) return -EINVAL; if ((err = info->fbops->fb_pan_display(var, info))) @@ -954,6 +954,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) goto done; if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + struct fb_var_screeninfo old_var; struct fb_videomode mode; if (info->fbops->fb_get_caps) { @@ -963,10 +964,20 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) goto done; } + old_var = info->var; info->var = *var; - if (info->fbops->fb_set_par) - info->fbops->fb_set_par(info); + if (info->fbops->fb_set_par) { + ret = info->fbops->fb_set_par(info); + + if (ret) { + info->var = old_var; + printk(KERN_WARNING "detected " + "fb_set_par error, " + "error code: %d\n", ret); + goto done; + } + } fb_pan_display(info, &info->var); fb_set_cmap(&info->cmap, info); diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 15a0ee6d8e23..66358fa825f3 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -33,6 +33,7 @@ #include <linux/math64.h> #include <mach/imxfb.h> +#include <mach/hardware.h> /* * Complain if VAR is out of range. @@ -129,6 +130,10 @@ #define LCDISR_EOF (1<<1) #define LCDISR_BOF (1<<0) +/* Used fb-mode. Can be set on kernel command line, therefore file-static. */ +static const char *fb_mode; + + /* * These are the bitfields for each * display depth that we support. @@ -145,10 +150,6 @@ struct imxfb_info { void __iomem *regs; struct clk *clk; - u_int max_bpp; - u_int max_xres; - u_int max_yres; - /* * These are the addresses we mapped * the framebuffer memory region to. @@ -172,6 +173,9 @@ struct imxfb_info { cmap_static:1, unused:30; + struct imx_fb_videomode *mode; + int num_modes; + void (*lcd_power)(int); void (*backlight_power)(int); }; @@ -298,6 +302,18 @@ static int imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, return ret; } +static const struct imx_fb_videomode *imxfb_find_mode(struct imxfb_info *fbi) +{ + struct imx_fb_videomode *m; + int i; + + for (i = 0, m = &fbi->mode[0]; i < fbi->num_modes; i++, m++) { + if (!strcmp(m->mode.name, fb_mode)) + return m; + } + return NULL; +} + /* * imxfb_check_var(): * Round up in the following order: bits_per_pixel, xres, @@ -308,35 +324,81 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct imxfb_info *fbi = info->par; struct imxfb_rgb *rgb; + const struct imx_fb_videomode *imxfb_mode; + unsigned long lcd_clk; + unsigned long long tmp; + u32 pcr = 0; if (var->xres < MIN_XRES) var->xres = MIN_XRES; if (var->yres < MIN_YRES) var->yres = MIN_YRES; - if (var->xres > fbi->max_xres) - var->xres = fbi->max_xres; - if (var->yres > fbi->max_yres) - var->yres = fbi->max_yres; - var->xres_virtual = max(var->xres_virtual, var->xres); - var->yres_virtual = max(var->yres_virtual, var->yres); + + imxfb_mode = imxfb_find_mode(fbi); + if (!imxfb_mode) + return -EINVAL; + + var->xres = imxfb_mode->mode.xres; + var->yres = imxfb_mode->mode.yres; + var->bits_per_pixel = imxfb_mode->bpp; + var->pixclock = imxfb_mode->mode.pixclock; + var->hsync_len = imxfb_mode->mode.hsync_len; + var->left_margin = imxfb_mode->mode.left_margin; + var->right_margin = imxfb_mode->mode.right_margin; + var->vsync_len = imxfb_mode->mode.vsync_len; + var->upper_margin = imxfb_mode->mode.upper_margin; + var->lower_margin = imxfb_mode->mode.lower_margin; + var->sync = imxfb_mode->mode.sync; + var->xres_virtual = max(var->xres_virtual, var->xres); + var->yres_virtual = max(var->yres_virtual, var->yres); pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); + + lcd_clk = clk_get_rate(fbi->clk); + + tmp = var->pixclock * (unsigned long long)lcd_clk; + + do_div(tmp, 1000000); + + if (do_div(tmp, 1000000) > 500000) + tmp++; + + pcr = (unsigned int)tmp; + + if (--pcr > 0x3F) { + pcr = 0x3F; + printk(KERN_WARNING "Must limit pixel clock to %luHz\n", + lcd_clk / pcr); + } + switch (var->bits_per_pixel) { case 32: + pcr |= PCR_BPIX_18; rgb = &def_rgb_18; break; case 16: default: - if (fbi->pcr & PCR_TFT) + if (cpu_is_mx1()) + pcr |= PCR_BPIX_12; + else + pcr |= PCR_BPIX_16; + + if (imxfb_mode->pcr & PCR_TFT) rgb = &def_rgb_16_tft; else rgb = &def_rgb_16_stn; break; case 8: + pcr |= PCR_BPIX_8; rgb = &def_rgb_8; break; } + /* add sync polarities */ + pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25)); + + fbi->pcr = pcr; + /* * Copy the RGB parameters for this display * from the machine specific parameters. @@ -393,10 +455,6 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) writel(fbi->screen_dma, fbi->regs + LCDC_SSA); - /* physical screen start address */ - writel(VPW_VPW(fbi->max_xres * fbi->max_bpp / 8 / 4), - fbi->regs + LCDC_VPW); - /* panning offset 0 (0 pixel offset) */ writel(0x00000000, fbi->regs + LCDC_POS); @@ -468,8 +526,6 @@ static struct fb_ops imxfb_ops = { static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct imxfb_info *fbi = info->par; - unsigned int pcr, lcd_clk; - unsigned long long tmp; pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n", var->xres, var->hsync_len, @@ -505,6 +561,10 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf info->fix.id, var->lower_margin); #endif + /* physical screen start address */ + writel(VPW_VPW(var->xres * var->bits_per_pixel / 8 / 4), + fbi->regs + LCDC_VPW); + writel(HCR_H_WIDTH(var->hsync_len - 1) | HCR_H_WAIT_1(var->right_margin - 1) | HCR_H_WAIT_2(var->left_margin - 3), @@ -518,22 +578,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres), fbi->regs + LCDC_SIZE); - lcd_clk = clk_get_rate(fbi->clk); - tmp = var->pixclock * (unsigned long long)lcd_clk; - do_div(tmp, 1000000); - if (do_div(tmp, 1000000) > 500000) - tmp++; - pcr = (unsigned int)tmp; - if (--pcr > 0x3F) { - pcr = 0x3F; - printk(KERN_WARNING "Must limit pixel clock to %uHz\n", - lcd_clk / pcr); - } - - /* add sync polarities */ - pcr |= fbi->pcr & ~0x3F; - - writel(pcr, fbi->regs + LCDC_PCR); + writel(fbi->pcr, fbi->regs + LCDC_PCR); writel(fbi->pwmr, fbi->regs + LCDC_PWMR); writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); writel(fbi->dmacr, fbi->regs + LCDC_DMACR); @@ -575,6 +620,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev) struct imx_fb_platform_data *pdata = pdev->dev.platform_data; struct fb_info *info = dev_get_drvdata(&pdev->dev); struct imxfb_info *fbi = info->par; + struct imx_fb_videomode *m; + int i; pr_debug("%s\n",__func__); @@ -603,35 +650,18 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev) info->fbops = &imxfb_ops; info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST; - - fbi->max_xres = pdata->xres; - info->var.xres = pdata->xres; - info->var.xres_virtual = pdata->xres; - fbi->max_yres = pdata->yres; - info->var.yres = pdata->yres; - info->var.yres_virtual = pdata->yres; - fbi->max_bpp = pdata->bpp; - info->var.bits_per_pixel = pdata->bpp; - info->var.nonstd = pdata->nonstd; - info->var.pixclock = pdata->pixclock; - info->var.hsync_len = pdata->hsync_len; - info->var.left_margin = pdata->left_margin; - info->var.right_margin = pdata->right_margin; - info->var.vsync_len = pdata->vsync_len; - info->var.upper_margin = pdata->upper_margin; - info->var.lower_margin = pdata->lower_margin; - info->var.sync = pdata->sync; info->var.grayscale = pdata->cmap_greyscale; fbi->cmap_inverse = pdata->cmap_inverse; fbi->cmap_static = pdata->cmap_static; - fbi->pcr = pdata->pcr; fbi->lscr1 = pdata->lscr1; fbi->dmacr = pdata->dmacr; fbi->pwmr = pdata->pwmr; fbi->lcd_power = pdata->lcd_power; fbi->backlight_power = pdata->backlight_power; - info->fix.smem_len = fbi->max_xres * fbi->max_yres * - fbi->max_bpp / 8; + + for (i = 0, m = &pdata->mode[0]; i < pdata->num_modes; i++, m++) + info->fix.smem_len = max_t(size_t, info->fix.smem_len, + m->mode.xres * m->mode.yres * m->bpp / 8); return 0; } @@ -642,9 +672,9 @@ static int __init imxfb_probe(struct platform_device *pdev) struct fb_info *info; struct imx_fb_platform_data *pdata; struct resource *res; - int ret; + int ret, i; - printk("i.MX Framebuffer driver\n"); + dev_info(&pdev->dev, "i.MX Framebuffer driver\n"); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -662,6 +692,9 @@ static int __init imxfb_probe(struct platform_device *pdev) fbi = info->par; + if (!fb_mode) + fb_mode = pdata->mode[0].mode.name; + platform_set_drvdata(pdev, info); ret = imxfb_init_fbinfo(pdev); @@ -677,14 +710,14 @@ static int __init imxfb_probe(struct platform_device *pdev) fbi->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(fbi->clk)) { - ret = PTR_ERR(fbi->clk);; + ret = PTR_ERR(fbi->clk); dev_err(&pdev->dev, "unable to get clock: %d\n", ret); goto failed_getclock; } fbi->regs = ioremap(res->start, resource_size(res)); if (fbi->regs == NULL) { - printk(KERN_ERR"Cannot map frame buffer registers\n"); + dev_err(&pdev->dev, "Cannot map frame buffer registers\n"); goto failed_ioremap; } @@ -719,6 +752,13 @@ static int __init imxfb_probe(struct platform_device *pdev) goto failed_platform_init; } + fbi->mode = pdata->mode; + fbi->num_modes = pdata->num_modes; + + INIT_LIST_HEAD(&info->modelist); + for (i = 0; i < pdata->num_modes; i++) + fb_add_videomode(&pdata->mode[i].mode, &info->modelist); + /* * This makes sure that our colour bitfield * descriptors are correctly initialised. @@ -754,7 +794,7 @@ failed_map: failed_getclock: iounmap(fbi->regs); failed_ioremap: - release_mem_region(res->start, res->end - res->start); + release_mem_region(res->start, resource_size(res)); failed_req: kfree(info->pseudo_palette); failed_init: @@ -785,7 +825,7 @@ static int __devexit imxfb_remove(struct platform_device *pdev) framebuffer_release(info); iounmap(fbi->regs); - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); clk_disable(fbi->clk); clk_put(fbi->clk); @@ -811,8 +851,34 @@ static struct platform_driver imxfb_driver = { }, }; +static int imxfb_setup(void) +{ +#ifndef MODULE + char *opt, *options = NULL; + + if (fb_get_options("imxfb", &options)) + return -ENODEV; + + if (!options || !*options) + return 0; + + while ((opt = strsep(&options, ",")) != NULL) { + if (!*opt) + continue; + else + fb_mode = opt; + } +#endif + return 0; +} + int __init imxfb_init(void) { + int ret = imxfb_setup(); + + if (ret < 0) + return ret; + return platform_driver_probe(&imxfb_driver, imxfb_probe); } diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c index d42346e7fdda..09f6e045d5be 100644 --- a/drivers/video/matrox/g450_pll.c +++ b/drivers/video/matrox/g450_pll.c @@ -25,16 +25,19 @@ static inline unsigned int g450_f2vco(unsigned char p, unsigned int fin) { return (p & 0x40) ? fin : fin << ((p & 3) + 1); } -static unsigned int g450_mnp2vco(CPMINFO unsigned int mnp) { +static unsigned int g450_mnp2vco(const struct matrox_fb_info *minfo, + unsigned int mnp) +{ unsigned int m, n; m = ((mnp >> 16) & 0x0FF) + 1; n = ((mnp >> 7) & 0x1FE) + 4; - return (ACCESS_FBINFO(features).pll.ref_freq * n + (m >> 1)) / m; + return (minfo->features.pll.ref_freq * n + (m >> 1)) / m; } -unsigned int g450_mnp2f(CPMINFO unsigned int mnp) { - return g450_vco2f(mnp, g450_mnp2vco(PMINFO mnp)); +unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp) +{ + return g450_vco2f(mnp, g450_mnp2vco(minfo, mnp)); } static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) { @@ -49,7 +52,10 @@ static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) { #define NO_MORE_MNP 0x01FFFFFF #define G450_MNP_FREQBITS (0xFFFFFF43) /* do not mask high byte so we'll catch NO_MORE_MNP */ -static unsigned int g450_nextpll(CPMINFO const struct matrox_pll_limits* pi, unsigned int* fvco, unsigned int mnp) { +static unsigned int g450_nextpll(const struct matrox_fb_info *minfo, + const struct matrox_pll_limits *pi, + unsigned int *fvco, unsigned int mnp) +{ unsigned int m, n, p; unsigned int tvco = *fvco; @@ -90,12 +96,15 @@ static unsigned int g450_nextpll(CPMINFO const struct matrox_pll_limits* pi, uns } else { m--; } - n = ((tvco * (m+1) + ACCESS_FBINFO(features).pll.ref_freq) / (ACCESS_FBINFO(features).pll.ref_freq * 2)) - 2; + n = ((tvco * (m+1) + minfo->features.pll.ref_freq) / (minfo->features.pll.ref_freq * 2)) - 2; } while (n < 0x03 || n > 0x7A); return (m << 16) | (n << 8) | p; } -static unsigned int g450_firstpll(CPMINFO const struct matrox_pll_limits* pi, unsigned int* vco, unsigned int fout) { +static unsigned int g450_firstpll(const struct matrox_fb_info *minfo, + const struct matrox_pll_limits *pi, + unsigned int *vco, unsigned int fout) +{ unsigned int p; unsigned int vcomax; @@ -121,88 +130,94 @@ static unsigned int g450_firstpll(CPMINFO const struct matrox_pll_limits* pi, un } *vco = tvco; } - return g450_nextpll(PMINFO pi, vco, 0xFF0000 | p); + return g450_nextpll(minfo, pi, vco, 0xFF0000 | p); } -static inline unsigned int g450_setpll(CPMINFO unsigned int mnp, unsigned int pll) { +static inline unsigned int g450_setpll(const struct matrox_fb_info *minfo, + unsigned int mnp, unsigned int pll) +{ switch (pll) { case M_PIXEL_PLL_A: - matroxfb_DAC_out(PMINFO M1064_XPIXPLLAM, mnp >> 16); - matroxfb_DAC_out(PMINFO M1064_XPIXPLLAN, mnp >> 8); - matroxfb_DAC_out(PMINFO M1064_XPIXPLLAP, mnp); + matroxfb_DAC_out(minfo, M1064_XPIXPLLAM, mnp >> 16); + matroxfb_DAC_out(minfo, M1064_XPIXPLLAN, mnp >> 8); + matroxfb_DAC_out(minfo, M1064_XPIXPLLAP, mnp); return M1064_XPIXPLLSTAT; case M_PIXEL_PLL_B: - matroxfb_DAC_out(PMINFO M1064_XPIXPLLBM, mnp >> 16); - matroxfb_DAC_out(PMINFO M1064_XPIXPLLBN, mnp >> 8); - matroxfb_DAC_out(PMINFO M1064_XPIXPLLBP, mnp); + matroxfb_DAC_out(minfo, M1064_XPIXPLLBM, mnp >> 16); + matroxfb_DAC_out(minfo, M1064_XPIXPLLBN, mnp >> 8); + matroxfb_DAC_out(minfo, M1064_XPIXPLLBP, mnp); return M1064_XPIXPLLSTAT; case M_PIXEL_PLL_C: - matroxfb_DAC_out(PMINFO M1064_XPIXPLLCM, mnp >> 16); - matroxfb_DAC_out(PMINFO M1064_XPIXPLLCN, mnp >> 8); - matroxfb_DAC_out(PMINFO M1064_XPIXPLLCP, mnp); + matroxfb_DAC_out(minfo, M1064_XPIXPLLCM, mnp >> 16); + matroxfb_DAC_out(minfo, M1064_XPIXPLLCN, mnp >> 8); + matroxfb_DAC_out(minfo, M1064_XPIXPLLCP, mnp); return M1064_XPIXPLLSTAT; case M_SYSTEM_PLL: - matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLM, mnp >> 16); - matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLN, mnp >> 8); - matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLP, mnp); + matroxfb_DAC_out(minfo, DAC1064_XSYSPLLM, mnp >> 16); + matroxfb_DAC_out(minfo, DAC1064_XSYSPLLN, mnp >> 8); + matroxfb_DAC_out(minfo, DAC1064_XSYSPLLP, mnp); return DAC1064_XSYSPLLSTAT; case M_VIDEO_PLL: - matroxfb_DAC_out(PMINFO M1064_XVIDPLLM, mnp >> 16); - matroxfb_DAC_out(PMINFO M1064_XVIDPLLN, mnp >> 8); - matroxfb_DAC_out(PMINFO M1064_XVIDPLLP, mnp); + matroxfb_DAC_out(minfo, M1064_XVIDPLLM, mnp >> 16); + matroxfb_DAC_out(minfo, M1064_XVIDPLLN, mnp >> 8); + matroxfb_DAC_out(minfo, M1064_XVIDPLLP, mnp); return M1064_XVIDPLLSTAT; } return 0; } -static inline unsigned int g450_cmppll(CPMINFO unsigned int mnp, unsigned int pll) { +static inline unsigned int g450_cmppll(const struct matrox_fb_info *minfo, + unsigned int mnp, unsigned int pll) +{ unsigned char m = mnp >> 16; unsigned char n = mnp >> 8; unsigned char p = mnp; switch (pll) { case M_PIXEL_PLL_A: - return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLAM) != m || - matroxfb_DAC_in(PMINFO M1064_XPIXPLLAN) != n || - matroxfb_DAC_in(PMINFO M1064_XPIXPLLAP) != p); + return (matroxfb_DAC_in(minfo, M1064_XPIXPLLAM) != m || + matroxfb_DAC_in(minfo, M1064_XPIXPLLAN) != n || + matroxfb_DAC_in(minfo, M1064_XPIXPLLAP) != p); case M_PIXEL_PLL_B: - return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLBM) != m || - matroxfb_DAC_in(PMINFO M1064_XPIXPLLBN) != n || - matroxfb_DAC_in(PMINFO M1064_XPIXPLLBP) != p); + return (matroxfb_DAC_in(minfo, M1064_XPIXPLLBM) != m || + matroxfb_DAC_in(minfo, M1064_XPIXPLLBN) != n || + matroxfb_DAC_in(minfo, M1064_XPIXPLLBP) != p); case M_PIXEL_PLL_C: - return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLCM) != m || - matroxfb_DAC_in(PMINFO M1064_XPIXPLLCN) != n || - matroxfb_DAC_in(PMINFO M1064_XPIXPLLCP) != p); + return (matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) != m || + matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) != n || + matroxfb_DAC_in(minfo, M1064_XPIXPLLCP) != p); case M_SYSTEM_PLL: - return (matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLM) != m || - matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLN) != n || - matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLP) != p); + return (matroxfb_DAC_in(minfo, DAC1064_XSYSPLLM) != m || + matroxfb_DAC_in(minfo, DAC1064_XSYSPLLN) != n || + matroxfb_DAC_in(minfo, DAC1064_XSYSPLLP) != p); case M_VIDEO_PLL: - return (matroxfb_DAC_in(PMINFO M1064_XVIDPLLM) != m || - matroxfb_DAC_in(PMINFO M1064_XVIDPLLN) != n || - matroxfb_DAC_in(PMINFO M1064_XVIDPLLP) != p); + return (matroxfb_DAC_in(minfo, M1064_XVIDPLLM) != m || + matroxfb_DAC_in(minfo, M1064_XVIDPLLN) != n || + matroxfb_DAC_in(minfo, M1064_XVIDPLLP) != p); } return 1; } -static inline int g450_isplllocked(CPMINFO unsigned int regidx) { +static inline int g450_isplllocked(const struct matrox_fb_info *minfo, + unsigned int regidx) +{ unsigned int j; for (j = 0; j < 1000; j++) { - if (matroxfb_DAC_in(PMINFO regidx) & 0x40) { + if (matroxfb_DAC_in(minfo, regidx) & 0x40) { unsigned int r = 0; int i; for (i = 0; i < 100; i++) { - r += matroxfb_DAC_in(PMINFO regidx) & 0x40; + r += matroxfb_DAC_in(minfo, regidx) & 0x40; } return r >= (90 * 0x40); } @@ -211,8 +226,10 @@ static inline int g450_isplllocked(CPMINFO unsigned int regidx) { return 0; } -static int g450_testpll(CPMINFO unsigned int mnp, unsigned int pll) { - return g450_isplllocked(PMINFO g450_setpll(PMINFO mnp, pll)); +static int g450_testpll(const struct matrox_fb_info *minfo, unsigned int mnp, + unsigned int pll) +{ + return g450_isplllocked(minfo, g450_setpll(minfo, mnp, pll)); } static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsigned int pll) { @@ -225,13 +242,19 @@ static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsi } } -void matroxfb_g450_setpll_cond(WPMINFO unsigned int mnp, unsigned int pll) { - if (g450_cmppll(PMINFO mnp, pll)) { - g450_setpll(PMINFO mnp, pll); +void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp, + unsigned int pll) +{ + if (g450_cmppll(minfo, mnp, pll)) { + g450_setpll(minfo, mnp, pll); } } -static inline unsigned int g450_findworkingpll(WPMINFO unsigned int pll, unsigned int* mnparray, unsigned int mnpcount) { +static inline unsigned int g450_findworkingpll(struct matrox_fb_info *minfo, + unsigned int pll, + unsigned int *mnparray, + unsigned int mnpcount) +{ unsigned int found = 0; unsigned int idx; unsigned int mnpfound = mnparray[0]; @@ -255,22 +278,22 @@ static inline unsigned int g450_findworkingpll(WPMINFO unsigned int pll, unsigne while (sptr >= sarray) { unsigned int mnp = *sptr--; - if (g450_testpll(PMINFO mnp - 0x0300, pll) && - g450_testpll(PMINFO mnp + 0x0300, pll) && - g450_testpll(PMINFO mnp - 0x0200, pll) && - g450_testpll(PMINFO mnp + 0x0200, pll) && - g450_testpll(PMINFO mnp - 0x0100, pll) && - g450_testpll(PMINFO mnp + 0x0100, pll)) { - if (g450_testpll(PMINFO mnp, pll)) { + if (g450_testpll(minfo, mnp - 0x0300, pll) && + g450_testpll(minfo, mnp + 0x0300, pll) && + g450_testpll(minfo, mnp - 0x0200, pll) && + g450_testpll(minfo, mnp + 0x0200, pll) && + g450_testpll(minfo, mnp - 0x0100, pll) && + g450_testpll(minfo, mnp + 0x0100, pll)) { + if (g450_testpll(minfo, mnp, pll)) { return mnp; } - } else if (!found && g450_testpll(PMINFO mnp, pll)) { + } else if (!found && g450_testpll(minfo, mnp, pll)) { mnpfound = mnp; found = 1; } } } - g450_setpll(PMINFO mnpfound, pll); + g450_setpll(minfo, mnpfound, pll); return mnpfound; } @@ -283,7 +306,9 @@ static void g450_addcache(struct matrox_pll_cache* ci, unsigned int mnp_key, uns ci->data[0].mnp_value = mnp_value; } -static int g450_checkcache(WPMINFO struct matrox_pll_cache* ci, unsigned int mnp_key) { +static int g450_checkcache(struct matrox_fb_info *minfo, + struct matrox_pll_cache *ci, unsigned int mnp_key) +{ unsigned int i; mnp_key &= G450_MNP_FREQBITS; @@ -303,8 +328,10 @@ static int g450_checkcache(WPMINFO struct matrox_pll_cache* ci, unsigned int mnp return NO_MORE_MNP; } -static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, - unsigned int* mnparray, unsigned int* deltaarray) { +static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, + unsigned int pll, unsigned int *mnparray, + unsigned int *deltaarray) +{ unsigned int mnpcount; unsigned int pixel_vco; const struct matrox_pll_limits* pi; @@ -321,19 +348,19 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, matroxfb_DAC_lock_irqsave(flags); - xpwrctrl = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL); - matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN); + xpwrctrl = matroxfb_DAC_in(minfo, M1064_XPWRCTRL); + matroxfb_DAC_out(minfo, M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN); mga_outb(M_SEQ_INDEX, M_SEQ1); mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF); - tmp = matroxfb_DAC_in(PMINFO M1064_XPIXCLKCTRL); + tmp = matroxfb_DAC_in(minfo, M1064_XPIXCLKCTRL); tmp |= M1064_XPIXCLKCTRL_DIS; if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) { tmp |= M1064_XPIXCLKCTRL_PLL_UP; } - matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp); + matroxfb_DAC_out(minfo, M1064_XPIXCLKCTRL, tmp); /* DVI PLL preferred for frequencies up to panel link max, standard PLL otherwise */ - if (fout >= MINFO->max_pixel_clock_panellink) + if (fout >= minfo->max_pixel_clock_panellink) tmp = 0; else tmp = M1064_XDVICLKCTRL_DVIDATAPATHSEL | @@ -341,8 +368,8 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, M1064_XDVICLKCTRL_C1DVICLKEN | M1064_XDVICLKCTRL_DVILOOPCTL | M1064_XDVICLKCTRL_P1LOOPBWDTCTL; - matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL,tmp); - matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, + matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); + matroxfb_DAC_out(minfo, M1064_XPWRCTRL, xpwrctrl); matroxfb_DAC_unlock_irqrestore(flags); @@ -363,20 +390,20 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, } mga_outb(M_MISC_REG, misc); } - pi = &ACCESS_FBINFO(limits.pixel); - ci = &ACCESS_FBINFO(cache.pixel); + pi = &minfo->limits.pixel; + ci = &minfo->cache.pixel; break; case M_SYSTEM_PLL: { u_int32_t opt; - pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, &opt); + pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &opt); if (!(opt & 0x20)) { - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, opt | 0x20); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, opt | 0x20); } } - pi = &ACCESS_FBINFO(limits.system); - ci = &ACCESS_FBINFO(cache.system); + pi = &minfo->limits.system; + ci = &minfo->cache.system; break; case M_VIDEO_PLL: { @@ -385,18 +412,18 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, unsigned long flags; matroxfb_DAC_lock_irqsave(flags); - tmp = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL); + tmp = matroxfb_DAC_in(minfo, M1064_XPWRCTRL); if (!(tmp & 2)) { - matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, tmp | 2); + matroxfb_DAC_out(minfo, M1064_XPWRCTRL, tmp | 2); } - mnp = matroxfb_DAC_in(PMINFO M1064_XPIXPLLCM) << 16; - mnp |= matroxfb_DAC_in(PMINFO M1064_XPIXPLLCN) << 8; - pixel_vco = g450_mnp2vco(PMINFO mnp); + mnp = matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) << 16; + mnp |= matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) << 8; + pixel_vco = g450_mnp2vco(minfo, mnp); matroxfb_DAC_unlock_irqrestore(flags); } - pi = &ACCESS_FBINFO(limits.video); - ci = &ACCESS_FBINFO(cache.video); + pi = &minfo->limits.video; + ci = &minfo->cache.video; break; default: return -EINVAL; @@ -407,12 +434,12 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, unsigned int mnp; unsigned int xvco; - for(mnp = g450_firstpll(PMINFO pi, &xvco, fout); mnp != NO_MORE_MNP; mnp = g450_nextpll(PMINFO pi, &xvco, mnp)) { + for (mnp = g450_firstpll(minfo, pi, &xvco, fout); mnp != NO_MORE_MNP; mnp = g450_nextpll(minfo, pi, &xvco, mnp)) { unsigned int idx; unsigned int vco; unsigned int delta; - vco = g450_mnp2vco(PMINFO mnp); + vco = g450_mnp2vco(minfo, mnp); #if 0 if (pll == M_VIDEO_PLL) { unsigned int big, small; @@ -444,7 +471,7 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, * (freqs near VCOmin aren't as stable) */ if (delta == deltaarray[idx-1] - && vco != g450_mnp2vco(PMINFO mnparray[idx-1]) + && vco != g450_mnp2vco(minfo, mnparray[idx-1]) && vco < (pi->vcomin * 17 / 16)) { break; } @@ -468,14 +495,14 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, unsigned int mnp; matroxfb_DAC_lock_irqsave(flags); - mnp = g450_checkcache(PMINFO ci, mnparray[0]); + mnp = g450_checkcache(minfo, ci, mnparray[0]); if (mnp != NO_MORE_MNP) { - matroxfb_g450_setpll_cond(PMINFO mnp, pll); + matroxfb_g450_setpll_cond(minfo, mnp, pll); } else { - mnp = g450_findworkingpll(PMINFO pll, mnparray, mnpcount); + mnp = g450_findworkingpll(minfo, pll, mnparray, mnpcount); g450_addcache(ci, mnparray[0], mnp); } - updatehwstate_clk(&ACCESS_FBINFO(hw), mnp, pll); + updatehwstate_clk(&minfo->hw, mnp, pll); matroxfb_DAC_unlock_irqrestore(flags); return mnp; } @@ -485,14 +512,16 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, * Currently there is 5(p) * 10(m) = 50 possible values. */ #define MNP_TABLE_SIZE 64 -int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll) { +int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, + unsigned int pll) +{ unsigned int* arr; arr = kmalloc(sizeof(*arr) * MNP_TABLE_SIZE * 2, GFP_KERNEL); if (arr) { int r; - r = __g450_setclk(PMINFO fout, pll, arr, arr + MNP_TABLE_SIZE); + r = __g450_setclk(minfo, fout, pll, arr, arr + MNP_TABLE_SIZE); kfree(arr); return r; } diff --git a/drivers/video/matrox/g450_pll.h b/drivers/video/matrox/g450_pll.h index c17ed74501e9..aac615d18440 100644 --- a/drivers/video/matrox/g450_pll.h +++ b/drivers/video/matrox/g450_pll.h @@ -3,8 +3,10 @@ #include "matroxfb_base.h" -int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll); -unsigned int g450_mnp2f(CPMINFO unsigned int mnp); -void matroxfb_g450_setpll_cond(WPMINFO unsigned int mnp, unsigned int pll); +int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, + unsigned int pll); +unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp); +void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp, + unsigned int pll); #endif /* __G450_PLL_H__ */ diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c index c14e3e2212b3..f3728ab262f8 100644 --- a/drivers/video/matrox/i2c-matroxfb.c +++ b/drivers/video/matrox/i2c-matroxfb.c @@ -41,7 +41,7 @@ static int matroxfb_read_gpio(struct matrox_fb_info* minfo) { int v; matroxfb_DAC_lock_irqsave(flags); - v = matroxfb_DAC_in(PMINFO DAC_XGENIODATA); + v = matroxfb_DAC_in(minfo, DAC_XGENIODATA); matroxfb_DAC_unlock_irqrestore(flags); return v; } @@ -51,10 +51,10 @@ static void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) { int v; matroxfb_DAC_lock_irqsave(flags); - v = (matroxfb_DAC_in(PMINFO DAC_XGENIOCTRL) & mask) | val; - matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, v); + v = (matroxfb_DAC_in(minfo, DAC_XGENIOCTRL) & mask) | val; + matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, v); /* We must reset GENIODATA very often... XFree plays with this register */ - matroxfb_DAC_out(PMINFO DAC_XGENIODATA, 0x00); + matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0x00); matroxfb_DAC_unlock_irqrestore(flags); } @@ -112,7 +112,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, i2c_set_adapdata(&b->adapter, b); b->adapter.class = class; b->adapter.algo_data = &b->bac; - b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev; + b->adapter.dev.parent = &minfo->pcidev->dev; b->bac = matrox_i2c_algo_template; b->bac.data = b; err = i2c_bit_add_bus(&b->adapter); @@ -149,11 +149,11 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) { return NULL; matroxfb_DAC_lock_irqsave(flags); - matroxfb_DAC_out(PMINFO DAC_XGENIODATA, 0xFF); - matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, 0x00); + matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0xFF); + matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, 0x00); matroxfb_DAC_unlock_irqrestore(flags); - switch (ACCESS_FBINFO(chip)) { + switch (minfo->chip) { case MGA_2064: case MGA_2164: err = i2c_bus_reg(&m2info->ddc1, minfo, @@ -168,7 +168,7 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) { } if (err) goto fail_ddc1; - if (ACCESS_FBINFO(devflags.dualhead)) { + if (minfo->devflags.dualhead) { err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, "DDC:fb%u #1", I2C_CLASS_DDC); diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index a74e5da17aa0..f9fa0fd00292 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -33,7 +33,11 @@ #define DAC1064_OPT_MDIV2 0x00 #define DAC1064_OPT_RESERVED 0x10 -static void DAC1064_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsigned int* in, unsigned int* feed, unsigned int* post) { +static void DAC1064_calcclock(const struct matrox_fb_info *minfo, + unsigned int freq, unsigned int fmax, + unsigned int *in, unsigned int *feed, + unsigned int *post) +{ unsigned int fvco; unsigned int p; @@ -41,7 +45,7 @@ static void DAC1064_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsi /* only for devices older than G450 */ - fvco = PLL_calcclock(PMINFO freq, fmax, in, feed, &p); + fvco = PLL_calcclock(minfo, freq, fmax, in, feed, &p); p = (1 << p) - 1; if (fvco <= 100000) @@ -80,32 +84,35 @@ static const unsigned char MGA1064_DAC[] = { 0x00, 0x00, 0x00, 0xFF, 0xFF}; -static void DAC1064_setpclk(WPMINFO unsigned long fout) { +static void DAC1064_setpclk(struct matrox_fb_info *minfo, unsigned long fout) +{ unsigned int m, n, p; DBG(__func__) - DAC1064_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); - ACCESS_FBINFO(hw).DACclk[0] = m; - ACCESS_FBINFO(hw).DACclk[1] = n; - ACCESS_FBINFO(hw).DACclk[2] = p; + DAC1064_calcclock(minfo, fout, minfo->max_pixel_clock, &m, &n, &p); + minfo->hw.DACclk[0] = m; + minfo->hw.DACclk[1] = n; + minfo->hw.DACclk[2] = p; } -static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) { +static void DAC1064_setmclk(struct matrox_fb_info *minfo, int oscinfo, + unsigned long fmem) +{ u_int32_t mx; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) - if (ACCESS_FBINFO(devflags.noinit)) { + if (minfo->devflags.noinit) { /* read MCLK and give up... */ - hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM); - hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN); - hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP); + hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM); + hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN); + hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP); return; } mx = hw->MXoptionReg | 0x00000004; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx); mx &= ~0x000000BB; if (oscinfo & DAC1064_OPT_GDIV1) mx |= 0x00000008; @@ -120,9 +127,9 @@ static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) { /* powerup system PLL, select PCI clock */ mx |= 0x00000020; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx); mx &= ~0x00000004; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx); /* !!! you must not access device if MCLK is not running !!! Doing so cause immediate PCI lockup :-( Maybe they should @@ -131,12 +138,12 @@ static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) { perfect... */ /* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not select PLL... because of PLL can be stopped at this time) */ - DAC1064_calcclock(PMINFO fmem, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); - outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3] = m); - outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4] = n); - outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5] = p); + DAC1064_calcclock(minfo, fmem, minfo->max_pixel_clock, &m, &n, &p); + outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3] = m); + outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4] = n); + outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5] = p); for (clk = 65536; clk; --clk) { - if (inDAC1064(PMINFO DAC1064_XSYSPLLSTAT) & 0x40) + if (inDAC1064(minfo, DAC1064_XSYSPLLSTAT) & 0x40) break; } if (!clk) @@ -147,29 +154,30 @@ static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) { /* select specified system clock source */ mx |= oscinfo & DAC1064_OPT_SCLK_MASK; } - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx); mx &= ~0x00000004; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx); hw->MXoptionReg = mx; } #ifdef CONFIG_FB_MATROX_G -static void g450_set_plls(WPMINFO2) { +static void g450_set_plls(struct matrox_fb_info *minfo) +{ u_int32_t c2_ctl; unsigned int pxc; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; int pixelmnp; int videomnp; c2_ctl = hw->crtc2.ctl & ~0x4007; /* Clear PLL + enable for CRTC2 */ c2_ctl |= 0x0001; /* Enable CRTC2 */ hw->DACreg[POS1064_XPWRCTRL] &= ~0x02; /* Stop VIDEO PLL */ - pixelmnp = ACCESS_FBINFO(crtc1).mnp; - videomnp = ACCESS_FBINFO(crtc2).mnp; + pixelmnp = minfo->crtc1.mnp; + videomnp = minfo->crtc2.mnp; if (videomnp < 0) { c2_ctl &= ~0x0001; /* Disable CRTC2 */ hw->DACreg[POS1064_XPWRCTRL] &= ~0x10; /* Powerdown CRTC2 */ - } else if (ACCESS_FBINFO(crtc2).pixclock == ACCESS_FBINFO(features).pll.ref_freq) { + } else if (minfo->crtc2.pixclock == minfo->features.pll.ref_freq) { c2_ctl |= 0x4002; /* Use reference directly */ } else if (videomnp == pixelmnp) { c2_ctl |= 0x0004; /* Use pixel PLL */ @@ -184,27 +192,27 @@ static void g450_set_plls(WPMINFO2) { c2_ctl |= 0x0006; /* Use video PLL */ hw->DACreg[POS1064_XPWRCTRL] |= 0x02; - outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]); - matroxfb_g450_setpll_cond(PMINFO videomnp, M_VIDEO_PLL); + outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]); + matroxfb_g450_setpll_cond(minfo, videomnp, M_VIDEO_PLL); } hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP; if (pixelmnp >= 0) { hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP; - outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]); - matroxfb_g450_setpll_cond(PMINFO pixelmnp, M_PIXEL_PLL_C); + outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]); + matroxfb_g450_setpll_cond(minfo, pixelmnp, M_PIXEL_PLL_C); } if (c2_ctl != hw->crtc2.ctl) { hw->crtc2.ctl = c2_ctl; mga_outl(0x3C10, c2_ctl); } - pxc = ACCESS_FBINFO(crtc1).pixclock; - if (pxc == 0 || ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC2) { - pxc = ACCESS_FBINFO(crtc2).pixclock; + pxc = minfo->crtc1.pixclock; + if (pxc == 0 || minfo->outputs[2].src == MATROXFB_SRC_CRTC2) { + pxc = minfo->crtc2.pixclock; } - if (ACCESS_FBINFO(chip) == MGA_G550) { + if (minfo->chip == MGA_G550) { if (pxc < 45000) { hw->DACreg[POS1064_XPANMODE] = 0x00; /* 0-50 */ } else if (pxc < 55000) { @@ -245,18 +253,19 @@ static void g450_set_plls(WPMINFO2) { } #endif -void DAC1064_global_init(WPMINFO2) { - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); +void DAC1064_global_init(struct matrox_fb_info *minfo) +{ + struct matrox_hw_state *hw = &minfo->hw; hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK; hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN; hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL; #ifdef CONFIG_FB_MATROX_G - if (ACCESS_FBINFO(devflags.g450dac)) { + if (minfo->devflags.g450dac) { hw->DACreg[POS1064_XPWRCTRL] = 0x1F; /* powerup everything */ hw->DACreg[POS1064_XOUTPUTCONN] = 0x00; /* disable outputs */ hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN; - switch (ACCESS_FBINFO(outputs[0]).src) { + switch (minfo->outputs[0].src) { case MATROXFB_SRC_CRTC1: case MATROXFB_SRC_CRTC2: hw->DACreg[POS1064_XOUTPUTCONN] |= 0x01; /* enable output; CRTC1/2 selection is in CRTC2 ctl */ @@ -265,12 +274,12 @@ void DAC1064_global_init(WPMINFO2) { hw->DACreg[POS1064_XMISCCTRL] &= ~M1064_XMISCCTRL_DAC_EN; break; } - switch (ACCESS_FBINFO(outputs[1]).src) { + switch (minfo->outputs[1].src) { case MATROXFB_SRC_CRTC1: hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04; break; case MATROXFB_SRC_CRTC2: - if (ACCESS_FBINFO(outputs[1]).mode == MATROXFB_OUTPUT_MODE_MONITOR) { + if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_MONITOR) { hw->DACreg[POS1064_XOUTPUTCONN] |= 0x08; } else { hw->DACreg[POS1064_XOUTPUTCONN] |= 0x0C; @@ -280,7 +289,7 @@ void DAC1064_global_init(WPMINFO2) { hw->DACreg[POS1064_XPWRCTRL] &= ~0x01; /* Poweroff DAC2 */ break; } - switch (ACCESS_FBINFO(outputs[2]).src) { + switch (minfo->outputs[2].src) { case MATROXFB_SRC_CRTC1: hw->DACreg[POS1064_XOUTPUTCONN] |= 0x20; break; @@ -299,55 +308,57 @@ void DAC1064_global_init(WPMINFO2) { break; } /* Now set timming related variables... */ - g450_set_plls(PMINFO2); + g450_set_plls(minfo); } else #endif { - if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1) { + if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1) { hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT; hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12; - } else if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) { + } else if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) { hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12; - } else if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) + } else if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1) hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12; else hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS; - if (ACCESS_FBINFO(outputs[0]).src != MATROXFB_SRC_NONE) + if (minfo->outputs[0].src != MATROXFB_SRC_NONE) hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN; } } -void DAC1064_global_restore(WPMINFO2) { - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); - - outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]); - outDAC1064(PMINFO M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]); - if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) { - outDAC1064(PMINFO 0x20, 0x04); - outDAC1064(PMINFO 0x1F, ACCESS_FBINFO(devflags.dfp_type)); - if (ACCESS_FBINFO(devflags.g450dac)) { - outDAC1064(PMINFO M1064_XSYNCCTRL, 0xCC); - outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]); - outDAC1064(PMINFO M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]); - outDAC1064(PMINFO M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]); +void DAC1064_global_restore(struct matrox_fb_info *minfo) +{ + struct matrox_hw_state *hw = &minfo->hw; + + outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]); + outDAC1064(minfo, M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]); + if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) { + outDAC1064(minfo, 0x20, 0x04); + outDAC1064(minfo, 0x1F, minfo->devflags.dfp_type); + if (minfo->devflags.g450dac) { + outDAC1064(minfo, M1064_XSYNCCTRL, 0xCC); + outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]); + outDAC1064(minfo, M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]); + outDAC1064(minfo, M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]); } } } -static int DAC1064_init_1(WPMINFO struct my_timming* m) { - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); +static int DAC1064_init_1(struct matrox_fb_info *minfo, struct my_timming *m) +{ + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs)); - switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { + switch (minfo->fbcon.var.bits_per_pixel) { /* case 4: not supported by MGA1064 DAC */ case 8: hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; break; case 16: - if (ACCESS_FBINFO(fbcon).var.green.length == 5) + if (minfo->fbcon.var.green.length == 5) hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; else hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; @@ -361,22 +372,23 @@ static int DAC1064_init_1(WPMINFO struct my_timming* m) { default: return 1; /* unsupported depth */ } - hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl); + hw->DACreg[POS1064_XVREFCTRL] = minfo->features.DAC1064.xvrefctrl; hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK; hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN; hw->DACreg[POS1064_XCURADDL] = 0; hw->DACreg[POS1064_XCURADDH] = 0; - DAC1064_global_init(PMINFO2); + DAC1064_global_init(minfo); return 0; } -static int DAC1064_init_2(WPMINFO struct my_timming* m) { - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); +static int DAC1064_init_2(struct matrox_fb_info *minfo, struct my_timming *m) +{ + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) - if (ACCESS_FBINFO(fbcon).var.bits_per_pixel > 16) { /* 256 entries */ + if (minfo->fbcon.var.bits_per_pixel > 16) { /* 256 entries */ int i; for (i = 0; i < 256; i++) { @@ -384,8 +396,8 @@ static int DAC1064_init_2(WPMINFO struct my_timming* m) { hw->DACpal[i * 3 + 1] = i; hw->DACpal[i * 3 + 2] = i; } - } else if (ACCESS_FBINFO(fbcon).var.bits_per_pixel > 8) { - if (ACCESS_FBINFO(fbcon).var.green.length == 5) { /* 0..31, 128..159 */ + } else if (minfo->fbcon.var.bits_per_pixel > 8) { + if (minfo->fbcon.var.green.length == 5) { /* 0..31, 128..159 */ int i; for (i = 0; i < 32; i++) { @@ -413,8 +425,9 @@ static int DAC1064_init_2(WPMINFO struct my_timming* m) { return 0; } -static void DAC1064_restore_1(WPMINFO2) { - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); +static void DAC1064_restore_1(struct matrox_fb_info *minfo) +{ + struct matrox_hw_state *hw = &minfo->hw; CRITFLAGS @@ -422,28 +435,29 @@ static void DAC1064_restore_1(WPMINFO2) { CRITBEGIN - if ((inDAC1064(PMINFO DAC1064_XSYSPLLM) != hw->DACclk[3]) || - (inDAC1064(PMINFO DAC1064_XSYSPLLN) != hw->DACclk[4]) || - (inDAC1064(PMINFO DAC1064_XSYSPLLP) != hw->DACclk[5])) { - outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]); - outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]); - outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]); + if ((inDAC1064(minfo, DAC1064_XSYSPLLM) != hw->DACclk[3]) || + (inDAC1064(minfo, DAC1064_XSYSPLLN) != hw->DACclk[4]) || + (inDAC1064(minfo, DAC1064_XSYSPLLP) != hw->DACclk[5])) { + outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3]); + outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4]); + outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5]); } { unsigned int i; for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL)) - outDAC1064(PMINFO MGA1064_DAC_regs[i], hw->DACreg[i]); + outDAC1064(minfo, MGA1064_DAC_regs[i], hw->DACreg[i]); } } - DAC1064_global_restore(PMINFO2); + DAC1064_global_restore(minfo); CRITEND }; -static void DAC1064_restore_2(WPMINFO2) { +static void DAC1064_restore_2(struct matrox_fb_info *minfo) +{ #ifdef DEBUG unsigned int i; #endif @@ -453,12 +467,12 @@ static void DAC1064_restore_2(WPMINFO2) { #ifdef DEBUG dprintk(KERN_DEBUG "DAC1064regs "); for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { - dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]); + dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], minfo->hw.DACreg[i]); if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... "); } dprintk(KERN_DEBUG "DAC1064clk "); for (i = 0; i < 6; i++) - dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]); + dprintk("C%02X=%02X ", i, minfo->hw.DACclk[i]); dprintk("\n"); #endif } @@ -470,14 +484,14 @@ static int m1064_compute(void* out, struct my_timming* m) { int tmout; CRITFLAGS - DAC1064_setpclk(PMINFO m->pixclock); + DAC1064_setpclk(minfo, m->pixclock); CRITBEGIN for (i = 0; i < 3; i++) - outDAC1064(PMINFO M1064_XPIXPLLCM + i, ACCESS_FBINFO(hw).DACclk[i]); + outDAC1064(minfo, M1064_XPIXPLLCM + i, minfo->hw.DACclk[i]); for (tmout = 500000; tmout; tmout--) { - if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40) + if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40) break; udelay(10); }; @@ -500,9 +514,9 @@ static struct matrox_altout m1064 = { static int g450_compute(void* out, struct my_timming* m) { #define minfo ((struct matrox_fb_info*)out) if (m->mnp < 0) { - m->mnp = matroxfb_g450_setclk(PMINFO m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); + m->mnp = matroxfb_g450_setclk(minfo, m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); if (m->mnp >= 0) { - m->pixclock = g450_mnp2f(PMINFO m->mnp); + m->pixclock = g450_mnp2f(minfo, m->mnp); } } #undef minfo @@ -518,13 +532,14 @@ static struct matrox_altout g450out = { #endif /* NEED_DAC1064 */ #ifdef CONFIG_FB_MATROX_MYSTIQUE -static int MGA1064_init(WPMINFO struct my_timming* m) { - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); +static int MGA1064_init(struct matrox_fb_info *minfo, struct my_timming *m) +{ + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) - if (DAC1064_init_1(PMINFO m)) return 1; - if (matroxfb_vgaHWinit(PMINFO m)) return 1; + if (DAC1064_init_1(minfo, m)) return 1; + if (matroxfb_vgaHWinit(minfo, m)) return 1; hw->MiscOutReg = 0xCB; if (m->sync & FB_SYNC_HOR_HIGH_ACT) @@ -534,20 +549,21 @@ static int MGA1064_init(WPMINFO struct my_timming* m) { if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */ hw->CRTCEXT[3] |= 0x40; - if (DAC1064_init_2(PMINFO m)) return 1; + if (DAC1064_init_2(minfo, m)) return 1; return 0; } #endif #ifdef CONFIG_FB_MATROX_G -static int MGAG100_init(WPMINFO struct my_timming* m) { - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); +static int MGAG100_init(struct matrox_fb_info *minfo, struct my_timming *m) +{ + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) - if (DAC1064_init_1(PMINFO m)) return 1; + if (DAC1064_init_1(minfo, m)) return 1; hw->MXoptionReg &= ~0x2000; - if (matroxfb_vgaHWinit(PMINFO m)) return 1; + if (matroxfb_vgaHWinit(minfo, m)) return 1; hw->MiscOutReg = 0xEF; if (m->sync & FB_SYNC_HOR_HIGH_ACT) @@ -557,27 +573,28 @@ static int MGAG100_init(WPMINFO struct my_timming* m) { if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */ hw->CRTCEXT[3] |= 0x40; - if (DAC1064_init_2(PMINFO m)) return 1; + if (DAC1064_init_2(minfo, m)) return 1; return 0; } #endif /* G */ #ifdef CONFIG_FB_MATROX_MYSTIQUE -static void MGA1064_ramdac_init(WPMINFO2) { +static void MGA1064_ramdac_init(struct matrox_fb_info *minfo) +{ DBG(__func__) - /* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */ - ACCESS_FBINFO(features.pll.vco_freq_min) = 62000; - ACCESS_FBINFO(features.pll.ref_freq) = 14318; - ACCESS_FBINFO(features.pll.feed_div_min) = 100; - ACCESS_FBINFO(features.pll.feed_div_max) = 127; - ACCESS_FBINFO(features.pll.in_div_min) = 1; - ACCESS_FBINFO(features.pll.in_div_max) = 31; - ACCESS_FBINFO(features.pll.post_shift_max) = 3; - ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_EXTERNAL; + /* minfo->features.DAC1064.vco_freq_min = 120000; */ + minfo->features.pll.vco_freq_min = 62000; + minfo->features.pll.ref_freq = 14318; + minfo->features.pll.feed_div_min = 100; + minfo->features.pll.feed_div_max = 127; + minfo->features.pll.in_div_min = 1; + minfo->features.pll.in_div_max = 31; + minfo->features.pll.post_shift_max = 3; + minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_EXTERNAL; /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */ - DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333); + DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333); } #endif @@ -589,23 +606,25 @@ static int x7AF4 = 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */ static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */ #endif -static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) { +static void MGAG100_progPixClock(const struct matrox_fb_info *minfo, int flags, + int m, int n, int p) +{ int reg; int selClk; int clk; DBG(__func__) - outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS | + outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS | M1064_XPIXCLKCTRL_PLL_UP); switch (flags & 3) { case 0: reg = M1064_XPIXPLLAM; break; case 1: reg = M1064_XPIXPLLBM; break; default: reg = M1064_XPIXPLLCM; break; } - outDAC1064(PMINFO reg++, m); - outDAC1064(PMINFO reg++, n); - outDAC1064(PMINFO reg, p); + outDAC1064(minfo, reg++, m); + outDAC1064(minfo, reg++, n); + outDAC1064(minfo, reg, p); selClk = mga_inb(M_MISC_REG_READ) & ~0xC; /* there should be flags & 0x03 & case 0/1/else */ /* and we should first select source and after that we should wait for PLL */ @@ -617,61 +636,64 @@ static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) { } mga_outb(M_MISC_REG, selClk); for (clk = 500000; clk; clk--) { - if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40) + if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40) break; udelay(10); }; if (!clk) printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A'); - selClk = inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK; + selClk = inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK; switch (flags & 0x0C) { case 0x00: selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break; case 0x04: selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break; default: selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break; } - outDAC1064(PMINFO M1064_XPIXCLKCTRL, selClk); - outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS); + outDAC1064(minfo, M1064_XPIXCLKCTRL, selClk); + outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS); } -static void MGAG100_setPixClock(CPMINFO int flags, int freq) { +static void MGAG100_setPixClock(const struct matrox_fb_info *minfo, int flags, + int freq) +{ unsigned int m, n, p; DBG(__func__) - DAC1064_calcclock(PMINFO freq, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); - MGAG100_progPixClock(PMINFO flags, m, n, p); + DAC1064_calcclock(minfo, freq, minfo->max_pixel_clock, &m, &n, &p); + MGAG100_progPixClock(minfo, flags, m, n, p); } #endif #ifdef CONFIG_FB_MATROX_MYSTIQUE -static int MGA1064_preinit(WPMINFO2) { +static int MGA1064_preinit(struct matrox_fb_info *minfo) +{ static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) - /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ - ACCESS_FBINFO(capable.text) = 1; - ACCESS_FBINFO(capable.vxres) = vxres_mystique; + /* minfo->capable.cfb4 = 0; ... preinitialized by 0 */ + minfo->capable.text = 1; + minfo->capable.vxres = vxres_mystique; - ACCESS_FBINFO(outputs[0]).output = &m1064; - ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; - ACCESS_FBINFO(outputs[0]).data = MINFO; - ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; + minfo->outputs[0].output = &m1064; + minfo->outputs[0].src = minfo->outputs[0].default_src; + minfo->outputs[0].data = minfo; + minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR; - if (ACCESS_FBINFO(devflags.noinit)) + if (minfo->devflags.noinit) return 0; /* do not modify settings */ hw->MXoptionReg &= 0xC0000100; hw->MXoptionReg |= 0x00094E20; - if (ACCESS_FBINFO(devflags.novga)) + if (minfo->devflags.novga) hw->MXoptionReg &= ~0x00000100; - if (ACCESS_FBINFO(devflags.nobios)) + if (minfo->devflags.nobios) hw->MXoptionReg &= ~0x40000000; - if (ACCESS_FBINFO(devflags.nopciretry)) + if (minfo->devflags.nopciretry) hw->MXoptionReg |= 0x20000000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); mga_setr(M_SEQ_INDEX, 0x01, 0x20); mga_outl(M_CTLWTST, 0x00000000); udelay(200); @@ -681,101 +703,105 @@ static int MGA1064_preinit(WPMINFO2) { return 0; } -static void MGA1064_reset(WPMINFO2) { +static void MGA1064_reset(struct matrox_fb_info *minfo) +{ DBG(__func__); - MGA1064_ramdac_init(PMINFO2); + MGA1064_ramdac_init(minfo); } #endif #ifdef CONFIG_FB_MATROX_G -static void g450_mclk_init(WPMINFO2) { +static void g450_mclk_init(struct matrox_fb_info *minfo) +{ /* switch all clocks to PCI source */ - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4); - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3 & ~0x00300C03); - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); - - if (((ACCESS_FBINFO(values).reg.opt3 & 0x000003) == 0x000003) || - ((ACCESS_FBINFO(values).reg.opt3 & 0x000C00) == 0x000C00) || - ((ACCESS_FBINFO(values).reg.opt3 & 0x300000) == 0x300000)) { - matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.video), M_VIDEO_PLL); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4); + pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3 & ~0x00300C03); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); + + if (((minfo->values.reg.opt3 & 0x000003) == 0x000003) || + ((minfo->values.reg.opt3 & 0x000C00) == 0x000C00) || + ((minfo->values.reg.opt3 & 0x300000) == 0x300000)) { + matroxfb_g450_setclk(minfo, minfo->values.pll.video, M_VIDEO_PLL); } else { unsigned long flags; unsigned int pwr; matroxfb_DAC_lock_irqsave(flags); - pwr = inDAC1064(PMINFO M1064_XPWRCTRL) & ~0x02; - outDAC1064(PMINFO M1064_XPWRCTRL, pwr); + pwr = inDAC1064(minfo, M1064_XPWRCTRL) & ~0x02; + outDAC1064(minfo, M1064_XPWRCTRL, pwr); matroxfb_DAC_unlock_irqrestore(flags); } - matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.system), M_SYSTEM_PLL); + matroxfb_g450_setclk(minfo, minfo->values.pll.system, M_SYSTEM_PLL); /* switch clocks to their real PLL source(s) */ - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4); - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3); - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4); + pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); } -static void g450_memory_init(WPMINFO2) { +static void g450_memory_init(struct matrox_fb_info *minfo) +{ /* disable memory refresh */ - ACCESS_FBINFO(hw).MXoptionReg &= ~0x001F8000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + minfo->hw.MXoptionReg &= ~0x001F8000; + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); /* set memory interface parameters */ - ACCESS_FBINFO(hw).MXoptionReg &= ~0x00207E00; - ACCESS_FBINFO(hw).MXoptionReg |= 0x00207E00 & ACCESS_FBINFO(values).reg.opt; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ACCESS_FBINFO(values).reg.opt2); + minfo->hw.MXoptionReg &= ~0x00207E00; + minfo->hw.MXoptionReg |= 0x00207E00 & minfo->values.reg.opt; + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); + pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, minfo->values.reg.opt2); - mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); + mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst); /* first set up memory interface with disabled memory interface clocks */ - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc & ~0x80000000U); - mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); - mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess); + pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc & ~0x80000000U); + mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk); + mga_outl(M_MACCESS, minfo->values.reg.maccess); /* start memory clocks */ - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc | 0x80000000U); + pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc | 0x80000000U); udelay(200); - if (ACCESS_FBINFO(values).memory.ddr && (!ACCESS_FBINFO(values).memory.emrswen || !ACCESS_FBINFO(values).memory.dll)) { - mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk & ~0x1000); + if (minfo->values.memory.ddr && (!minfo->values.memory.emrswen || !minfo->values.memory.dll)) { + mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk & ~0x1000); } - mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess | 0x8000); + mga_outl(M_MACCESS, minfo->values.reg.maccess | 0x8000); udelay(200); - ACCESS_FBINFO(hw).MXoptionReg |= 0x001F8000 & ACCESS_FBINFO(values).reg.opt; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + minfo->hw.MXoptionReg |= 0x001F8000 & minfo->values.reg.opt; + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); /* value is written to memory chips only if old != new */ mga_outl(M_PLNWT, 0); mga_outl(M_PLNWT, ~0); - if (ACCESS_FBINFO(values).reg.mctlwtst != ACCESS_FBINFO(values).reg.mctlwtst_core) { - mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst_core); + if (minfo->values.reg.mctlwtst != minfo->values.reg.mctlwtst_core) { + mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst_core); } } -static void g450_preinit(WPMINFO2) { +static void g450_preinit(struct matrox_fb_info *minfo) +{ u_int32_t c2ctl; u_int8_t curctl; u_int8_t c1ctl; - /* ACCESS_FBINFO(hw).MXoptionReg = minfo->values.reg.opt; */ - ACCESS_FBINFO(hw).MXoptionReg &= 0xC0000100; - ACCESS_FBINFO(hw).MXoptionReg |= 0x00000020; - if (ACCESS_FBINFO(devflags.novga)) - ACCESS_FBINFO(hw).MXoptionReg &= ~0x00000100; - if (ACCESS_FBINFO(devflags.nobios)) - ACCESS_FBINFO(hw).MXoptionReg &= ~0x40000000; - if (ACCESS_FBINFO(devflags.nopciretry)) - ACCESS_FBINFO(hw).MXoptionReg |= 0x20000000; - ACCESS_FBINFO(hw).MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x03400040; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + /* minfo->hw.MXoptionReg = minfo->values.reg.opt; */ + minfo->hw.MXoptionReg &= 0xC0000100; + minfo->hw.MXoptionReg |= 0x00000020; + if (minfo->devflags.novga) + minfo->hw.MXoptionReg &= ~0x00000100; + if (minfo->devflags.nobios) + minfo->hw.MXoptionReg &= ~0x40000000; + if (minfo->devflags.nopciretry) + minfo->hw.MXoptionReg |= 0x20000000; + minfo->hw.MXoptionReg |= minfo->values.reg.opt & 0x03400040; + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); /* Init system clocks */ @@ -783,24 +809,24 @@ static void g450_preinit(WPMINFO2) { c2ctl = mga_inl(M_C2CTL); mga_outl(M_C2CTL, c2ctl & ~1); /* stop cursor */ - curctl = inDAC1064(PMINFO M1064_XCURCTRL); - outDAC1064(PMINFO M1064_XCURCTRL, 0); + curctl = inDAC1064(minfo, M1064_XCURCTRL); + outDAC1064(minfo, M1064_XCURCTRL, 0); /* stop crtc1 */ c1ctl = mga_readr(M_SEQ_INDEX, 1); mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20); - g450_mclk_init(PMINFO2); - g450_memory_init(PMINFO2); + g450_mclk_init(minfo); + g450_memory_init(minfo); /* set legacy VGA clock sources for DOSEmu or VMware... */ - matroxfb_g450_setclk(PMINFO 25175, M_PIXEL_PLL_A); - matroxfb_g450_setclk(PMINFO 28322, M_PIXEL_PLL_B); + matroxfb_g450_setclk(minfo, 25175, M_PIXEL_PLL_A); + matroxfb_g450_setclk(minfo, 28322, M_PIXEL_PLL_B); /* restore crtc1 */ mga_setr(M_SEQ_INDEX, 1, c1ctl); /* restore cursor */ - outDAC1064(PMINFO M1064_XCURCTRL, curctl); + outDAC1064(minfo, M1064_XCURCTRL, curctl); /* restore crtc2 */ mga_outl(M_C2CTL, c2ctl); @@ -808,11 +834,12 @@ static void g450_preinit(WPMINFO2) { return; } -static int MGAG100_preinit(WPMINFO2) { +static int MGAG100_preinit(struct matrox_fb_info *minfo) +{ static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; u_int32_t reg50; #if 0 @@ -822,68 +849,68 @@ static int MGAG100_preinit(WPMINFO2) { DBG(__func__) /* there are some instabilities if in_div > 19 && vco < 61000 */ - if (ACCESS_FBINFO(devflags.g450dac)) { - ACCESS_FBINFO(features.pll.vco_freq_min) = 130000; /* my sample: >118 */ + if (minfo->devflags.g450dac) { + minfo->features.pll.vco_freq_min = 130000; /* my sample: >118 */ } else { - ACCESS_FBINFO(features.pll.vco_freq_min) = 62000; + minfo->features.pll.vco_freq_min = 62000; } - if (!ACCESS_FBINFO(features.pll.ref_freq)) { - ACCESS_FBINFO(features.pll.ref_freq) = 27000; + if (!minfo->features.pll.ref_freq) { + minfo->features.pll.ref_freq = 27000; } - ACCESS_FBINFO(features.pll.feed_div_min) = 7; - ACCESS_FBINFO(features.pll.feed_div_max) = 127; - ACCESS_FBINFO(features.pll.in_div_min) = 1; - ACCESS_FBINFO(features.pll.in_div_max) = 31; - ACCESS_FBINFO(features.pll.post_shift_max) = 3; - ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_G100_DEFAULT; - /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ - ACCESS_FBINFO(capable.text) = 1; - ACCESS_FBINFO(capable.vxres) = vxres_g100; - ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100 - ? ACCESS_FBINFO(devflags.sgram) : 1; + minfo->features.pll.feed_div_min = 7; + minfo->features.pll.feed_div_max = 127; + minfo->features.pll.in_div_min = 1; + minfo->features.pll.in_div_max = 31; + minfo->features.pll.post_shift_max = 3; + minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_G100_DEFAULT; + /* minfo->capable.cfb4 = 0; ... preinitialized by 0 */ + minfo->capable.text = 1; + minfo->capable.vxres = vxres_g100; + minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100 + ? minfo->devflags.sgram : 1; #ifdef CONFIG_FB_MATROX_G - if (ACCESS_FBINFO(devflags.g450dac)) { - ACCESS_FBINFO(outputs[0]).output = &g450out; + if (minfo->devflags.g450dac) { + minfo->outputs[0].output = &g450out; } else #endif { - ACCESS_FBINFO(outputs[0]).output = &m1064; + minfo->outputs[0].output = &m1064; } - ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; - ACCESS_FBINFO(outputs[0]).data = MINFO; - ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; + minfo->outputs[0].src = minfo->outputs[0].default_src; + minfo->outputs[0].data = minfo; + minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR; - if (ACCESS_FBINFO(devflags.g450dac)) { + if (minfo->devflags.g450dac) { /* we must do this always, BIOS does not do it for us and accelerator dies without it */ mga_outl(0x1C0C, 0); } - if (ACCESS_FBINFO(devflags.noinit)) + if (minfo->devflags.noinit) return 0; - if (ACCESS_FBINFO(devflags.g450dac)) { - g450_preinit(PMINFO2); + if (minfo->devflags.g450dac) { + g450_preinit(minfo); return 0; } hw->MXoptionReg &= 0xC0000100; hw->MXoptionReg |= 0x00000020; - if (ACCESS_FBINFO(devflags.novga)) + if (minfo->devflags.novga) hw->MXoptionReg &= ~0x00000100; - if (ACCESS_FBINFO(devflags.nobios)) + if (minfo->devflags.nobios) hw->MXoptionReg &= ~0x40000000; - if (ACCESS_FBINFO(devflags.nopciretry)) + if (minfo->devflags.nopciretry) hw->MXoptionReg |= 0x20000000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); - DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); + DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333); - if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) { - pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50); + if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100) { + pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, ®50); reg50 &= ~0x3000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); + pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50); hw->MXoptionReg |= 0x1080; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); - mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); + mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst); udelay(100); mga_outb(0x1C05, 0x00); mga_outb(0x1C05, 0x80); @@ -893,68 +920,69 @@ static int MGAG100_preinit(WPMINFO2) { udelay(100); reg50 &= ~0xFF; reg50 |= 0x07; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); + pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50); /* it should help with G100 */ mga_outb(M_GRAPHICS_INDEX, 6); mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4); mga_setr(M_EXTVGA_INDEX, 0x03, 0x81); mga_setr(M_EXTVGA_INDEX, 0x04, 0x00); - mga_writeb(ACCESS_FBINFO(video.vbase), 0x0000, 0xAA); - mga_writeb(ACCESS_FBINFO(video.vbase), 0x0800, 0x55); - mga_writeb(ACCESS_FBINFO(video.vbase), 0x4000, 0x55); + mga_writeb(minfo->video.vbase, 0x0000, 0xAA); + mga_writeb(minfo->video.vbase, 0x0800, 0x55); + mga_writeb(minfo->video.vbase, 0x4000, 0x55); #if 0 - if (mga_readb(ACCESS_FBINFO(video.vbase), 0x0000) != 0xAA) { + if (mga_readb(minfo->video.vbase, 0x0000) != 0xAA) { hw->MXoptionReg &= ~0x1000; } #endif hw->MXoptionReg |= 0x00078020; - } else if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG200) { - pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50); + } else if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG200) { + pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, ®50); reg50 &= ~0x3000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); + pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50); - if (ACCESS_FBINFO(devflags.memtype) == -1) - hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00; + if (minfo->devflags.memtype == -1) + hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00; else - hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10; - if (ACCESS_FBINFO(devflags.sgram)) + hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10; + if (minfo->devflags.sgram) hw->MXoptionReg |= 0x4000; - mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); - mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); + mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst); + mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk); udelay(200); mga_outl(M_MACCESS, 0x00000000); mga_outl(M_MACCESS, 0x00008000); udelay(100); - mga_outw(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); + mga_outw(M_MEMRDBK, minfo->values.reg.memrdbk); hw->MXoptionReg |= 0x00078020; } else { - pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50); + pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, ®50); reg50 &= ~0x00000100; reg50 |= 0x00000000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); + pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50); - if (ACCESS_FBINFO(devflags.memtype) == -1) - hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00; + if (minfo->devflags.memtype == -1) + hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00; else - hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10; - if (ACCESS_FBINFO(devflags.sgram)) + hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10; + if (minfo->devflags.sgram) hw->MXoptionReg |= 0x4000; - mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); - mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); + mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst); + mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk); udelay(200); mga_outl(M_MACCESS, 0x00000000); mga_outl(M_MACCESS, 0x00008000); udelay(100); - mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); + mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk); hw->MXoptionReg |= 0x00040020; } - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); return 0; } -static void MGAG100_reset(WPMINFO2) { +static void MGAG100_reset(struct matrox_fb_info *minfo) +{ u_int8_t b; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) @@ -964,54 +992,55 @@ static void MGAG100_reset(WPMINFO2) { find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */ pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b); - if (b == ACCESS_FBINFO(pcidev)->bus->number) { + if (b == minfo->pcidev->bus->number) { pci_write_config_byte(ibm, PCI_COMMAND+1, 0); /* disable back-to-back & SERR */ pci_write_config_byte(ibm, 0x41, 0xF4); /* ??? */ pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0); /* ??? */ pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00); /* ??? */ } #endif - if (!ACCESS_FBINFO(devflags.noinit)) { + if (!minfo->devflags.noinit) { if (x7AF4 & 8) { hw->MXoptionReg |= 0x40; /* FIXME... */ - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); } mga_setr(M_EXTVGA_INDEX, 0x06, 0x00); } } - if (ACCESS_FBINFO(devflags.g450dac)) { + if (minfo->devflags.g450dac) { /* either leave MCLK as is... or they were set in preinit */ - hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM); - hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN); - hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP); + hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM); + hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN); + hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP); } else { - DAC1064_setmclk(PMINFO DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333); + DAC1064_setmclk(minfo, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333); } - if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) { - if (ACCESS_FBINFO(devflags.dfp_type) == -1) { - ACCESS_FBINFO(devflags.dfp_type) = inDAC1064(PMINFO 0x1F); + if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) { + if (minfo->devflags.dfp_type == -1) { + minfo->devflags.dfp_type = inDAC1064(minfo, 0x1F); } } - if (ACCESS_FBINFO(devflags.noinit)) + if (minfo->devflags.noinit) return; - if (ACCESS_FBINFO(devflags.g450dac)) { + if (minfo->devflags.g450dac) { } else { - MGAG100_setPixClock(PMINFO 4, 25175); - MGAG100_setPixClock(PMINFO 5, 28322); + MGAG100_setPixClock(minfo, 4, 25175); + MGAG100_setPixClock(minfo, 5, 28322); if (x7AF4 & 0x10) { - b = inDAC1064(PMINFO M1064_XGENIODATA) & ~1; - outDAC1064(PMINFO M1064_XGENIODATA, b); - b = inDAC1064(PMINFO M1064_XGENIOCTRL) | 1; - outDAC1064(PMINFO M1064_XGENIOCTRL, b); + b = inDAC1064(minfo, M1064_XGENIODATA) & ~1; + outDAC1064(minfo, M1064_XGENIODATA, b); + b = inDAC1064(minfo, M1064_XGENIOCTRL) | 1; + outDAC1064(minfo, M1064_XGENIOCTRL, b); } } } #endif #ifdef CONFIG_FB_MATROX_MYSTIQUE -static void MGA1064_restore(WPMINFO2) { +static void MGA1064_restore(struct matrox_fb_info *minfo) +{ int i; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; CRITFLAGS @@ -1019,25 +1048,26 @@ static void MGA1064_restore(WPMINFO2) { CRITBEGIN - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); mga_outb(M_IEN, 0x00); mga_outb(M_CACHEFLUSH, 0x00); CRITEND - DAC1064_restore_1(PMINFO2); - matroxfb_vgaHWrestore(PMINFO2); - ACCESS_FBINFO(crtc1.panpos) = -1; + DAC1064_restore_1(minfo); + matroxfb_vgaHWrestore(minfo); + minfo->crtc1.panpos = -1; for (i = 0; i < 6; i++) mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); - DAC1064_restore_2(PMINFO2); + DAC1064_restore_2(minfo); } #endif #ifdef CONFIG_FB_MATROX_G -static void MGAG100_restore(WPMINFO2) { +static void MGAG100_restore(struct matrox_fb_info *minfo) +{ int i; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; CRITFLAGS @@ -1045,19 +1075,17 @@ static void MGAG100_restore(WPMINFO2) { CRITBEGIN - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); CRITEND - DAC1064_restore_1(PMINFO2); - matroxfb_vgaHWrestore(PMINFO2); -#ifdef CONFIG_FB_MATROX_32MB - if (ACCESS_FBINFO(devflags.support32MB)) + DAC1064_restore_1(minfo); + matroxfb_vgaHWrestore(minfo); + if (minfo->devflags.support32MB) mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]); -#endif - ACCESS_FBINFO(crtc1.panpos) = -1; + minfo->crtc1.panpos = -1; for (i = 0; i < 6; i++) mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); - DAC1064_restore_2(PMINFO2); + DAC1064_restore_2(minfo); } #endif diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h index 7a98ce8043d7..c6ed7801efe2 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.h +++ b/drivers/video/matrox/matroxfb_DAC1064.h @@ -11,8 +11,8 @@ extern struct matrox_switch matrox_mystique; extern struct matrox_switch matrox_G100; #endif #ifdef NEED_DAC1064 -void DAC1064_global_init(WPMINFO2); -void DAC1064_global_restore(WPMINFO2); +void DAC1064_global_init(struct matrox_fb_info *minfo); +void DAC1064_global_restore(struct matrox_fb_info *minfo); #endif #define M1064_INDEX 0x00 diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index 4e825112a601..835aaaae6b96 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c @@ -279,27 +279,31 @@ static const unsigned char MGADACbpp32[] = TVP3026_XCOLKEYCTRL_ZOOM1, 0x00, 0x00, TVP3026_XCURCTRL_DIS }; -static int Ti3026_calcclock(CPMINFO unsigned int freq, unsigned int fmax, int* in, int* feed, int* post) { +static int Ti3026_calcclock(const struct matrox_fb_info *minfo, + unsigned int freq, unsigned int fmax, int *in, + int *feed, int *post) +{ unsigned int fvco; unsigned int lin, lfeed, lpost; DBG(__func__) - fvco = PLL_calcclock(PMINFO freq, fmax, &lin, &lfeed, &lpost); + fvco = PLL_calcclock(minfo, freq, fmax, &lin, &lfeed, &lpost); fvco >>= (*post = lpost); *in = 64 - lin; *feed = 64 - lfeed; return fvco; } -static int Ti3026_setpclk(WPMINFO int clk) { +static int Ti3026_setpclk(struct matrox_fb_info *minfo, int clk) +{ unsigned int f_pll; unsigned int pixfeed, pixin, pixpost; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) - f_pll = Ti3026_calcclock(PMINFO clk, ACCESS_FBINFO(max_pixel_clock), &pixin, &pixfeed, &pixpost); + f_pll = Ti3026_calcclock(minfo, clk, minfo->max_pixel_clock, &pixin, &pixfeed, &pixpost); hw->DACclk[0] = pixin | 0xC0; hw->DACclk[1] = pixfeed; @@ -309,9 +313,9 @@ static int Ti3026_setpclk(WPMINFO int clk) { unsigned int loopfeed, loopin, looppost, loopdiv, z; unsigned int Bpp; - Bpp = ACCESS_FBINFO(curr.final_bppShift); + Bpp = minfo->curr.final_bppShift; - if (ACCESS_FBINFO(fbcon).var.bits_per_pixel == 24) { + if (minfo->fbcon.var.bits_per_pixel == 24) { loopfeed = 3; /* set lm to any possible value */ loopin = 3 * 32 / Bpp; } else { @@ -330,18 +334,18 @@ static int Ti3026_setpclk(WPMINFO int clk) { looppost = 3; loopdiv = z/16; } - if (ACCESS_FBINFO(fbcon).var.bits_per_pixel == 24) { + if (minfo->fbcon.var.bits_per_pixel == 24) { hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0; hw->DACclk[4] = (65 - loopfeed) | 0x80; - if (ACCESS_FBINFO(accel.ramdac_rev) > 0x20) { - if (isInterleave(MINFO)) + if (minfo->accel.ramdac_rev > 0x20) { + if (isInterleave(minfo)) hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3; else { hw->DACclk[4] &= ~0xC0; hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3; } } else { - if (isInterleave(MINFO)) + if (isInterleave(minfo)) ; /* default... */ else { hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */ @@ -349,7 +353,7 @@ static int Ti3026_setpclk(WPMINFO int clk) { } } hw->DACclk[5] = looppost | 0xF8; - if (ACCESS_FBINFO(devflags.mga_24bpp_fix)) + if (minfo->devflags.mga_24bpp_fix) hw->DACclk[5] ^= 0x40; } else { hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0; @@ -361,14 +365,15 @@ static int Ti3026_setpclk(WPMINFO int clk) { return 0; } -static int Ti3026_init(WPMINFO struct my_timming* m) { - u_int8_t muxctrl = isInterleave(MINFO) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); +static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m) +{ + u_int8_t muxctrl = isInterleave(minfo) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT; + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg)); - switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { + switch (minfo->fbcon.var.bits_per_pixel) { case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */ hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR; hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT; @@ -383,7 +388,7 @@ static int Ti3026_init(WPMINFO struct my_timming* m) { break; case 16: /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used everytime) */ - hw->DACreg[POS3026_XTRUECOLORCTRL] = (ACCESS_FBINFO(fbcon).var.green.length == 5)? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555 ) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565); + hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565); hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT; hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2; break; @@ -400,7 +405,7 @@ static int Ti3026_init(WPMINFO struct my_timming* m) { default: return 1; /* TODO: failed */ } - if (matroxfb_vgaHWinit(PMINFO m)) return 1; + if (matroxfb_vgaHWinit(minfo, m)) return 1; /* set SYNC */ hw->MiscOutReg = 0xCB; @@ -412,9 +417,9 @@ static int Ti3026_init(WPMINFO struct my_timming* m) { hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN; /* set DELAY */ - if (ACCESS_FBINFO(video.len) < 0x400000) + if (minfo->video.len < 0x400000) hw->CRTCEXT[3] |= 0x08; - else if (ACCESS_FBINFO(video.len) > 0x400000) + else if (minfo->video.len > 0x400000) hw->CRTCEXT[3] |= 0x10; /* set HWCURSOR */ @@ -426,14 +431,15 @@ static int Ti3026_init(WPMINFO struct my_timming* m) { /* set interleaving */ hw->MXoptionReg &= ~0x00001000; - if (isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000; + if (isInterleave(minfo)) hw->MXoptionReg |= 0x00001000; /* set DAC */ - Ti3026_setpclk(PMINFO m->pixclock); + Ti3026_setpclk(minfo, m->pixclock); return 0; } -static void ti3026_setMCLK(WPMINFO int fout){ +static void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout) +{ unsigned int f_pll; unsigned int pclk_m, pclk_n, pclk_p; unsigned int mclk_m, mclk_n, mclk_p; @@ -442,29 +448,29 @@ static void ti3026_setMCLK(WPMINFO int fout){ DBG(__func__) - f_pll = Ti3026_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &mclk_n, &mclk_m, &mclk_p); + f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p); /* save pclk */ - outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC); - pclk_n = inTi3026(PMINFO TVP3026_XPIXPLLDATA); - outTi3026(PMINFO TVP3026_XPLLADDR, 0xFD); - pclk_m = inTi3026(PMINFO TVP3026_XPIXPLLDATA); - outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE); - pclk_p = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + outTi3026(minfo, TVP3026_XPLLADDR, 0xFC); + pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA); + outTi3026(minfo, TVP3026_XPLLADDR, 0xFD); + pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA); + outTi3026(minfo, TVP3026_XPLLADDR, 0xFE); + pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA); /* stop pclk */ - outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00); + outTi3026(minfo, TVP3026_XPLLADDR, 0xFE); + outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00); /* set pclk to new mclk */ - outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_n | 0xC0); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_m); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_p | 0xB0); + outTi3026(minfo, TVP3026_XPLLADDR, 0xFC); + outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0); + outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m); + outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0); /* wait for PLL to lock */ for (tmout = 500000; tmout; tmout--) { - if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40) + if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) break; udelay(10); }; @@ -472,23 +478,23 @@ static void ti3026_setMCLK(WPMINFO int fout){ printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n"); /* output pclk on mclk pin */ - mclk_ctl = inTi3026(PMINFO TVP3026_XMEMPLLCTRL); - outTi3026(PMINFO TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7); - outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4); + mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL); + outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7); + outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4); /* stop MCLK */ - outTi3026(PMINFO TVP3026_XPLLADDR, 0xFB); - outTi3026(PMINFO TVP3026_XMEMPLLDATA, 0x00); + outTi3026(minfo, TVP3026_XPLLADDR, 0xFB); + outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00); /* set mclk to new freq */ - outTi3026(PMINFO TVP3026_XPLLADDR, 0xF3); - outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_n | 0xC0); - outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_m); - outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_p | 0xB0); + outTi3026(minfo, TVP3026_XPLLADDR, 0xF3); + outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0); + outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m); + outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0); /* wait for PLL to lock */ for (tmout = 500000; tmout; tmout--) { - if (inTi3026(PMINFO TVP3026_XMEMPLLDATA) & 0x40) + if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40) break; udelay(10); } @@ -496,7 +502,7 @@ static void ti3026_setMCLK(WPMINFO int fout){ printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n"); f_pll = f_pll * 333 / (10000 << mclk_p); - if (isMilleniumII(MINFO)) { + if (isMilleniumII(minfo)) { rfhcnt = (f_pll - 128) / 256; if (rfhcnt > 15) rfhcnt = 15; @@ -505,26 +511,26 @@ static void ti3026_setMCLK(WPMINFO int fout){ if (rfhcnt > 15) rfhcnt = 0; } - ACCESS_FBINFO(hw).MXoptionReg = (ACCESS_FBINFO(hw).MXoptionReg & ~0x000F0000) | (rfhcnt << 16); - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); /* output MCLK to MCLK pin */ - outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); - outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4); + outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); + outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4); /* stop PCLK */ - outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00); + outTi3026(minfo, TVP3026_XPLLADDR, 0xFE); + outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00); /* restore pclk */ - outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_n); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_m); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_p); + outTi3026(minfo, TVP3026_XPLLADDR, 0xFC); + outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n); + outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m); + outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p); /* wait for PLL to lock */ for (tmout = 500000; tmout; tmout--) { - if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40) + if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) break; udelay(10); } @@ -532,26 +538,27 @@ static void ti3026_setMCLK(WPMINFO int fout){ printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); } -static void ti3026_ramdac_init(WPMINFO2) { - +static void ti3026_ramdac_init(struct matrox_fb_info *minfo) +{ DBG(__func__) - ACCESS_FBINFO(features.pll.vco_freq_min) = 110000; - ACCESS_FBINFO(features.pll.ref_freq) = 114545; - ACCESS_FBINFO(features.pll.feed_div_min) = 2; - ACCESS_FBINFO(features.pll.feed_div_max) = 24; - ACCESS_FBINFO(features.pll.in_div_min) = 2; - ACCESS_FBINFO(features.pll.in_div_max) = 63; - ACCESS_FBINFO(features.pll.post_shift_max) = 3; - if (ACCESS_FBINFO(devflags.noinit)) + minfo->features.pll.vco_freq_min = 110000; + minfo->features.pll.ref_freq = 114545; + minfo->features.pll.feed_div_min = 2; + minfo->features.pll.feed_div_max = 24; + minfo->features.pll.in_div_min = 2; + minfo->features.pll.in_div_max = 63; + minfo->features.pll.post_shift_max = 3; + if (minfo->devflags.noinit) return; - ti3026_setMCLK(PMINFO 60000); + ti3026_setMCLK(minfo, 60000); } -static void Ti3026_restore(WPMINFO2) { +static void Ti3026_restore(struct matrox_fb_info *minfo) +{ int i; unsigned char progdac[6]; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; CRITFLAGS DBG(__func__) @@ -565,31 +572,31 @@ static void Ti3026_restore(WPMINFO2) { CRITBEGIN - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); CRITEND - matroxfb_vgaHWrestore(PMINFO2); + matroxfb_vgaHWrestore(minfo); CRITBEGIN - ACCESS_FBINFO(crtc1.panpos) = -1; + minfo->crtc1.panpos = -1; for (i = 0; i < 6; i++) mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); for (i = 0; i < 21; i++) { - outTi3026(PMINFO DACseq[i], hw->DACreg[i]); + outTi3026(minfo, DACseq[i], hw->DACreg[i]); } - outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); - progdac[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); - progdac[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); - outTi3026(PMINFO TVP3026_XPLLADDR, 0x15); - progdac[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); - progdac[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); - outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); - progdac[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); - progdac[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + outTi3026(minfo, TVP3026_XPLLADDR, 0x00); + progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA); + progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA); + outTi3026(minfo, TVP3026_XPLLADDR, 0x15); + progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA); + progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA); + outTi3026(minfo, TVP3026_XPLLADDR, 0x2A); + progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA); + progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA); CRITEND if (memcmp(hw->DACclk, progdac, 6)) { @@ -598,20 +605,20 @@ static void Ti3026_restore(WPMINFO2) { /* Maybe even we should call schedule() ? */ CRITBEGIN - outTi3026(PMINFO TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]); - outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); - outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0); + outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]); + outTi3026(minfo, TVP3026_XPLLADDR, 0x2A); + outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0); + outTi3026(minfo, TVP3026_XPIXPLLDATA, 0); - outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); + outTi3026(minfo, TVP3026_XPLLADDR, 0x00); for (i = 0; i < 3; i++) - outTi3026(PMINFO TVP3026_XPIXPLLDATA, hw->DACclk[i]); + outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]); /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */ if (hw->MiscOutReg & 0x08) { int tmout; - outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F); + outTi3026(minfo, TVP3026_XPLLADDR, 0x3F); for (tmout = 500000; tmout; --tmout) { - if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40) + if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) break; udelay(10); } @@ -624,18 +631,18 @@ static void Ti3026_restore(WPMINFO2) { dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout); CRITBEGIN } - outTi3026(PMINFO TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]); - outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); + outTi3026(minfo, TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]); + outTi3026(minfo, TVP3026_XPLLADDR, 0x00); for (i = 3; i < 6; i++) - outTi3026(PMINFO TVP3026_XLOOPPLLDATA, hw->DACclk[i]); + outTi3026(minfo, TVP3026_XLOOPPLLDATA, hw->DACclk[i]); CRITEND if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) { int tmout; CRITBEGIN - outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F); + outTi3026(minfo, TVP3026_XPLLADDR, 0x3F); for (tmout = 500000; tmout; --tmout) { - if (inTi3026(PMINFO TVP3026_XLOOPPLLDATA) & 0x40) + if (inTi3026(minfo, TVP3026_XLOOPPLLDATA) & 0x40) break; udelay(10); } @@ -660,65 +667,66 @@ static void Ti3026_restore(WPMINFO2) { #endif } -static void Ti3026_reset(WPMINFO2) { - +static void Ti3026_reset(struct matrox_fb_info *minfo) +{ DBG(__func__) - ti3026_ramdac_init(PMINFO2); + ti3026_ramdac_init(minfo); } static struct matrox_altout ti3026_output = { .name = "Primary output", }; -static int Ti3026_preinit(WPMINFO2) { +static int Ti3026_preinit(struct matrox_fb_info *minfo) +{ static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; static const int vxres_mill1[] = { 640, 768, 800, 960, 1024, 1152, 1280, 1600, 1920, 2048, 0}; - struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state *hw = &minfo->hw; DBG(__func__) - ACCESS_FBINFO(millenium) = 1; - ACCESS_FBINFO(milleniumII) = (ACCESS_FBINFO(pcidev)->device != PCI_DEVICE_ID_MATROX_MIL); - ACCESS_FBINFO(capable.cfb4) = 1; - ACCESS_FBINFO(capable.text) = 1; /* isMilleniumII(MINFO); */ - ACCESS_FBINFO(capable.vxres) = isMilleniumII(MINFO)?vxres_mill2:vxres_mill1; + minfo->millenium = 1; + minfo->milleniumII = (minfo->pcidev->device != PCI_DEVICE_ID_MATROX_MIL); + minfo->capable.cfb4 = 1; + minfo->capable.text = 1; /* isMilleniumII(minfo); */ + minfo->capable.vxres = isMilleniumII(minfo) ? vxres_mill2 : vxres_mill1; - ACCESS_FBINFO(outputs[0]).data = MINFO; - ACCESS_FBINFO(outputs[0]).output = &ti3026_output; - ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; - ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; + minfo->outputs[0].data = minfo; + minfo->outputs[0].output = &ti3026_output; + minfo->outputs[0].src = minfo->outputs[0].default_src; + minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR; - if (ACCESS_FBINFO(devflags.noinit)) + if (minfo->devflags.noinit) return 0; /* preserve VGA I/O, BIOS and PPC */ hw->MXoptionReg &= 0xC0000100; hw->MXoptionReg |= 0x002C0000; - if (ACCESS_FBINFO(devflags.novga)) + if (minfo->devflags.novga) hw->MXoptionReg &= ~0x00000100; - if (ACCESS_FBINFO(devflags.nobios)) + if (minfo->devflags.nobios) hw->MXoptionReg &= ~0x40000000; - if (ACCESS_FBINFO(devflags.nopciretry)) + if (minfo->devflags.nopciretry) hw->MXoptionReg |= 0x20000000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); - ACCESS_FBINFO(accel.ramdac_rev) = inTi3026(PMINFO TVP3026_XSILICONREV); + minfo->accel.ramdac_rev = inTi3026(minfo, TVP3026_XSILICONREV); - outTi3026(PMINFO TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED); - outTi3026(PMINFO TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR); - outTi3026(PMINFO TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA); + outTi3026(minfo, TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED); + outTi3026(minfo, TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR); + outTi3026(minfo, TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA); - outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); - outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0x00); - outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00); + outTi3026(minfo, TVP3026_XPLLADDR, 0x2A); + outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0x00); + outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00); mga_outb(M_MISC_REG, 0x67); - outTi3026(PMINFO TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); + outTi3026(minfo, TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); mga_outl(M_RESET, 1); udelay(250); diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c index 9c3aeee1cc4f..8335a6fe303e 100644 --- a/drivers/video/matrox/matroxfb_accel.c +++ b/drivers/video/matrox/matroxfb_accel.c @@ -81,7 +81,7 @@ #include "matroxfb_Ti3026.h" #include "matroxfb_misc.h" -#define curr_ydstorg(x) ACCESS_FBINFO2(x, curr.ydstorg.pixels) +#define curr_ydstorg(x) ((x)->curr.ydstorg.pixels) #define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l)) @@ -107,7 +107,8 @@ static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* imag static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect); static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area); -void matrox_cfbX_init(WPMINFO2) { +void matrox_cfbX_init(struct matrox_fb_info *minfo) +{ u_int32_t maccess; u_int32_t mpitch; u_int32_t mopmode; @@ -115,59 +116,59 @@ void matrox_cfbX_init(WPMINFO2) { DBG(__func__) - mpitch = ACCESS_FBINFO(fbcon).var.xres_virtual; + mpitch = minfo->fbcon.var.xres_virtual; - ACCESS_FBINFO(fbops).fb_copyarea = cfb_copyarea; - ACCESS_FBINFO(fbops).fb_fillrect = cfb_fillrect; - ACCESS_FBINFO(fbops).fb_imageblit = cfb_imageblit; - ACCESS_FBINFO(fbops).fb_cursor = NULL; + minfo->fbops.fb_copyarea = cfb_copyarea; + minfo->fbops.fb_fillrect = cfb_fillrect; + minfo->fbops.fb_imageblit = cfb_imageblit; + minfo->fbops.fb_cursor = NULL; - accel = (ACCESS_FBINFO(fbcon).var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; + accel = (minfo->fbcon.var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; - switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { + switch (minfo->fbcon.var.bits_per_pixel) { case 4: maccess = 0x00000000; /* accelerate as 8bpp video */ mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */ mopmode = M_OPMODE_4BPP; - matrox_cfb4_pal(ACCESS_FBINFO(cmap)); + matrox_cfb4_pal(minfo->cmap); if (accel && !(mpitch & 1)) { - ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_cfb4_copyarea; - ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_cfb4_fillrect; + minfo->fbops.fb_copyarea = matroxfb_cfb4_copyarea; + minfo->fbops.fb_fillrect = matroxfb_cfb4_fillrect; } break; case 8: maccess = 0x00000000; mopmode = M_OPMODE_8BPP; - matrox_cfb8_pal(ACCESS_FBINFO(cmap)); + matrox_cfb8_pal(minfo->cmap); if (accel) { - ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; - ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; - ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; + minfo->fbops.fb_copyarea = matroxfb_copyarea; + minfo->fbops.fb_fillrect = matroxfb_fillrect; + minfo->fbops.fb_imageblit = matroxfb_imageblit; } break; - case 16: if (ACCESS_FBINFO(fbcon).var.green.length == 5) + case 16: if (minfo->fbcon.var.green.length == 5) maccess = 0xC0000001; else maccess = 0x40000001; mopmode = M_OPMODE_16BPP; if (accel) { - ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; - ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; - ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; + minfo->fbops.fb_copyarea = matroxfb_copyarea; + minfo->fbops.fb_fillrect = matroxfb_fillrect; + minfo->fbops.fb_imageblit = matroxfb_imageblit; } break; case 24: maccess = 0x00000003; mopmode = M_OPMODE_24BPP; if (accel) { - ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; - ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; - ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; + minfo->fbops.fb_copyarea = matroxfb_copyarea; + minfo->fbops.fb_fillrect = matroxfb_fillrect; + minfo->fbops.fb_imageblit = matroxfb_imageblit; } break; case 32: maccess = 0x00000002; mopmode = M_OPMODE_32BPP; if (accel) { - ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; - ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; - ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; + minfo->fbops.fb_copyarea = matroxfb_copyarea; + minfo->fbops.fb_fillrect = matroxfb_fillrect; + minfo->fbops.fb_imageblit = matroxfb_imageblit; } break; default: maccess = 0x00000000; @@ -176,10 +177,10 @@ void matrox_cfbX_init(WPMINFO2) { } mga_fifo(8); mga_outl(M_PITCH, mpitch); - mga_outl(M_YDSTORG, curr_ydstorg(MINFO)); - if (ACCESS_FBINFO(capable.plnwt)) + mga_outl(M_YDSTORG, curr_ydstorg(minfo)); + if (minfo->capable.plnwt) mga_outl(M_PLNWT, -1); - if (ACCESS_FBINFO(capable.srcorg)) { + if (minfo->capable.srcorg) { mga_outl(M_SRCORG, 0); mga_outl(M_DSTORG, 0); } @@ -188,14 +189,16 @@ void matrox_cfbX_init(WPMINFO2) { mga_outl(M_YTOP, 0); mga_outl(M_YBOT, 0x01FFFFFF); mga_outl(M_MACCESS, maccess); - ACCESS_FBINFO(accel.m_dwg_rect) = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO; - if (isMilleniumII(MINFO)) ACCESS_FBINFO(accel.m_dwg_rect) |= M_DWG_TRANSC; - ACCESS_FBINFO(accel.m_opmode) = mopmode; + minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO; + if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC; + minfo->accel.m_opmode = mopmode; } EXPORT_SYMBOL(matrox_cfbX_init); -static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx, int height, int width) { +static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy, + int sx, int dy, int dx, int height, int width) +{ int start, end; CRITFLAGS @@ -209,7 +212,7 @@ static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx M_DWG_BFCOL | M_DWG_REPLACE); mga_outl(M_AR5, vxres); width--; - start = sy*vxres+sx+curr_ydstorg(MINFO); + start = sy*vxres+sx+curr_ydstorg(minfo); end = start+width; } else { mga_fifo(3); @@ -217,7 +220,7 @@ static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx mga_outl(M_SGN, 5); mga_outl(M_AR5, -vxres); width--; - end = (sy+height-1)*vxres+sx+curr_ydstorg(MINFO); + end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo); start = end+width; dy += height-1; } @@ -231,7 +234,10 @@ static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx CRITEND } -static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, int dx, int height, int width) { +static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres, + int sy, int sx, int dy, int dx, int height, + int width) +{ int start, end; CRITFLAGS @@ -245,7 +251,7 @@ static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, in M_DWG_BFCOL | M_DWG_REPLACE); mga_outl(M_AR5, vxres); width--; - start = sy*vxres+sx+curr_ydstorg(MINFO); + start = sy*vxres+sx+curr_ydstorg(minfo); end = start+width; } else { mga_fifo(3); @@ -253,7 +259,7 @@ static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, in mga_outl(M_SGN, 5); mga_outl(M_AR5, -vxres); width--; - end = (sy+height-1)*vxres+sx+curr_ydstorg(MINFO); + end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo); start = end+width; dy += height-1; } @@ -269,22 +275,23 @@ static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, in } static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) { - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); if ((area->sx | area->dx | area->width) & 1) cfb_copyarea(info, area); else - matrox_accel_bmove_lin(PMINFO ACCESS_FBINFO(fbcon.var.xres_virtual) >> 1, area->sy, area->sx >> 1, area->dy, area->dx >> 1, area->height, area->width >> 1); + matrox_accel_bmove_lin(minfo, minfo->fbcon.var.xres_virtual >> 1, area->sy, area->sx >> 1, area->dy, area->dx >> 1, area->height, area->width >> 1); } static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) { - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); - matrox_accel_bmove(PMINFO ACCESS_FBINFO(fbcon.var.xres_virtual), area->sy, area->sx, area->dy, area->dx, area->height, area->width); + matrox_accel_bmove(minfo, minfo->fbcon.var.xres_virtual, area->sy, area->sx, area->dy, area->dx, area->height, area->width); } -static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int height, - int width) { +static void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color, + int sy, int sx, int height, int width) +{ CRITFLAGS DBG(__func__) @@ -292,7 +299,7 @@ static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int he CRITBEGIN mga_fifo(5); - mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE); + mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE); mga_outl(M_FCOL, color); mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); mga_ydstlen(sy, height); @@ -302,16 +309,18 @@ static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int he } static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); switch (rect->rop) { case ROP_COPY: - matroxfb_accel_clear(PMINFO ((u_int32_t*)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); + matroxfb_accel_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); break; } } -static void matroxfb_cfb4_clear(WPMINFO u_int32_t bgx, int sy, int sx, int height, int width) { +static void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx, + int sy, int sx, int height, int width) +{ int whattodo; CRITFLAGS @@ -333,16 +342,16 @@ static void matroxfb_cfb4_clear(WPMINFO u_int32_t bgx, int sy, int sx, int heigh sx >>= 1; if (width) { mga_fifo(5); - mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE2); + mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2); mga_outl(M_FCOL, bgx); mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); - mga_outl(M_YDST, sy * ACCESS_FBINFO(fbcon).var.xres_virtual >> 6); + mga_outl(M_YDST, sy * minfo->fbcon.var.xres_virtual >> 6); mga_outl(M_LEN | M_EXEC, height); WaitTillIdle(); } if (whattodo) { - u_int32_t step = ACCESS_FBINFO(fbcon).var.xres_virtual >> 1; - vaddr_t vbase = ACCESS_FBINFO(video.vbase); + u_int32_t step = minfo->fbcon.var.xres_virtual >> 1; + vaddr_t vbase = minfo->video.vbase; if (whattodo & 1) { unsigned int uaddr = sy * step + sx - 1; u_int32_t loop; @@ -367,17 +376,19 @@ static void matroxfb_cfb4_clear(WPMINFO u_int32_t bgx, int sy, int sx, int heigh } static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); switch (rect->rop) { case ROP_COPY: - matroxfb_cfb4_clear(PMINFO ((u_int32_t*)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); + matroxfb_cfb4_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); break; } } -static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx, - const u_int8_t* chardata, int width, int height, int yy, int xx) { +static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx, + u_int32_t bgx, const u_int8_t *chardata, + int width, int height, int yy, int xx) +{ u_int32_t step; u_int32_t ydstlen; u_int32_t xlen; @@ -412,7 +423,7 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx, mga_outl(M_FCOL, fgx); mga_outl(M_BCOL, bgx); fxbndry = ((xx + width - 1) << 16) | xx; - mmio = ACCESS_FBINFO(mmio.vbase); + mmio = minfo->mmio.vbase; mga_fifo(6); mga_writel(mmio, M_FXBNDRY, fxbndry); @@ -467,7 +478,7 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx, static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) { - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); DBG_HEAVY(__func__); @@ -476,7 +487,7 @@ static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* imag fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color]; bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color]; - matroxfb_1bpp_imageblit(PMINFO fgx, bgx, image->data, image->width, image->height, image->dy, image->dx); + matroxfb_1bpp_imageblit(minfo, fgx, bgx, image->data, image->width, image->height, image->dy, image->dx); } else { /* Danger! image->depth is useless: logo painting code always passes framebuffer color depth here, although logo data are diff --git a/drivers/video/matrox/matroxfb_accel.h b/drivers/video/matrox/matroxfb_accel.h index f40c314b4c30..1e418e62c22d 100644 --- a/drivers/video/matrox/matroxfb_accel.h +++ b/drivers/video/matrox/matroxfb_accel.h @@ -3,6 +3,6 @@ #include "matroxfb_base.h" -void matrox_cfbX_init(WPMINFO2); +void matrox_cfbX_init(struct matrox_fb_info *minfo); #endif diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 0c1049b308bf..7064fb4427b6 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -154,21 +154,22 @@ static struct fb_var_screeninfo vesafb_defined = { /* --------------------------------------------------------------------- */ -static void update_crtc2(WPMINFO unsigned int pos) { - struct matroxfb_dh_fb_info* info = ACCESS_FBINFO(crtc2.info); +static void update_crtc2(struct matrox_fb_info *minfo, unsigned int pos) +{ + struct matroxfb_dh_fb_info *info = minfo->crtc2.info; /* Make sure that displays are compatible */ - if (info && (info->fbcon.var.bits_per_pixel == ACCESS_FBINFO(fbcon).var.bits_per_pixel) - && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual) - && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length) + if (info && (info->fbcon.var.bits_per_pixel == minfo->fbcon.var.bits_per_pixel) + && (info->fbcon.var.xres_virtual == minfo->fbcon.var.xres_virtual) + && (info->fbcon.var.green.length == minfo->fbcon.var.green.length) ) { - switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { + switch (minfo->fbcon.var.bits_per_pixel) { case 16: case 32: pos = pos * 8; if (info->interlaced) { mga_outl(0x3C2C, pos); - mga_outl(0x3C28, pos + ACCESS_FBINFO(fbcon).var.xres_virtual * ACCESS_FBINFO(fbcon).var.bits_per_pixel / 8); + mga_outl(0x3C28, pos + minfo->fbcon.var.xres_virtual * minfo->fbcon.var.bits_per_pixel / 8); } else { mga_outl(0x3C28, pos); } @@ -177,17 +178,18 @@ static void update_crtc2(WPMINFO unsigned int pos) { } } -static void matroxfb_crtc1_panpos(WPMINFO2) { - if (ACCESS_FBINFO(crtc1.panpos) >= 0) { +static void matroxfb_crtc1_panpos(struct matrox_fb_info *minfo) +{ + if (minfo->crtc1.panpos >= 0) { unsigned long flags; int panpos; matroxfb_DAC_lock_irqsave(flags); - panpos = ACCESS_FBINFO(crtc1.panpos); + panpos = minfo->crtc1.panpos; if (panpos >= 0) { unsigned int extvga_reg; - ACCESS_FBINFO(crtc1.panpos) = -1; /* No update pending anymore */ + minfo->crtc1.panpos = -1; /* No update pending anymore */ extvga_reg = mga_inb(M_EXTVGA_INDEX); mga_setr(M_EXTVGA_INDEX, 0x00, panpos); if (extvga_reg != 0x00) { @@ -202,39 +204,39 @@ static irqreturn_t matrox_irq(int irq, void *dev_id) { u_int32_t status; int handled = 0; - - MINFO_FROM(dev_id); + struct matrox_fb_info *minfo = dev_id; status = mga_inl(M_STATUS); if (status & 0x20) { mga_outl(M_ICLEAR, 0x20); - ACCESS_FBINFO(crtc1.vsync.cnt)++; - matroxfb_crtc1_panpos(PMINFO2); - wake_up_interruptible(&ACCESS_FBINFO(crtc1.vsync.wait)); + minfo->crtc1.vsync.cnt++; + matroxfb_crtc1_panpos(minfo); + wake_up_interruptible(&minfo->crtc1.vsync.wait); handled = 1; } if (status & 0x200) { mga_outl(M_ICLEAR, 0x200); - ACCESS_FBINFO(crtc2.vsync.cnt)++; - wake_up_interruptible(&ACCESS_FBINFO(crtc2.vsync.wait)); + minfo->crtc2.vsync.cnt++; + wake_up_interruptible(&minfo->crtc2.vsync.wait); handled = 1; } return IRQ_RETVAL(handled); } -int matroxfb_enable_irq(WPMINFO int reenable) { +int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable) +{ u_int32_t bm; - if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) + if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) bm = 0x220; else bm = 0x020; - if (!test_and_set_bit(0, &ACCESS_FBINFO(irq_flags))) { - if (request_irq(ACCESS_FBINFO(pcidev)->irq, matrox_irq, - IRQF_SHARED, "matroxfb", MINFO)) { - clear_bit(0, &ACCESS_FBINFO(irq_flags)); + if (!test_and_set_bit(0, &minfo->irq_flags)) { + if (request_irq(minfo->pcidev->irq, matrox_irq, + IRQF_SHARED, "matroxfb", minfo)) { + clear_bit(0, &minfo->irq_flags); return -EINVAL; } /* Clear any pending field interrupts */ @@ -252,37 +254,39 @@ int matroxfb_enable_irq(WPMINFO int reenable) { return 0; } -static void matroxfb_disable_irq(WPMINFO2) { - if (test_and_clear_bit(0, &ACCESS_FBINFO(irq_flags))) { +static void matroxfb_disable_irq(struct matrox_fb_info *minfo) +{ + if (test_and_clear_bit(0, &minfo->irq_flags)) { /* Flush pending pan-at-vbl request... */ - matroxfb_crtc1_panpos(PMINFO2); - if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) + matroxfb_crtc1_panpos(minfo); + if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) mga_outl(M_IEN, mga_inl(M_IEN) & ~0x220); else mga_outl(M_IEN, mga_inl(M_IEN) & ~0x20); - free_irq(ACCESS_FBINFO(pcidev)->irq, MINFO); + free_irq(minfo->pcidev->irq, minfo); } } -int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) { +int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc) +{ struct matrox_vsync *vs; unsigned int cnt; int ret; switch (crtc) { case 0: - vs = &ACCESS_FBINFO(crtc1.vsync); + vs = &minfo->crtc1.vsync; break; case 1: - if (ACCESS_FBINFO(devflags.accelerator) != FB_ACCEL_MATROX_MGAG400) { + if (minfo->devflags.accelerator != FB_ACCEL_MATROX_MGAG400) { return -ENODEV; } - vs = &ACCESS_FBINFO(crtc2.vsync); + vs = &minfo->crtc2.vsync; break; default: return -ENODEV; } - ret = matroxfb_enable_irq(PMINFO 0); + ret = matroxfb_enable_irq(minfo, 0); if (ret) { return ret; } @@ -293,7 +297,7 @@ int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) { return ret; } if (ret == 0) { - matroxfb_enable_irq(PMINFO 1); + matroxfb_enable_irq(minfo, 1); return -ETIMEDOUT; } return 0; @@ -301,12 +305,12 @@ int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) { /* --------------------------------------------------------------------- */ -static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) { +static void matrox_pan_var(struct matrox_fb_info *minfo, + struct fb_var_screeninfo *var) +{ unsigned int pos; unsigned short p0, p1, p2; -#ifdef CONFIG_FB_MATROX_32MB unsigned int p3; -#endif int vbl; unsigned long flags; @@ -314,47 +318,44 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) { DBG(__func__) - if (ACCESS_FBINFO(dead)) + if (minfo->dead) return; - ACCESS_FBINFO(fbcon).var.xoffset = var->xoffset; - ACCESS_FBINFO(fbcon).var.yoffset = var->yoffset; - pos = (ACCESS_FBINFO(fbcon).var.yoffset * ACCESS_FBINFO(fbcon).var.xres_virtual + ACCESS_FBINFO(fbcon).var.xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32; - pos += ACCESS_FBINFO(curr.ydstorg.chunks); - p0 = ACCESS_FBINFO(hw).CRTC[0x0D] = pos & 0xFF; - p1 = ACCESS_FBINFO(hw).CRTC[0x0C] = (pos & 0xFF00) >> 8; - p2 = ACCESS_FBINFO(hw).CRTCEXT[0] = (ACCESS_FBINFO(hw).CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); -#ifdef CONFIG_FB_MATROX_32MB - p3 = ACCESS_FBINFO(hw).CRTCEXT[8] = pos >> 21; -#endif + minfo->fbcon.var.xoffset = var->xoffset; + minfo->fbcon.var.yoffset = var->yoffset; + pos = (minfo->fbcon.var.yoffset * minfo->fbcon.var.xres_virtual + minfo->fbcon.var.xoffset) * minfo->curr.final_bppShift / 32; + pos += minfo->curr.ydstorg.chunks; + p0 = minfo->hw.CRTC[0x0D] = pos & 0xFF; + p1 = minfo->hw.CRTC[0x0C] = (pos & 0xFF00) >> 8; + p2 = minfo->hw.CRTCEXT[0] = (minfo->hw.CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); + p3 = minfo->hw.CRTCEXT[8] = pos >> 21; /* FB_ACTIVATE_VBL and we can acquire interrupts? Honor FB_ACTIVATE_VBL then... */ - vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(PMINFO 0) == 0); + vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(minfo, 0) == 0); CRITBEGIN matroxfb_DAC_lock_irqsave(flags); mga_setr(M_CRTC_INDEX, 0x0D, p0); mga_setr(M_CRTC_INDEX, 0x0C, p1); -#ifdef CONFIG_FB_MATROX_32MB - if (ACCESS_FBINFO(devflags.support32MB)) + if (minfo->devflags.support32MB) mga_setr(M_EXTVGA_INDEX, 0x08, p3); -#endif if (vbl) { - ACCESS_FBINFO(crtc1.panpos) = p2; + minfo->crtc1.panpos = p2; } else { /* Abort any pending change */ - ACCESS_FBINFO(crtc1.panpos) = -1; + minfo->crtc1.panpos = -1; mga_setr(M_EXTVGA_INDEX, 0x00, p2); } matroxfb_DAC_unlock_irqrestore(flags); - update_crtc2(PMINFO pos); + update_crtc2(minfo, pos); CRITEND } -static void matroxfb_remove(WPMINFO int dummy) { +static void matroxfb_remove(struct matrox_fb_info *minfo, int dummy) +{ /* Currently we are holding big kernel lock on all dead & usecount updates. * Destroy everything after all users release it. Especially do not unregister * framebuffer and iounmap memory, neither fbmem nor fbcon-cfb* does not check @@ -363,25 +364,23 @@ static void matroxfb_remove(WPMINFO int dummy) { * write data without causing too much damage... */ - ACCESS_FBINFO(dead) = 1; - if (ACCESS_FBINFO(usecount)) { + minfo->dead = 1; + if (minfo->usecount) { /* destroy it later */ return; } - matroxfb_unregister_device(MINFO); - unregister_framebuffer(&ACCESS_FBINFO(fbcon)); - matroxfb_g450_shutdown(PMINFO2); + matroxfb_unregister_device(minfo); + unregister_framebuffer(&minfo->fbcon); + matroxfb_g450_shutdown(minfo); #ifdef CONFIG_MTRR - if (ACCESS_FBINFO(mtrr.vram_valid)) - mtrr_del(ACCESS_FBINFO(mtrr.vram), ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len)); + if (minfo->mtrr.vram_valid) + mtrr_del(minfo->mtrr.vram, minfo->video.base, minfo->video.len); #endif - mga_iounmap(ACCESS_FBINFO(mmio.vbase)); - mga_iounmap(ACCESS_FBINFO(video.vbase)); - release_mem_region(ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len_maximum)); - release_mem_region(ACCESS_FBINFO(mmio.base), 16384); -#ifdef CONFIG_FB_MATROX_MULTIHEAD + mga_iounmap(minfo->mmio.vbase); + mga_iounmap(minfo->video.vbase); + release_mem_region(minfo->video.base, minfo->video.len_maximum); + release_mem_region(minfo->mmio.base, 16384); kfree(minfo); -#endif } /* @@ -390,48 +389,50 @@ static void matroxfb_remove(WPMINFO int dummy) { static int matroxfb_open(struct fb_info *info, int user) { - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); DBG_LOOP(__func__) - if (ACCESS_FBINFO(dead)) { + if (minfo->dead) { return -ENXIO; } - ACCESS_FBINFO(usecount)++; + minfo->usecount++; if (user) { - ACCESS_FBINFO(userusecount)++; + minfo->userusecount++; } return(0); } static int matroxfb_release(struct fb_info *info, int user) { - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); DBG_LOOP(__func__) if (user) { - if (0 == --ACCESS_FBINFO(userusecount)) { - matroxfb_disable_irq(PMINFO2); + if (0 == --minfo->userusecount) { + matroxfb_disable_irq(minfo); } } - if (!(--ACCESS_FBINFO(usecount)) && ACCESS_FBINFO(dead)) { - matroxfb_remove(PMINFO 0); + if (!(--minfo->usecount) && minfo->dead) { + matroxfb_remove(minfo, 0); } return(0); } static int matroxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info) { - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); DBG(__func__) - matrox_pan_var(PMINFO var); + matrox_pan_var(minfo, var); return 0; } -static int matroxfb_get_final_bppShift(CPMINFO int bpp) { +static int matroxfb_get_final_bppShift(const struct matrox_fb_info *minfo, + int bpp) +{ int bppshft2; DBG(__func__) @@ -440,14 +441,16 @@ static int matroxfb_get_final_bppShift(CPMINFO int bpp) { if (!bppshft2) { return 8; } - if (isInterleave(MINFO)) + if (isInterleave(minfo)) bppshft2 >>= 1; - if (ACCESS_FBINFO(devflags.video64bits)) + if (minfo->devflags.video64bits) bppshft2 >>= 1; return bppshft2; } -static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) { +static int matroxfb_test_and_set_rounding(const struct matrox_fb_info *minfo, + int xres, int bpp) +{ int over; int rounding; @@ -465,11 +468,11 @@ static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) { break; default: rounding = 16; /* on G400, 16 really does not work */ - if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) + if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) rounding = 32; break; } - if (isInterleave(MINFO)) { + if (isInterleave(minfo)) { rounding *= 2; } over = xres % rounding; @@ -478,7 +481,9 @@ static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) { return xres; } -static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) { +static int matroxfb_pitch_adjust(const struct matrox_fb_info *minfo, int xres, + int bpp) +{ const int* width; int xres_new; @@ -486,18 +491,18 @@ static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) { if (!bpp) return xres; - width = ACCESS_FBINFO(capable.vxres); + width = minfo->capable.vxres; - if (ACCESS_FBINFO(devflags.precise_width)) { + if (minfo->devflags.precise_width) { while (*width) { - if ((*width >= xres) && (matroxfb_test_and_set_rounding(PMINFO *width, bpp) == *width)) { + if ((*width >= xres) && (matroxfb_test_and_set_rounding(minfo, *width, bpp) == *width)) { break; } width++; } xres_new = *width; } else { - xres_new = matroxfb_test_and_set_rounding(PMINFO xres, bpp); + xres_new = matroxfb_test_and_set_rounding(minfo, xres, bpp); } return xres_new; } @@ -524,7 +529,10 @@ static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) { return 16; /* return something reasonable... or panic()? */ } -static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visual, int *video_cmap_len, unsigned int* ydstorg) { +static int matroxfb_decode_var(const struct matrox_fb_info *minfo, + struct fb_var_screeninfo *var, int *visual, + int *video_cmap_len, unsigned int* ydstorg) +{ struct RGBT { unsigned char bpp; struct { @@ -551,7 +559,7 @@ static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visua DBG(__func__) switch (bpp) { - case 4: if (!ACCESS_FBINFO(capable.cfb4)) return -EINVAL; + case 4: if (!minfo->capable.cfb4) return -EINVAL; break; case 8: break; case 16: break; @@ -560,13 +568,13 @@ static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visua default: return -EINVAL; } *ydstorg = 0; - vramlen = ACCESS_FBINFO(video.len_usable); + vramlen = minfo->video.len_usable; if (var->yres_virtual < var->yres) var->yres_virtual = var->yres; if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; - var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, bpp); + var->xres_virtual = matroxfb_pitch_adjust(minfo, var->xres_virtual, bpp); memlen = var->xres_virtual * bpp * var->yres_virtual / 8; if (memlen > vramlen) { var->yres_virtual = vramlen * 8 / (var->xres_virtual * bpp); @@ -575,7 +583,7 @@ static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visua /* There is hardware bug that no line can cross 4MB boundary */ /* give up for CFB24, it is impossible to easy workaround it */ /* for other try to do something */ - if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000)) { + if (!minfo->capable.cross4MB && (memlen > 0x400000)) { if (bpp == 24) { /* sorry */ } else { @@ -644,9 +652,7 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fb_info) { -#ifdef CONFIG_FB_MATROX_MULTIHEAD struct matrox_fb_info* minfo = container_of(fb_info, struct matrox_fb_info, fbcon); -#endif DBG(__func__) @@ -657,20 +663,20 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green, * != 0 for invalid regno. */ - if (regno >= ACCESS_FBINFO(curr.cmap_len)) + if (regno >= minfo->curr.cmap_len) return 1; - if (ACCESS_FBINFO(fbcon).var.grayscale) { + if (minfo->fbcon.var.grayscale) { /* gray = 0.30*R + 0.59*G + 0.11*B */ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; } - red = CNVT_TOHW(red, ACCESS_FBINFO(fbcon).var.red.length); - green = CNVT_TOHW(green, ACCESS_FBINFO(fbcon).var.green.length); - blue = CNVT_TOHW(blue, ACCESS_FBINFO(fbcon).var.blue.length); - transp = CNVT_TOHW(transp, ACCESS_FBINFO(fbcon).var.transp.length); + red = CNVT_TOHW(red, minfo->fbcon.var.red.length); + green = CNVT_TOHW(green, minfo->fbcon.var.green.length); + blue = CNVT_TOHW(blue, minfo->fbcon.var.blue.length); + transp = CNVT_TOHW(transp, minfo->fbcon.var.transp.length); - switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { + switch (minfo->fbcon.var.bits_per_pixel) { case 4: case 8: mga_outb(M_DAC_REG, regno); @@ -683,30 +689,30 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green, break; { u_int16_t col = - (red << ACCESS_FBINFO(fbcon).var.red.offset) | - (green << ACCESS_FBINFO(fbcon).var.green.offset) | - (blue << ACCESS_FBINFO(fbcon).var.blue.offset) | - (transp << ACCESS_FBINFO(fbcon).var.transp.offset); /* for 1:5:5:5 */ - ACCESS_FBINFO(cmap[regno]) = col | (col << 16); + (red << minfo->fbcon.var.red.offset) | + (green << minfo->fbcon.var.green.offset) | + (blue << minfo->fbcon.var.blue.offset) | + (transp << minfo->fbcon.var.transp.offset); /* for 1:5:5:5 */ + minfo->cmap[regno] = col | (col << 16); } break; case 24: case 32: if (regno >= 16) break; - ACCESS_FBINFO(cmap[regno]) = - (red << ACCESS_FBINFO(fbcon).var.red.offset) | - (green << ACCESS_FBINFO(fbcon).var.green.offset) | - (blue << ACCESS_FBINFO(fbcon).var.blue.offset) | - (transp << ACCESS_FBINFO(fbcon).var.transp.offset); /* 8:8:8:8 */ + minfo->cmap[regno] = + (red << minfo->fbcon.var.red.offset) | + (green << minfo->fbcon.var.green.offset) | + (blue << minfo->fbcon.var.blue.offset) | + (transp << minfo->fbcon.var.transp.offset); /* 8:8:8:8 */ break; } return 0; } -static void matroxfb_init_fix(WPMINFO2) +static void matroxfb_init_fix(struct matrox_fb_info *minfo) { - struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; + struct fb_fix_screeninfo *fix = &minfo->fbcon.fix; DBG(__func__) strcpy(fix->id,"MATROX"); @@ -714,20 +720,20 @@ static void matroxfb_init_fix(WPMINFO2) fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */ fix->ypanstep = 1; fix->ywrapstep = 0; - fix->mmio_start = ACCESS_FBINFO(mmio.base); - fix->mmio_len = ACCESS_FBINFO(mmio.len); - fix->accel = ACCESS_FBINFO(devflags.accelerator); + fix->mmio_start = minfo->mmio.base; + fix->mmio_len = minfo->mmio.len; + fix->accel = minfo->devflags.accelerator; } -static void matroxfb_update_fix(WPMINFO2) +static void matroxfb_update_fix(struct matrox_fb_info *minfo) { - struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; + struct fb_fix_screeninfo *fix = &minfo->fbcon.fix; DBG(__func__) - mutex_lock(&ACCESS_FBINFO(fbcon).mm_lock); - fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); - fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); - mutex_unlock(&ACCESS_FBINFO(fbcon).mm_lock); + mutex_lock(&minfo->fbcon.mm_lock); + fix->smem_start = minfo->video.base + minfo->curr.ydstorg.bytes; + fix->smem_len = minfo->video.len_usable - minfo->curr.ydstorg.bytes; + mutex_unlock(&minfo->fbcon.mm_lock); } static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) @@ -736,12 +742,12 @@ static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *inf int visual; int cmap_len; unsigned int ydstorg; - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); - if (ACCESS_FBINFO(dead)) { + if (minfo->dead) { return -ENXIO; } - if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len, &ydstorg)) != 0) + if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0) return err; return 0; } @@ -753,35 +759,35 @@ static int matroxfb_set_par(struct fb_info *info) int cmap_len; unsigned int ydstorg; struct fb_var_screeninfo *var; - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); DBG(__func__) - if (ACCESS_FBINFO(dead)) { + if (minfo->dead) { return -ENXIO; } var = &info->var; - if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len, &ydstorg)) != 0) + if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0) return err; - ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)) + ydstorg; - matroxfb_update_fix(PMINFO2); - ACCESS_FBINFO(fbcon).fix.visual = visual; - ACCESS_FBINFO(fbcon).fix.type = FB_TYPE_PACKED_PIXELS; - ACCESS_FBINFO(fbcon).fix.type_aux = 0; - ACCESS_FBINFO(fbcon).fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3; + minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase) + ydstorg; + matroxfb_update_fix(minfo); + minfo->fbcon.fix.visual = visual; + minfo->fbcon.fix.type = FB_TYPE_PACKED_PIXELS; + minfo->fbcon.fix.type_aux = 0; + minfo->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3; { unsigned int pos; - ACCESS_FBINFO(curr.cmap_len) = cmap_len; - ydstorg += ACCESS_FBINFO(devflags.ydstorg); - ACCESS_FBINFO(curr.ydstorg.bytes) = ydstorg; - ACCESS_FBINFO(curr.ydstorg.chunks) = ydstorg >> (isInterleave(MINFO)?3:2); + minfo->curr.cmap_len = cmap_len; + ydstorg += minfo->devflags.ydstorg; + minfo->curr.ydstorg.bytes = ydstorg; + minfo->curr.ydstorg.chunks = ydstorg >> (isInterleave(minfo) ? 3 : 2); if (var->bits_per_pixel == 4) - ACCESS_FBINFO(curr.ydstorg.pixels) = ydstorg; + minfo->curr.ydstorg.pixels = ydstorg; else - ACCESS_FBINFO(curr.ydstorg.pixels) = (ydstorg * 8) / var->bits_per_pixel; - ACCESS_FBINFO(curr.final_bppShift) = matroxfb_get_final_bppShift(PMINFO var->bits_per_pixel); + minfo->curr.ydstorg.pixels = (ydstorg * 8) / var->bits_per_pixel; + minfo->curr.final_bppShift = matroxfb_get_final_bppShift(minfo, var->bits_per_pixel); { struct my_timming mt; struct matrox_hw_state* hw; int out; @@ -797,54 +803,55 @@ static int matroxfb_set_par(struct fb_info *info) default: mt.delay = 31 + 8; break; } - hw = &ACCESS_FBINFO(hw); + hw = &minfo->hw; - down_read(&ACCESS_FBINFO(altout).lock); + down_read(&minfo->altout.lock); for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 && - ACCESS_FBINFO(outputs[out]).output->compute) { - ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt); + if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 && + minfo->outputs[out].output->compute) { + minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt); } } - up_read(&ACCESS_FBINFO(altout).lock); - ACCESS_FBINFO(crtc1).pixclock = mt.pixclock; - ACCESS_FBINFO(crtc1).mnp = mt.mnp; - ACCESS_FBINFO(hw_switch->init(PMINFO &mt)); - pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32; - pos += ACCESS_FBINFO(curr.ydstorg.chunks); + up_read(&minfo->altout.lock); + minfo->crtc1.pixclock = mt.pixclock; + minfo->crtc1.mnp = mt.mnp; + minfo->hw_switch->init(minfo, &mt); + pos = (var->yoffset * var->xres_virtual + var->xoffset) * minfo->curr.final_bppShift / 32; + pos += minfo->curr.ydstorg.chunks; hw->CRTC[0x0D] = pos & 0xFF; hw->CRTC[0x0C] = (pos & 0xFF00) >> 8; hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); hw->CRTCEXT[8] = pos >> 21; - ACCESS_FBINFO(hw_switch->restore(PMINFO2)); - update_crtc2(PMINFO pos); - down_read(&ACCESS_FBINFO(altout).lock); + minfo->hw_switch->restore(minfo); + update_crtc2(minfo, pos); + down_read(&minfo->altout.lock); for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 && - ACCESS_FBINFO(outputs[out]).output->program) { - ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data); + if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 && + minfo->outputs[out].output->program) { + minfo->outputs[out].output->program(minfo->outputs[out].data); } } for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 && - ACCESS_FBINFO(outputs[out]).output->start) { - ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data); + if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 && + minfo->outputs[out].output->start) { + minfo->outputs[out].output->start(minfo->outputs[out].data); } } - up_read(&ACCESS_FBINFO(altout).lock); - matrox_cfbX_init(PMINFO2); + up_read(&minfo->altout.lock); + matrox_cfbX_init(minfo); } } - ACCESS_FBINFO(initialized) = 1; + minfo->initialized = 1; return 0; } -static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank) +static int matroxfb_get_vblank(struct matrox_fb_info *minfo, + struct fb_vblank *vblank) { unsigned int sts1; - matroxfb_enable_irq(PMINFO 0); + matroxfb_enable_irq(minfo, 0); memset(vblank, 0, sizeof(*vblank)); vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC | FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK; @@ -857,13 +864,13 @@ static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank) vblank->flags |= FB_VBLANK_HBLANKING; if (sts1 & 8) vblank->flags |= FB_VBLANK_VSYNCING; - if (vblank->vcount >= ACCESS_FBINFO(fbcon).var.yres) + if (vblank->vcount >= minfo->fbcon.var.yres) vblank->flags |= FB_VBLANK_VBLANKING; - if (test_bit(0, &ACCESS_FBINFO(irq_flags))) { + if (test_bit(0, &minfo->irq_flags)) { vblank->flags |= FB_VBLANK_HAVE_COUNT; /* Only one writer, aligned int value... it should work without lock and without atomic_t */ - vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt; + vblank->count = minfo->crtc1.vsync.cnt; } return 0; } @@ -876,11 +883,11 @@ static int matroxfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); DBG(__func__) - if (ACCESS_FBINFO(dead)) { + if (minfo->dead) { return -ENXIO; } @@ -890,7 +897,7 @@ static int matroxfb_ioctl(struct fb_info *info, struct fb_vblank vblank; int err; - err = matroxfb_get_vblank(PMINFO &vblank); + err = matroxfb_get_vblank(minfo, &vblank); if (err) return err; if (copy_to_user(argp, &vblank, sizeof(vblank))) @@ -904,7 +911,7 @@ static int matroxfb_ioctl(struct fb_info *info, if (get_user(crt, (u_int32_t __user *)arg)) return -EFAULT; - return matroxfb_wait_for_sync(PMINFO crt); + return matroxfb_wait_for_sync(minfo, crt); } case MATROXFB_SET_OUTPUT_MODE: { @@ -916,8 +923,8 @@ static int matroxfb_ioctl(struct fb_info *info, return -EFAULT; if (mom.output >= MATROXFB_MAX_OUTPUTS) return -ENXIO; - down_read(&ACCESS_FBINFO(altout.lock)); - oproc = ACCESS_FBINFO(outputs[mom.output]).output; + down_read(&minfo->altout.lock); + oproc = minfo->outputs[mom.output].output; if (!oproc) { val = -ENXIO; } else if (!oproc->verifymode) { @@ -927,18 +934,18 @@ static int matroxfb_ioctl(struct fb_info *info, val = -EINVAL; } } else { - val = oproc->verifymode(ACCESS_FBINFO(outputs[mom.output]).data, mom.mode); + val = oproc->verifymode(minfo->outputs[mom.output].data, mom.mode); } if (!val) { - if (ACCESS_FBINFO(outputs[mom.output]).mode != mom.mode) { - ACCESS_FBINFO(outputs[mom.output]).mode = mom.mode; + if (minfo->outputs[mom.output].mode != mom.mode) { + minfo->outputs[mom.output].mode = mom.mode; val = 1; } } - up_read(&ACCESS_FBINFO(altout.lock)); + up_read(&minfo->altout.lock); if (val != 1) return val; - switch (ACCESS_FBINFO(outputs[mom.output]).src) { + switch (minfo->outputs[mom.output].src) { case MATROXFB_SRC_CRTC1: matroxfb_set_par(info); break; @@ -946,11 +953,11 @@ static int matroxfb_ioctl(struct fb_info *info, { struct matroxfb_dh_fb_info* crtc2; - down_read(&ACCESS_FBINFO(crtc2.lock)); - crtc2 = ACCESS_FBINFO(crtc2.info); + down_read(&minfo->crtc2.lock); + crtc2 = minfo->crtc2.info; if (crtc2) crtc2->fbcon.fbops->fb_set_par(&crtc2->fbcon); - up_read(&ACCESS_FBINFO(crtc2.lock)); + up_read(&minfo->crtc2.lock); } break; } @@ -966,15 +973,15 @@ static int matroxfb_ioctl(struct fb_info *info, return -EFAULT; if (mom.output >= MATROXFB_MAX_OUTPUTS) return -ENXIO; - down_read(&ACCESS_FBINFO(altout.lock)); - oproc = ACCESS_FBINFO(outputs[mom.output]).output; + down_read(&minfo->altout.lock); + oproc = minfo->outputs[mom.output].output; if (!oproc) { val = -ENXIO; } else { - mom.mode = ACCESS_FBINFO(outputs[mom.output]).mode; + mom.mode = minfo->outputs[mom.output].mode; val = 0; } - up_read(&ACCESS_FBINFO(altout.lock)); + up_read(&minfo->altout.lock); if (val) return val; if (copy_to_user(argp, &mom, sizeof(mom))) @@ -993,9 +1000,9 @@ static int matroxfb_ioctl(struct fb_info *info, if (tmp & (1 << i)) { if (i >= MATROXFB_MAX_OUTPUTS) return -ENXIO; - if (!ACCESS_FBINFO(outputs[i]).output) + if (!minfo->outputs[i].output) return -ENXIO; - switch (ACCESS_FBINFO(outputs[i]).src) { + switch (minfo->outputs[i].src) { case MATROXFB_SRC_NONE: case MATROXFB_SRC_CRTC1: break; @@ -1004,12 +1011,12 @@ static int matroxfb_ioctl(struct fb_info *info, } } } - if (ACCESS_FBINFO(devflags.panellink)) { + if (minfo->devflags.panellink) { if (tmp & MATROXFB_OUTPUT_CONN_DFP) { if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY) return -EINVAL; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { - if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC2) { + if (minfo->outputs[i].src == MATROXFB_SRC_CRTC2) { return -EBUSY; } } @@ -1018,13 +1025,13 @@ static int matroxfb_ioctl(struct fb_info *info, changes = 0; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { if (tmp & (1 << i)) { - if (ACCESS_FBINFO(outputs[i]).src != MATROXFB_SRC_CRTC1) { + if (minfo->outputs[i].src != MATROXFB_SRC_CRTC1) { changes = 1; - ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_CRTC1; + minfo->outputs[i].src = MATROXFB_SRC_CRTC1; } - } else if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) { + } else if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) { changes = 1; - ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_NONE; + minfo->outputs[i].src = MATROXFB_SRC_NONE; } } if (!changes) @@ -1038,7 +1045,7 @@ static int matroxfb_ioctl(struct fb_info *info, int i; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { - if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) { + if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) { conn |= 1 << i; } } @@ -1052,8 +1059,8 @@ static int matroxfb_ioctl(struct fb_info *info, int i; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { - if (ACCESS_FBINFO(outputs[i]).output) { - switch (ACCESS_FBINFO(outputs[i]).src) { + if (minfo->outputs[i].output) { + switch (minfo->outputs[i].src) { case MATROXFB_SRC_NONE: case MATROXFB_SRC_CRTC1: conn |= 1 << i; @@ -1061,7 +1068,7 @@ static int matroxfb_ioctl(struct fb_info *info, } } } - if (ACCESS_FBINFO(devflags.panellink)) { + if (minfo->devflags.panellink) { if (conn & MATROXFB_OUTPUT_CONN_DFP) conn &= ~MATROXFB_OUTPUT_CONN_SECONDARY; if (conn & MATROXFB_OUTPUT_CONN_SECONDARY) @@ -1077,7 +1084,7 @@ static int matroxfb_ioctl(struct fb_info *info, int i; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { - if (ACCESS_FBINFO(outputs[i]).output) { + if (minfo->outputs[i].output) { conn |= 1 << i; } } @@ -1092,7 +1099,7 @@ static int matroxfb_ioctl(struct fb_info *info, memset(&r, 0, sizeof(r)); strcpy(r.driver, "matroxfb"); strcpy(r.card, "Matrox"); - sprintf(r.bus_info, "PCI:%s", pci_name(ACCESS_FBINFO(pcidev))); + sprintf(r.bus_info, "PCI:%s", pci_name(minfo->pcidev)); r.version = KERNEL_VERSION(1,0,0); r.capabilities = V4L2_CAP_VIDEO_OUTPUT; if (copy_to_user(argp, &r, sizeof(r))) @@ -1108,15 +1115,15 @@ static int matroxfb_ioctl(struct fb_info *info, if (copy_from_user(&qctrl, argp, sizeof(qctrl))) return -EFAULT; - down_read(&ACCESS_FBINFO(altout).lock); - if (!ACCESS_FBINFO(outputs[1]).output) { + down_read(&minfo->altout.lock); + if (!minfo->outputs[1].output) { err = -ENXIO; - } else if (ACCESS_FBINFO(outputs[1]).output->getqueryctrl) { - err = ACCESS_FBINFO(outputs[1]).output->getqueryctrl(ACCESS_FBINFO(outputs[1]).data, &qctrl); + } else if (minfo->outputs[1].output->getqueryctrl) { + err = minfo->outputs[1].output->getqueryctrl(minfo->outputs[1].data, &qctrl); } else { err = -EINVAL; } - up_read(&ACCESS_FBINFO(altout).lock); + up_read(&minfo->altout.lock); if (err >= 0 && copy_to_user(argp, &qctrl, sizeof(qctrl))) return -EFAULT; @@ -1130,15 +1137,15 @@ static int matroxfb_ioctl(struct fb_info *info, if (copy_from_user(&ctrl, argp, sizeof(ctrl))) return -EFAULT; - down_read(&ACCESS_FBINFO(altout).lock); - if (!ACCESS_FBINFO(outputs[1]).output) { + down_read(&minfo->altout.lock); + if (!minfo->outputs[1].output) { err = -ENXIO; - } else if (ACCESS_FBINFO(outputs[1]).output->getctrl) { - err = ACCESS_FBINFO(outputs[1]).output->getctrl(ACCESS_FBINFO(outputs[1]).data, &ctrl); + } else if (minfo->outputs[1].output->getctrl) { + err = minfo->outputs[1].output->getctrl(minfo->outputs[1].data, &ctrl); } else { err = -EINVAL; } - up_read(&ACCESS_FBINFO(altout).lock); + up_read(&minfo->altout.lock); if (err >= 0 && copy_to_user(argp, &ctrl, sizeof(ctrl))) return -EFAULT; @@ -1153,15 +1160,15 @@ static int matroxfb_ioctl(struct fb_info *info, if (copy_from_user(&ctrl, argp, sizeof(ctrl))) return -EFAULT; - down_read(&ACCESS_FBINFO(altout).lock); - if (!ACCESS_FBINFO(outputs[1]).output) { + down_read(&minfo->altout.lock); + if (!minfo->outputs[1].output) { err = -ENXIO; - } else if (ACCESS_FBINFO(outputs[1]).output->setctrl) { - err = ACCESS_FBINFO(outputs[1]).output->setctrl(ACCESS_FBINFO(outputs[1]).data, &ctrl); + } else if (minfo->outputs[1].output->setctrl) { + err = minfo->outputs[1].output->setctrl(minfo->outputs[1].data, &ctrl); } else { err = -EINVAL; } - up_read(&ACCESS_FBINFO(altout).lock); + up_read(&minfo->altout.lock); return err; } } @@ -1175,11 +1182,11 @@ static int matroxfb_blank(int blank, struct fb_info *info) int seq; int crtc; CRITFLAGS - MINFO_FROM_INFO(info); + struct matrox_fb_info *minfo = info2minfo(info); DBG(__func__) - if (ACCESS_FBINFO(dead)) + if (minfo->dead) return 1; switch (blank) { @@ -1281,7 +1288,9 @@ static char outputs[8]; /* "matrox:outputs:xxx" */ static char videomode[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */ #endif -static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSize){ +static int matroxfb_getmemory(struct matrox_fb_info *minfo, + unsigned int maxSize, unsigned int *realSize) +{ vaddr_t vm; unsigned int offs; unsigned int offs2; @@ -1291,7 +1300,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi DBG(__func__) - vm = ACCESS_FBINFO(video.vbase); + vm = minfo->video.vbase; maxSize &= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */ /* at least 2MB */ if (maxSize < 0x0200000) return 0; @@ -1323,7 +1332,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi *realSize = offs - 0x100000; #ifdef CONFIG_FB_MATROX_MILLENIUM - ACCESS_FBINFO(interleave) = !(!isMillenium(MINFO) || ((offs - 0x100000) & 0x3FFFFF)); + minfo->interleave = !(!isMillenium(minfo) || ((offs - 0x100000) & 0x3FFFFF)); #endif return 1; } @@ -1345,13 +1354,9 @@ static struct video_board vbMystique = {0x0800000, 0x0800000, FB_ACCEL_MATROX_M #ifdef CONFIG_FB_MATROX_G static struct video_board vbG100 = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100, &matrox_G100}; static struct video_board vbG200 = {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200, &matrox_G100}; -#ifdef CONFIG_FB_MATROX_32MB /* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for whole 32MB */ static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100}; -#else -static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100}; -#endif #endif #define DEVF_VIDEO64BIT 0x0001 @@ -1558,16 +1563,17 @@ static struct fb_videomode defaultmode = { static int hotplug = 0; -static void setDefaultOutputs(WPMINFO2) { +static void setDefaultOutputs(struct matrox_fb_info *minfo) +{ unsigned int i; const char* ptr; - ACCESS_FBINFO(outputs[0]).default_src = MATROXFB_SRC_CRTC1; - if (ACCESS_FBINFO(devflags.g450dac)) { - ACCESS_FBINFO(outputs[1]).default_src = MATROXFB_SRC_CRTC1; - ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1; + minfo->outputs[0].default_src = MATROXFB_SRC_CRTC1; + if (minfo->devflags.g450dac) { + minfo->outputs[1].default_src = MATROXFB_SRC_CRTC1; + minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1; } else if (dfp) { - ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1; + minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1; } ptr = outputs; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { @@ -1577,11 +1583,11 @@ static void setDefaultOutputs(WPMINFO2) { break; } if (c == '0') { - ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_NONE; + minfo->outputs[i].default_src = MATROXFB_SRC_NONE; } else if (c == '1') { - ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC1; - } else if (c == '2' && ACCESS_FBINFO(devflags.crtc2)) { - ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC2; + minfo->outputs[i].default_src = MATROXFB_SRC_CRTC1; + } else if (c == '2' && minfo->devflags.crtc2) { + minfo->outputs[i].default_src = MATROXFB_SRC_CRTC2; } else { printk(KERN_ERR "matroxfb: Unknown outputs setting\n"); break; @@ -1591,7 +1597,8 @@ static void setDefaultOutputs(WPMINFO2) { outputs[0] = 0; } -static int initMatrox2(WPMINFO struct board* b){ +static int initMatrox2(struct matrox_fb_info *minfo, struct board *b) +{ unsigned long ctrlptr_phys = 0; unsigned long video_base_phys = 0; unsigned int memsize; @@ -1607,58 +1614,56 @@ static int initMatrox2(WPMINFO struct board* b){ /* set default values... */ vesafb_defined.accel_flags = FB_ACCELF_TEXT; - ACCESS_FBINFO(hw_switch) = b->base->lowlevel; - ACCESS_FBINFO(devflags.accelerator) = b->base->accelID; - ACCESS_FBINFO(max_pixel_clock) = b->maxclk; + minfo->hw_switch = b->base->lowlevel; + minfo->devflags.accelerator = b->base->accelID; + minfo->max_pixel_clock = b->maxclk; printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name); - ACCESS_FBINFO(capable.plnwt) = 1; - ACCESS_FBINFO(chip) = b->chip; - ACCESS_FBINFO(capable.srcorg) = b->flags & DEVF_SRCORG; - ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT; + minfo->capable.plnwt = 1; + minfo->chip = b->chip; + minfo->capable.srcorg = b->flags & DEVF_SRCORG; + minfo->devflags.video64bits = b->flags & DEVF_VIDEO64BIT; if (b->flags & DEVF_TEXT4B) { - ACCESS_FBINFO(devflags.vgastep) = 4; - ACCESS_FBINFO(devflags.textmode) = 4; - ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP16; + minfo->devflags.vgastep = 4; + minfo->devflags.textmode = 4; + minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16; } else if (b->flags & DEVF_TEXT16B) { - ACCESS_FBINFO(devflags.vgastep) = 16; - ACCESS_FBINFO(devflags.textmode) = 1; - ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP16; + minfo->devflags.vgastep = 16; + minfo->devflags.textmode = 1; + minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16; } else { - ACCESS_FBINFO(devflags.vgastep) = 8; - ACCESS_FBINFO(devflags.textmode) = 1; - ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP8; - } -#ifdef CONFIG_FB_MATROX_32MB - ACCESS_FBINFO(devflags.support32MB) = (b->flags & DEVF_SUPPORT32MB) != 0; -#endif - ACCESS_FBINFO(devflags.precise_width) = !(b->flags & DEVF_ANY_VXRES); - ACCESS_FBINFO(devflags.crtc2) = (b->flags & DEVF_CRTC2) != 0; - ACCESS_FBINFO(devflags.maven_capable) = (b->flags & DEVF_MAVEN_CAPABLE) != 0; - ACCESS_FBINFO(devflags.dualhead) = (b->flags & DEVF_DUALHEAD) != 0; - ACCESS_FBINFO(devflags.dfp_type) = dfp_type; - ACCESS_FBINFO(devflags.g450dac) = (b->flags & DEVF_G450DAC) != 0; - ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode); - ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode); - setDefaultOutputs(PMINFO2); + minfo->devflags.vgastep = 8; + minfo->devflags.textmode = 1; + minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP8; + } + minfo->devflags.support32MB = (b->flags & DEVF_SUPPORT32MB) != 0; + minfo->devflags.precise_width = !(b->flags & DEVF_ANY_VXRES); + minfo->devflags.crtc2 = (b->flags & DEVF_CRTC2) != 0; + minfo->devflags.maven_capable = (b->flags & DEVF_MAVEN_CAPABLE) != 0; + minfo->devflags.dualhead = (b->flags & DEVF_DUALHEAD) != 0; + minfo->devflags.dfp_type = dfp_type; + minfo->devflags.g450dac = (b->flags & DEVF_G450DAC) != 0; + minfo->devflags.textstep = minfo->devflags.vgastep * minfo->devflags.textmode; + minfo->devflags.textvram = 65536 / minfo->devflags.textmode; + setDefaultOutputs(minfo); if (b->flags & DEVF_PANELLINK_CAPABLE) { - ACCESS_FBINFO(outputs[2]).data = MINFO; - ACCESS_FBINFO(outputs[2]).output = &panellink_output; - ACCESS_FBINFO(outputs[2]).src = ACCESS_FBINFO(outputs[2]).default_src; - ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR; - ACCESS_FBINFO(devflags.panellink) = 1; + minfo->outputs[2].data = minfo; + minfo->outputs[2].output = &panellink_output; + minfo->outputs[2].src = minfo->outputs[2].default_src; + minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR; + minfo->devflags.panellink = 1; } - if (ACCESS_FBINFO(capable.cross4MB) < 0) - ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB; + if (minfo->capable.cross4MB < 0) + minfo->capable.cross4MB = b->flags & DEVF_CROSS4MB; if (b->flags & DEVF_SWAPS) { - ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1); - video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0); - ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_0; + ctrlptr_phys = pci_resource_start(minfo->pcidev, 1); + video_base_phys = pci_resource_start(minfo->pcidev, 0); + minfo->devflags.fbResource = PCI_BASE_ADDRESS_0; } else { - ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0); - video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1); - ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_1; + ctrlptr_phys = pci_resource_start(minfo->pcidev, 0); + video_base_phys = pci_resource_start(minfo->pcidev, 1); + minfo->devflags.fbResource = PCI_BASE_ADDRESS_1; } err = -EINVAL; if (!ctrlptr_phys) { @@ -1676,7 +1681,7 @@ static int initMatrox2(WPMINFO struct board* b){ if (!request_mem_region(video_base_phys, memsize, "matroxfb FB")) { goto failCtrlMR; } - ACCESS_FBINFO(video.len_maximum) = memsize; + minfo->video.len_maximum = memsize; /* convert mem (autodetect k, M) */ if (mem < 1024) mem *= 1024; if (mem < 0x00100000) mem *= 1024; @@ -1684,14 +1689,14 @@ static int initMatrox2(WPMINFO struct board* b){ if (mem && (mem < memsize)) memsize = mem; err = -ENOMEM; - if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &ACCESS_FBINFO(mmio.vbase))) { + if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &minfo->mmio.vbase)) { printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys); goto failVideoMR; } - ACCESS_FBINFO(mmio.base) = ctrlptr_phys; - ACCESS_FBINFO(mmio.len) = 16384; - ACCESS_FBINFO(video.base) = video_base_phys; - if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) { + minfo->mmio.base = ctrlptr_phys; + minfo->mmio.len = 16384; + minfo->video.base = video_base_phys; + if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &minfo->video.vbase)) { printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n", video_base_phys, memsize); goto failCtrlIO; @@ -1700,63 +1705,63 @@ static int initMatrox2(WPMINFO struct board* b){ u_int32_t cmd; u_int32_t mga_option; - pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, &mga_option); - pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, &cmd); + pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &mga_option); + pci_read_config_dword(minfo->pcidev, PCI_COMMAND, &cmd); mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */ mga_option |= MX_OPTION_BSWAP; /* disable palette snooping */ cmd &= ~PCI_COMMAND_VGA_PALETTE; if (pci_dev_present(intel_82437)) { - if (!(mga_option & 0x20000000) && !ACCESS_FBINFO(devflags.nopciretry)) { + if (!(mga_option & 0x20000000) && !minfo->devflags.nopciretry) { printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n"); } mga_option |= 0x20000000; - ACCESS_FBINFO(devflags.nopciretry) = 1; + minfo->devflags.nopciretry = 1; } - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, cmd); - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mga_option); - ACCESS_FBINFO(hw).MXoptionReg = mga_option; + pci_write_config_dword(minfo->pcidev, PCI_COMMAND, cmd); + pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mga_option); + minfo->hw.MXoptionReg = mga_option; /* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */ /* maybe preinit() candidate, but it is same... for all devices... at this time... */ - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MGA_INDEX, 0x00003C00); + pci_write_config_dword(minfo->pcidev, PCI_MGA_INDEX, 0x00003C00); } err = -ENXIO; - matroxfb_read_pins(PMINFO2); - if (ACCESS_FBINFO(hw_switch)->preinit(PMINFO2)) { + matroxfb_read_pins(minfo); + if (minfo->hw_switch->preinit(minfo)) { goto failVideoIO; } err = -ENOMEM; - if (!matroxfb_getmemory(PMINFO memsize, &ACCESS_FBINFO(video.len)) || !ACCESS_FBINFO(video.len)) { + if (!matroxfb_getmemory(minfo, memsize, &minfo->video.len) || !minfo->video.len) { printk(KERN_ERR "matroxfb: cannot determine memory size\n"); goto failVideoIO; } - ACCESS_FBINFO(devflags.ydstorg) = 0; + minfo->devflags.ydstorg = 0; - ACCESS_FBINFO(video.base) = video_base_phys; - ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len); - if (ACCESS_FBINFO(video.len_usable) > b->base->maxdisplayable) - ACCESS_FBINFO(video.len_usable) = b->base->maxdisplayable; + minfo->video.base = video_base_phys; + minfo->video.len_usable = minfo->video.len; + if (minfo->video.len_usable > b->base->maxdisplayable) + minfo->video.len_usable = b->base->maxdisplayable; #ifdef CONFIG_MTRR if (mtrr) { - ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1); - ACCESS_FBINFO(mtrr.vram_valid) = 1; + minfo->mtrr.vram = mtrr_add(video_base_phys, minfo->video.len, MTRR_TYPE_WRCOMB, 1); + minfo->mtrr.vram_valid = 1; printk(KERN_INFO "matroxfb: MTRR's turned on\n"); } #endif /* CONFIG_MTRR */ - if (!ACCESS_FBINFO(devflags.novga)) + if (!minfo->devflags.novga) request_region(0x3C0, 32, "matrox"); - matroxfb_g450_connect(PMINFO2); - ACCESS_FBINFO(hw_switch->reset(PMINFO2)); + matroxfb_g450_connect(minfo); + minfo->hw_switch->reset(minfo); - ACCESS_FBINFO(fbcon.monspecs.hfmin) = 0; - ACCESS_FBINFO(fbcon.monspecs.hfmax) = fh; - ACCESS_FBINFO(fbcon.monspecs.vfmin) = 0; - ACCESS_FBINFO(fbcon.monspecs.vfmax) = fv; - ACCESS_FBINFO(fbcon.monspecs.dpms) = 0; /* TBD */ + minfo->fbcon.monspecs.hfmin = 0; + minfo->fbcon.monspecs.hfmax = fh; + minfo->fbcon.monspecs.vfmin = 0; + minfo->fbcon.monspecs.vfmax = fv; + minfo->fbcon.monspecs.dpms = 0; /* TBD */ /* static settings */ vesafb_defined.red = colors[depth-1].red; @@ -1768,24 +1773,24 @@ static int initMatrox2(WPMINFO struct board* b){ if (noaccel) vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT; - ACCESS_FBINFO(fbops) = matroxfb_ops; - ACCESS_FBINFO(fbcon.fbops) = &ACCESS_FBINFO(fbops); - ACCESS_FBINFO(fbcon.pseudo_palette) = ACCESS_FBINFO(cmap); + minfo->fbops = matroxfb_ops; + minfo->fbcon.fbops = &minfo->fbops; + minfo->fbcon.pseudo_palette = minfo->cmap; /* after __init time we are like module... no logo */ - ACCESS_FBINFO(fbcon.flags) = hotplug ? FBINFO_FLAG_MODULE : FBINFO_FLAG_DEFAULT; - ACCESS_FBINFO(fbcon.flags) |= FBINFO_PARTIAL_PAN_OK | /* Prefer panning for scroll under MC viewer/edit */ + minfo->fbcon.flags = hotplug ? FBINFO_FLAG_MODULE : FBINFO_FLAG_DEFAULT; + minfo->fbcon.flags |= FBINFO_PARTIAL_PAN_OK | /* Prefer panning for scroll under MC viewer/edit */ FBINFO_HWACCEL_COPYAREA | /* We have hw-assisted bmove */ FBINFO_HWACCEL_FILLRECT | /* And fillrect */ FBINFO_HWACCEL_IMAGEBLIT | /* And imageblit */ FBINFO_HWACCEL_XPAN | /* And we support both horizontal */ FBINFO_HWACCEL_YPAN; /* And vertical panning */ - ACCESS_FBINFO(video.len_usable) &= PAGE_MASK; - fb_alloc_cmap(&ACCESS_FBINFO(fbcon.cmap), 256, 1); + minfo->video.len_usable &= PAGE_MASK; + fb_alloc_cmap(&minfo->fbcon.cmap, 256, 1); #ifndef MODULE /* mode database is marked __init!!! */ if (!hotplug) { - fb_find_mode(&vesafb_defined, &ACCESS_FBINFO(fbcon), videomode[0]?videomode:NULL, + fb_find_mode(&vesafb_defined, &minfo->fbcon, videomode[0] ? videomode : NULL, NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel); } #endif /* !MODULE */ @@ -1874,52 +1879,52 @@ static int initMatrox2(WPMINFO struct board* b){ vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough to yres_virtual * xres_virtual < 2^32 */ } - matroxfb_init_fix(PMINFO2); - ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)); + matroxfb_init_fix(minfo); + minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase); /* Normalize values (namely yres_virtual) */ - matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon)); + matroxfb_check_var(&vesafb_defined, &minfo->fbcon); /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over * vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var, * and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work * anyway. But we at least tried... */ - ACCESS_FBINFO(fbcon.var) = vesafb_defined; + minfo->fbcon.var = vesafb_defined; err = -EINVAL; printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n", vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_defined.xres_virtual, vesafb_defined.yres_virtual); printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n", - ACCESS_FBINFO(video.base), vaddr_va(ACCESS_FBINFO(video.vbase)), ACCESS_FBINFO(video.len)); + minfo->video.base, vaddr_va(minfo->video.vbase), minfo->video.len); /* We do not have to set currcon to 0... register_framebuffer do it for us on first console * and we do not want currcon == 0 for subsequent framebuffers */ - ACCESS_FBINFO(fbcon).device = &ACCESS_FBINFO(pcidev)->dev; - if (register_framebuffer(&ACCESS_FBINFO(fbcon)) < 0) { + minfo->fbcon.device = &minfo->pcidev->dev; + if (register_framebuffer(&minfo->fbcon) < 0) { goto failVideoIO; } printk("fb%d: %s frame buffer device\n", - ACCESS_FBINFO(fbcon.node), ACCESS_FBINFO(fbcon.fix.id)); + minfo->fbcon.node, minfo->fbcon.fix.id); /* there is no console on this fb... but we have to initialize hardware * until someone tells me what is proper thing to do */ - if (!ACCESS_FBINFO(initialized)) { + if (!minfo->initialized) { printk(KERN_INFO "fb%d: initializing hardware\n", - ACCESS_FBINFO(fbcon.node)); + minfo->fbcon.node); /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var * already before, so register_framebuffer works correctly. */ vesafb_defined.activate |= FB_ACTIVATE_FORCE; - fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined); + fb_set_var(&minfo->fbcon, &vesafb_defined); } return 0; failVideoIO:; - matroxfb_g450_shutdown(PMINFO2); - mga_iounmap(ACCESS_FBINFO(video.vbase)); + matroxfb_g450_shutdown(minfo); + mga_iounmap(minfo->video.vbase); failCtrlIO:; - mga_iounmap(ACCESS_FBINFO(mmio.vbase)); + mga_iounmap(minfo->mmio.vbase); failVideoMR:; - release_mem_region(video_base_phys, ACCESS_FBINFO(video.len_maximum)); + release_mem_region(video_base_phys, minfo->video.len_maximum); failCtrlMR:; release_mem_region(ctrlptr_phys, 16384); fail:; @@ -1975,7 +1980,7 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv) { static void matroxfb_register_device(struct matrox_fb_info* minfo) { struct matroxfb_driver* drv; int i = 0; - list_add(&ACCESS_FBINFO(next_fb), &matroxfb_list); + list_add(&minfo->next_fb, &matroxfb_list); for (drv = matroxfb_driver_l(matroxfb_driver_list.next); drv != matroxfb_driver_l(&matroxfb_driver_list); drv = matroxfb_driver_l(drv->node.next)) { @@ -1995,7 +2000,7 @@ static void matroxfb_register_device(struct matrox_fb_info* minfo) { static void matroxfb_unregister_device(struct matrox_fb_info* minfo) { int i; - list_del(&ACCESS_FBINFO(next_fb)); + list_del(&minfo->next_fb); for (i = 0; i < minfo->drivers_count; i++) { struct matroxfb_driver* drv = minfo->drivers[i]; @@ -2011,9 +2016,6 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm struct matrox_fb_info* minfo; int err; u_int32_t cmd; -#ifndef CONFIG_FB_MATROX_MULTIHEAD - static int registered = 0; -#endif DBG(__func__) svid = pdev->subsystem_vendor; @@ -2037,68 +2039,57 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm return -1; } -#ifdef CONFIG_FB_MATROX_MULTIHEAD minfo = kmalloc(sizeof(*minfo), GFP_KERNEL); if (!minfo) return -1; -#else - if (registered) /* singlehead driver... */ - return -1; - minfo = &matroxfb_global_mxinfo; -#endif - memset(MINFO, 0, sizeof(*MINFO)); + memset(minfo, 0, sizeof(*minfo)); - ACCESS_FBINFO(pcidev) = pdev; - ACCESS_FBINFO(dead) = 0; - ACCESS_FBINFO(usecount) = 0; - ACCESS_FBINFO(userusecount) = 0; + minfo->pcidev = pdev; + minfo->dead = 0; + minfo->usecount = 0; + minfo->userusecount = 0; - pci_set_drvdata(pdev, MINFO); + pci_set_drvdata(pdev, minfo); /* DEVFLAGS */ - ACCESS_FBINFO(devflags.memtype) = memtype; + minfo->devflags.memtype = memtype; if (memtype != -1) noinit = 0; if (cmd & PCI_COMMAND_MEMORY) { - ACCESS_FBINFO(devflags.novga) = novga; - ACCESS_FBINFO(devflags.nobios) = nobios; - ACCESS_FBINFO(devflags.noinit) = noinit; + minfo->devflags.novga = novga; + minfo->devflags.nobios = nobios; + minfo->devflags.noinit = noinit; /* subsequent heads always needs initialization and must not enable BIOS */ novga = 1; nobios = 1; noinit = 0; } else { - ACCESS_FBINFO(devflags.novga) = 1; - ACCESS_FBINFO(devflags.nobios) = 1; - ACCESS_FBINFO(devflags.noinit) = 0; - } - - ACCESS_FBINFO(devflags.nopciretry) = no_pci_retry; - ACCESS_FBINFO(devflags.mga_24bpp_fix) = inv24; - ACCESS_FBINFO(devflags.precise_width) = option_precise_width; - ACCESS_FBINFO(devflags.sgram) = sgram; - ACCESS_FBINFO(capable.cross4MB) = cross4MB; - - spin_lock_init(&ACCESS_FBINFO(lock.DAC)); - spin_lock_init(&ACCESS_FBINFO(lock.accel)); - init_rwsem(&ACCESS_FBINFO(crtc2.lock)); - init_rwsem(&ACCESS_FBINFO(altout.lock)); - mutex_init(&ACCESS_FBINFO(fbcon).mm_lock); - ACCESS_FBINFO(irq_flags) = 0; - init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); - init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); - ACCESS_FBINFO(crtc1.panpos) = -1; - - err = initMatrox2(PMINFO b); + minfo->devflags.novga = 1; + minfo->devflags.nobios = 1; + minfo->devflags.noinit = 0; + } + + minfo->devflags.nopciretry = no_pci_retry; + minfo->devflags.mga_24bpp_fix = inv24; + minfo->devflags.precise_width = option_precise_width; + minfo->devflags.sgram = sgram; + minfo->capable.cross4MB = cross4MB; + + spin_lock_init(&minfo->lock.DAC); + spin_lock_init(&minfo->lock.accel); + init_rwsem(&minfo->crtc2.lock); + init_rwsem(&minfo->altout.lock); + mutex_init(&minfo->fbcon.mm_lock); + minfo->irq_flags = 0; + init_waitqueue_head(&minfo->crtc1.vsync.wait); + init_waitqueue_head(&minfo->crtc2.vsync.wait); + minfo->crtc1.panpos = -1; + + err = initMatrox2(minfo, b); if (!err) { -#ifndef CONFIG_FB_MATROX_MULTIHEAD - registered = 1; -#endif - matroxfb_register_device(MINFO); + matroxfb_register_device(minfo); return 0; } -#ifdef CONFIG_FB_MATROX_MULTIHEAD kfree(minfo); -#endif return -1; } @@ -2106,7 +2097,7 @@ static void pci_remove_matrox(struct pci_dev* pdev) { struct matrox_fb_info* minfo; minfo = pci_get_drvdata(pdev); - matroxfb_remove(PMINFO 1); + matroxfb_remove(minfo, 1); } static struct pci_device_id matroxfb_devices[] = { @@ -2510,13 +2501,8 @@ module_param(inv24, int, 0); MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)"); module_param(inverse, int, 0); MODULE_PARM_DESC(inverse, "Inverse (0 or 1) (default=0)"); -#ifdef CONFIG_FB_MATROX_MULTIHEAD module_param(dev, int, 0); MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=all working)"); -#else -module_param(dev, int, 0); -MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=first working)"); -#endif module_param(vesa, int, 0); MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)"); module_param(xres, int, 0); diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 95883236c0cd..f3a4e15672d9 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -54,9 +54,6 @@ #include "../macmodes.h" #endif -/* always compile support for 32MB... It cost almost nothing */ -#define CONFIG_FB_MATROX_32MB - #ifdef MATROXFB_DEBUG #define DEBUG @@ -464,9 +461,7 @@ struct matrox_fb_info { int nopciretry; int noinit; int sgram; -#ifdef CONFIG_FB_MATROX_32MB int support32MB; -#endif int accelerator; int text_type_aux; @@ -524,47 +519,11 @@ struct matrox_fb_info { #define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon) -#ifdef CONFIG_FB_MATROX_MULTIHEAD -#define ACCESS_FBINFO2(info, x) (info->x) -#define ACCESS_FBINFO(x) ACCESS_FBINFO2(minfo,x) - -#define MINFO minfo - -#define WPMINFO2 struct matrox_fb_info* minfo -#define WPMINFO WPMINFO2 , -#define CPMINFO2 const struct matrox_fb_info* minfo -#define CPMINFO CPMINFO2 , -#define PMINFO2 minfo -#define PMINFO PMINFO2 , - -#define MINFO_FROM(x) struct matrox_fb_info* minfo = x -#else - -extern struct matrox_fb_info matroxfb_global_mxinfo; - -#define ACCESS_FBINFO(x) (matroxfb_global_mxinfo.x) -#define ACCESS_FBINFO2(info, x) (matroxfb_global_mxinfo.x) - -#define MINFO (&matroxfb_global_mxinfo) - -#define WPMINFO2 void -#define WPMINFO -#define CPMINFO2 void -#define CPMINFO -#define PMINFO2 -#define PMINFO - -#define MINFO_FROM(x) - -#endif - -#define MINFO_FROM_INFO(x) MINFO_FROM(info2minfo(x)) - struct matrox_switch { - int (*preinit)(WPMINFO2); - void (*reset)(WPMINFO2); - int (*init)(WPMINFO struct my_timming*); - void (*restore)(WPMINFO2); + int (*preinit)(struct matrox_fb_info *minfo); + void (*reset)(struct matrox_fb_info *minfo); + int (*init)(struct matrox_fb_info *minfo, struct my_timming*); + void (*restore)(struct matrox_fb_info *minfo); }; struct matroxfb_driver { @@ -727,11 +686,11 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv); #endif #endif -#define mga_inb(addr) mga_readb(ACCESS_FBINFO(mmio.vbase), (addr)) -#define mga_inl(addr) mga_readl(ACCESS_FBINFO(mmio.vbase), (addr)) -#define mga_outb(addr,val) mga_writeb(ACCESS_FBINFO(mmio.vbase), (addr), (val)) -#define mga_outw(addr,val) mga_writew(ACCESS_FBINFO(mmio.vbase), (addr), (val)) -#define mga_outl(addr,val) mga_writel(ACCESS_FBINFO(mmio.vbase), (addr), (val)) +#define mga_inb(addr) mga_readb(minfo->mmio.vbase, (addr)) +#define mga_inl(addr) mga_readl(minfo->mmio.vbase, (addr)) +#define mga_outb(addr,val) mga_writeb(minfo->mmio.vbase, (addr), (val)) +#define mga_outw(addr,val) mga_writew(minfo->mmio.vbase, (addr), (val)) +#define mga_outl(addr,val) mga_writel(minfo->mmio.vbase, (addr), (val)) #define mga_readr(port,idx) (mga_outb((port),(idx)), mga_inb((port)+1)) #define mga_setr(addr,port,val) mga_outw(addr, ((val)<<8) | (port)) @@ -750,19 +709,20 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv); #define isMilleniumII(x) (0) #endif -#define matroxfb_DAC_lock() spin_lock(&ACCESS_FBINFO(lock.DAC)) -#define matroxfb_DAC_unlock() spin_unlock(&ACCESS_FBINFO(lock.DAC)) -#define matroxfb_DAC_lock_irqsave(flags) spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC),flags) -#define matroxfb_DAC_unlock_irqrestore(flags) spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC),flags) -extern void matroxfb_DAC_out(CPMINFO int reg, int val); -extern int matroxfb_DAC_in(CPMINFO int reg); +#define matroxfb_DAC_lock() spin_lock(&minfo->lock.DAC) +#define matroxfb_DAC_unlock() spin_unlock(&minfo->lock.DAC) +#define matroxfb_DAC_lock_irqsave(flags) spin_lock_irqsave(&minfo->lock.DAC, flags) +#define matroxfb_DAC_unlock_irqrestore(flags) spin_unlock_irqrestore(&minfo->lock.DAC, flags) +extern void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg, + int val); +extern int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg); extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt); -extern int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc); -extern int matroxfb_enable_irq(WPMINFO int reenable); +extern int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc); +extern int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable); #ifdef MATROXFB_USE_SPINLOCKS -#define CRITBEGIN spin_lock_irqsave(&ACCESS_FBINFO(lock.accel), critflags); -#define CRITEND spin_unlock_irqrestore(&ACCESS_FBINFO(lock.accel), critflags); +#define CRITBEGIN spin_lock_irqsave(&minfo->lock.accel, critflags); +#define CRITEND spin_unlock_irqrestore(&minfo->lock.accel, critflags); #define CRITFLAGS unsigned long critflags; #else #define CRITBEGIN diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index ebcb5c6b4962..78414baa5a54 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -65,7 +65,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, unsigned int pos) { u_int32_t tmp; u_int32_t datactl; - MINFO_FROM(m2info->primary_dev); + struct matrox_fb_info *minfo = m2info->primary_dev; switch (mode) { case 15: @@ -81,11 +81,11 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, } tmp |= 0x00000001; /* enable CRTC2 */ datactl = 0; - if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) { - if (ACCESS_FBINFO(devflags.g450dac)) { + if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) { + if (minfo->devflags.g450dac) { tmp |= 0x00000006; /* source from secondary pixel PLL */ /* no vidrst when in monitor mode */ - if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { + if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) { tmp |= 0xC0001000; /* Enable H/V vidrst */ } } else { @@ -93,11 +93,11 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, tmp |= 0xC0000000; /* enable vvidrst & hvidrst */ /* MGA TVO is our clock source */ } - } else if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) { + } else if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) { tmp |= 0x00000004; /* source from pixclock */ /* PIXPLL is our clock source */ } - if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) { + if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) { tmp |= 0x00100000; /* connect CRTC2 to DAC */ } if (mt->interlaced) { @@ -146,7 +146,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, } } mga_outl(0x3C10, tmp); - ACCESS_FBINFO(hw).crtc2.ctl = tmp; + minfo->hw.crtc2.ctl = tmp; tmp = mt->VDisplay << 16; /* line compare */ if (mt->sync & FB_SYNC_HOR_HIGH_ACT) @@ -157,10 +157,10 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, } static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) { - MINFO_FROM(m2info->primary_dev); + struct matrox_fb_info *minfo = m2info->primary_dev; mga_outl(0x3C10, 0x00000004); /* disable CRTC2, CRTC1->DAC1, PLL as clock source */ - ACCESS_FBINFO(hw).crtc2.ctl = 0x00000004; + minfo->hw.crtc2.ctl = 0x00000004; } static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info, @@ -168,7 +168,7 @@ static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info, unsigned int pos; unsigned int linelen; unsigned int pixelsize; - MINFO_FROM(m2info->primary_dev); + struct matrox_fb_info *minfo = m2info->primary_dev; m2info->fbcon.var.xoffset = var->xoffset; m2info->fbcon.var.yoffset = var->yoffset; @@ -260,15 +260,15 @@ static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info, static int matroxfb_dh_open(struct fb_info* info, int user) { #define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - MINFO_FROM(m2info->primary_dev); + struct matrox_fb_info *minfo = m2info->primary_dev; - if (MINFO) { + if (minfo) { int err; - if (ACCESS_FBINFO(dead)) { + if (minfo->dead) { return -ENXIO; } - err = ACCESS_FBINFO(fbops).fb_open(&ACCESS_FBINFO(fbcon), user); + err = minfo->fbops.fb_open(&minfo->fbcon, user); if (err) { return err; } @@ -280,10 +280,10 @@ static int matroxfb_dh_open(struct fb_info* info, int user) { static int matroxfb_dh_release(struct fb_info* info, int user) { #define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) int err = 0; - MINFO_FROM(m2info->primary_dev); + struct matrox_fb_info *minfo = m2info->primary_dev; - if (MINFO) { - err = ACCESS_FBINFO(fbops).fb_release(&ACCESS_FBINFO(fbcon), user); + if (minfo) { + err = minfo->fbops.fb_release(&minfo->fbcon, user); } return err; #undef m2info @@ -326,7 +326,7 @@ static int matroxfb_dh_set_par(struct fb_info* info) { int mode; int err; struct fb_var_screeninfo* var = &info->var; - MINFO_FROM(m2info->primary_dev); + struct matrox_fb_info *minfo = m2info->primary_dev; if ((err = matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode)) != 0) return err; @@ -352,39 +352,39 @@ static int matroxfb_dh_set_par(struct fb_info* info) { pos = (m2info->fbcon.var.yoffset * m2info->fbcon.var.xres_virtual + m2info->fbcon.var.xoffset) * m2info->fbcon.var.bits_per_pixel >> 3; pos += m2info->video.offbase; cnt = 0; - down_read(&ACCESS_FBINFO(altout).lock); + down_read(&minfo->altout.lock); for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) { + if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) { cnt++; - if (ACCESS_FBINFO(outputs[out]).output->compute) { - ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt); + if (minfo->outputs[out].output->compute) { + minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt); } } } - ACCESS_FBINFO(crtc2).pixclock = mt.pixclock; - ACCESS_FBINFO(crtc2).mnp = mt.mnp; - up_read(&ACCESS_FBINFO(altout).lock); + minfo->crtc2.pixclock = mt.pixclock; + minfo->crtc2.mnp = mt.mnp; + up_read(&minfo->altout.lock); if (cnt) { matroxfb_dh_restore(m2info, &mt, mode, pos); } else { matroxfb_dh_disable(m2info); } - DAC1064_global_init(PMINFO2); - DAC1064_global_restore(PMINFO2); - down_read(&ACCESS_FBINFO(altout).lock); + DAC1064_global_init(minfo); + DAC1064_global_restore(minfo); + down_read(&minfo->altout.lock); for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 && - ACCESS_FBINFO(outputs[out]).output->program) { - ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data); + if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 && + minfo->outputs[out].output->program) { + minfo->outputs[out].output->program(minfo->outputs[out].data); } } for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 && - ACCESS_FBINFO(outputs[out]).output->start) { - ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data); + if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 && + minfo->outputs[out].output->start) { + minfo->outputs[out].output->start(minfo->outputs[out].data); } } - up_read(&ACCESS_FBINFO(altout).lock); + up_read(&minfo->altout.lock); } m2info->initialized = 1; return 0; @@ -399,9 +399,9 @@ static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, struct fb_info } static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) { - MINFO_FROM(m2info->primary_dev); + struct matrox_fb_info *minfo = m2info->primary_dev; - matroxfb_enable_irq(PMINFO 0); + matroxfb_enable_irq(minfo, 0); memset(vblank, 0, sizeof(*vblank)); vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK; /* mask out reserved bits + field number (odd/even) */ @@ -409,11 +409,11 @@ static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, stru /* compatibility stuff */ if (vblank->vcount >= m2info->fbcon.var.yres) vblank->flags |= FB_VBLANK_VBLANKING; - if (test_bit(0, &ACCESS_FBINFO(irq_flags))) { + if (test_bit(0, &minfo->irq_flags)) { vblank->flags |= FB_VBLANK_HAVE_COUNT; /* Only one writer, aligned int value... it should work without lock and without atomic_t */ - vblank->count = ACCESS_FBINFO(crtc2).vsync.cnt; + vblank->count = minfo->crtc2.vsync.cnt; } return 0; } @@ -423,7 +423,7 @@ static int matroxfb_dh_ioctl(struct fb_info *info, unsigned long arg) { #define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - MINFO_FROM(m2info->primary_dev); + struct matrox_fb_info *minfo = m2info->primary_dev; DBG(__func__) @@ -449,13 +449,13 @@ static int matroxfb_dh_ioctl(struct fb_info *info, if (crt != 0) return -ENODEV; - return matroxfb_wait_for_sync(PMINFO 1); + return matroxfb_wait_for_sync(minfo, 1); } case MATROXFB_SET_OUTPUT_MODE: case MATROXFB_GET_OUTPUT_MODE: case MATROXFB_GET_ALL_OUTPUTS: { - return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(&ACCESS_FBINFO(fbcon), cmd, arg); + return minfo->fbcon.fbops->fb_ioctl(&minfo->fbcon, cmd, arg); } case MATROXFB_SET_OUTPUT_CONNECTION: { @@ -469,9 +469,9 @@ static int matroxfb_dh_ioctl(struct fb_info *info, if (tmp & (1 << out)) { if (out >= MATROXFB_MAX_OUTPUTS) return -ENXIO; - if (!ACCESS_FBINFO(outputs[out]).output) + if (!minfo->outputs[out].output) return -ENXIO; - switch (ACCESS_FBINFO(outputs[out]).src) { + switch (minfo->outputs[out].src) { case MATROXFB_SRC_NONE: case MATROXFB_SRC_CRTC2: break; @@ -480,22 +480,22 @@ static int matroxfb_dh_ioctl(struct fb_info *info, } } } - if (ACCESS_FBINFO(devflags.panellink)) { + if (minfo->devflags.panellink) { if (tmp & MATROXFB_OUTPUT_CONN_DFP) return -EINVAL; - if ((ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) && tmp) + if ((minfo->outputs[2].src == MATROXFB_SRC_CRTC1) && tmp) return -EBUSY; } changes = 0; for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { if (tmp & (1 << out)) { - if (ACCESS_FBINFO(outputs[out]).src != MATROXFB_SRC_CRTC2) { + if (minfo->outputs[out].src != MATROXFB_SRC_CRTC2) { changes = 1; - ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_CRTC2; + minfo->outputs[out].src = MATROXFB_SRC_CRTC2; } - } else if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) { + } else if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) { changes = 1; - ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_NONE; + minfo->outputs[out].src = MATROXFB_SRC_NONE; } } if (!changes) @@ -509,7 +509,7 @@ static int matroxfb_dh_ioctl(struct fb_info *info, int out; for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) { + if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) { conn |= 1 << out; } } @@ -523,8 +523,8 @@ static int matroxfb_dh_ioctl(struct fb_info *info, int out; for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { - if (ACCESS_FBINFO(outputs[out]).output) { - switch (ACCESS_FBINFO(outputs[out]).src) { + if (minfo->outputs[out].output) { + switch (minfo->outputs[out].src) { case MATROXFB_SRC_NONE: case MATROXFB_SRC_CRTC2: tmp |= 1 << out; @@ -532,9 +532,9 @@ static int matroxfb_dh_ioctl(struct fb_info *info, } } } - if (ACCESS_FBINFO(devflags.panellink)) { + if (minfo->devflags.panellink) { tmp &= ~MATROXFB_OUTPUT_CONN_DFP; - if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) { + if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1) { tmp = 0; } } @@ -595,7 +595,9 @@ static struct fb_var_screeninfo matroxfb_dh_defined = { 0, {0,0,0,0,0} }; -static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) { +static int matroxfb_dh_regit(const struct matrox_fb_info *minfo, + struct matroxfb_dh_fb_info *m2info) +{ #define minfo (m2info->primary_dev) void* oldcrtc2; @@ -611,21 +613,21 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) { if (mem < 64*1024) mem *= 1024; mem &= ~0x00000FFF; /* PAGE_MASK? */ - if (ACCESS_FBINFO(video.len_usable) + mem <= ACCESS_FBINFO(video.len)) - m2info->video.offbase = ACCESS_FBINFO(video.len) - mem; - else if (ACCESS_FBINFO(video.len) < mem) { + if (minfo->video.len_usable + mem <= minfo->video.len) + m2info->video.offbase = minfo->video.len - mem; + else if (minfo->video.len < mem) { return -ENOMEM; } else { /* check yres on first head... */ m2info->video.borrowed = mem; - ACCESS_FBINFO(video.len_usable) -= mem; - m2info->video.offbase = ACCESS_FBINFO(video.len_usable); + minfo->video.len_usable -= mem; + m2info->video.offbase = minfo->video.len_usable; } - m2info->video.base = ACCESS_FBINFO(video.base) + m2info->video.offbase; + m2info->video.base = minfo->video.base + m2info->video.offbase; m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem; - m2info->video.vbase.vaddr = vaddr_va(ACCESS_FBINFO(video.vbase)) + m2info->video.offbase; - m2info->mmio.base = ACCESS_FBINFO(mmio.base); - m2info->mmio.vbase = ACCESS_FBINFO(mmio.vbase); - m2info->mmio.len = ACCESS_FBINFO(mmio.len); + m2info->video.vbase.vaddr = vaddr_va(minfo->video.vbase) + m2info->video.offbase; + m2info->mmio.base = minfo->mmio.base; + m2info->mmio.vbase = minfo->mmio.vbase; + m2info->mmio.len = minfo->mmio.len; matroxfb_dh_init_fix(m2info); if (register_framebuffer(&m2info->fbcon)) { @@ -633,10 +635,10 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) { } if (!m2info->initialized) fb_set_var(&m2info->fbcon, &matroxfb_dh_defined); - down_write(&ACCESS_FBINFO(crtc2.lock)); - oldcrtc2 = ACCESS_FBINFO(crtc2.info); - ACCESS_FBINFO(crtc2.info) = m2info; - up_write(&ACCESS_FBINFO(crtc2.lock)); + down_write(&minfo->crtc2.lock); + oldcrtc2 = minfo->crtc2.info; + minfo->crtc2.info = m2info; + up_write(&minfo->crtc2.lock); if (oldcrtc2) { printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n", oldcrtc2); @@ -649,12 +651,12 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) { static int matroxfb_dh_registerfb(struct matroxfb_dh_fb_info* m2info) { #define minfo (m2info->primary_dev) - if (matroxfb_dh_regit(PMINFO m2info)) { + if (matroxfb_dh_regit(minfo, m2info)) { printk(KERN_ERR "matroxfb_crtc2: secondary head failed to register\n"); return -1; } printk(KERN_INFO "matroxfb_crtc2: secondary head of fb%u was registered as fb%u\n", - ACCESS_FBINFO(fbcon.node), m2info->fbcon.node); + minfo->fbcon.node, m2info->fbcon.node); m2info->fbcon_registered = 1; return 0; #undef minfo @@ -666,11 +668,11 @@ static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) { int id; struct matroxfb_dh_fb_info* crtc2; - down_write(&ACCESS_FBINFO(crtc2.lock)); - crtc2 = ACCESS_FBINFO(crtc2.info); + down_write(&minfo->crtc2.lock); + crtc2 = minfo->crtc2.info; if (crtc2 == m2info) - ACCESS_FBINFO(crtc2.info) = NULL; - up_write(&ACCESS_FBINFO(crtc2.lock)); + minfo->crtc2.info = NULL; + up_write(&minfo->crtc2.lock); if (crtc2 != m2info) { printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n", crtc2, m2info); @@ -680,7 +682,7 @@ static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) { id = m2info->fbcon.node; unregister_framebuffer(&m2info->fbcon); /* return memory back to primary head */ - ACCESS_FBINFO(video.len_usable) += m2info->video.borrowed; + minfo->video.len_usable += m2info->video.borrowed; printk(KERN_INFO "matroxfb_crtc2: fb%u unregistered\n", id); m2info->fbcon_registered = 0; } @@ -691,14 +693,14 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) { struct matroxfb_dh_fb_info* m2info; /* hardware is CRTC2 incapable... */ - if (!ACCESS_FBINFO(devflags.crtc2)) + if (!minfo->devflags.crtc2) return NULL; m2info = kzalloc(sizeof(*m2info), GFP_KERNEL); if (!m2info) { printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n"); return NULL; } - m2info->primary_dev = MINFO; + m2info->primary_dev = minfo; if (matroxfb_dh_registerfb(m2info)) { kfree(m2info); printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n"); diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index 6209a761f674..cff0546ea6fd 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -80,52 +80,59 @@ static int get_ctrl_id(__u32 v4l2_id) { return -EINVAL; } -static inline int* get_ctrl_ptr(WPMINFO unsigned int idx) { - return (int*)((char*)MINFO + g450_controls[idx].control); +static inline int *get_ctrl_ptr(struct matrox_fb_info *minfo, unsigned int idx) +{ + return (int*)((char*)minfo + g450_controls[idx].control); } -static void tvo_fill_defaults(WPMINFO2) { +static void tvo_fill_defaults(struct matrox_fb_info *minfo) +{ unsigned int i; for (i = 0; i < G450CTRLS; i++) { - *get_ctrl_ptr(PMINFO i) = g450_controls[i].desc.default_value; + *get_ctrl_ptr(minfo, i) = g450_controls[i].desc.default_value; } } -static int cve2_get_reg(WPMINFO int reg) { +static int cve2_get_reg(struct matrox_fb_info *minfo, int reg) +{ unsigned long flags; int val; matroxfb_DAC_lock_irqsave(flags); - matroxfb_DAC_out(PMINFO 0x87, reg); - val = matroxfb_DAC_in(PMINFO 0x88); + matroxfb_DAC_out(minfo, 0x87, reg); + val = matroxfb_DAC_in(minfo, 0x88); matroxfb_DAC_unlock_irqrestore(flags); return val; } -static void cve2_set_reg(WPMINFO int reg, int val) { +static void cve2_set_reg(struct matrox_fb_info *minfo, int reg, int val) +{ unsigned long flags; matroxfb_DAC_lock_irqsave(flags); - matroxfb_DAC_out(PMINFO 0x87, reg); - matroxfb_DAC_out(PMINFO 0x88, val); + matroxfb_DAC_out(minfo, 0x87, reg); + matroxfb_DAC_out(minfo, 0x88, val); matroxfb_DAC_unlock_irqrestore(flags); } -static void cve2_set_reg10(WPMINFO int reg, int val) { +static void cve2_set_reg10(struct matrox_fb_info *minfo, int reg, int val) +{ unsigned long flags; matroxfb_DAC_lock_irqsave(flags); - matroxfb_DAC_out(PMINFO 0x87, reg); - matroxfb_DAC_out(PMINFO 0x88, val >> 2); - matroxfb_DAC_out(PMINFO 0x87, reg + 1); - matroxfb_DAC_out(PMINFO 0x88, val & 3); + matroxfb_DAC_out(minfo, 0x87, reg); + matroxfb_DAC_out(minfo, 0x88, val >> 2); + matroxfb_DAC_out(minfo, 0x87, reg + 1); + matroxfb_DAC_out(minfo, 0x88, val & 3); matroxfb_DAC_unlock_irqrestore(flags); } -static void g450_compute_bwlevel(CPMINFO int *bl, int *wl) { - const int b = ACCESS_FBINFO(altout.tvo_params.brightness) + BLMIN; - const int c = ACCESS_FBINFO(altout.tvo_params.contrast); +static void g450_compute_bwlevel(const struct matrox_fb_info *minfo, int *bl, + int *wl) +{ + const int b = minfo->altout.tvo_params.brightness + BLMIN; + const int c = minfo->altout.tvo_params.contrast; *bl = max(b - c, BLMIN); *wl = min(b + c, WLMAX); @@ -154,7 +161,7 @@ static int g450_query_ctrl(void* md, struct v4l2_queryctrl *p) { static int g450_set_ctrl(void* md, struct v4l2_control *p) { int i; - MINFO_FROM(md); + struct matrox_fb_info *minfo = md; i = get_ctrl_id(p->id); if (i < 0) return -EINVAL; @@ -162,7 +169,7 @@ static int g450_set_ctrl(void* md, struct v4l2_control *p) { /* * Check if changed. */ - if (p->value == *get_ctrl_ptr(PMINFO i)) return 0; + if (p->value == *get_ctrl_ptr(minfo, i)) return 0; /* * Check limits. @@ -173,31 +180,31 @@ static int g450_set_ctrl(void* md, struct v4l2_control *p) { /* * Store new value. */ - *get_ctrl_ptr(PMINFO i) = p->value; + *get_ctrl_ptr(minfo, i) = p->value; switch (p->id) { case V4L2_CID_BRIGHTNESS: case V4L2_CID_CONTRAST: { int blacklevel, whitelevel; - g450_compute_bwlevel(PMINFO &blacklevel, &whitelevel); - cve2_set_reg10(PMINFO 0x0e, blacklevel); - cve2_set_reg10(PMINFO 0x1e, whitelevel); + g450_compute_bwlevel(minfo, &blacklevel, &whitelevel); + cve2_set_reg10(minfo, 0x0e, blacklevel); + cve2_set_reg10(minfo, 0x1e, whitelevel); } break; case V4L2_CID_SATURATION: - cve2_set_reg(PMINFO 0x20, p->value); - cve2_set_reg(PMINFO 0x22, p->value); + cve2_set_reg(minfo, 0x20, p->value); + cve2_set_reg(minfo, 0x22, p->value); break; case V4L2_CID_HUE: - cve2_set_reg(PMINFO 0x25, p->value); + cve2_set_reg(minfo, 0x25, p->value); break; case MATROXFB_CID_TESTOUT: { - unsigned char val = cve2_get_reg (PMINFO 0x05); + unsigned char val = cve2_get_reg(minfo, 0x05); if (p->value) val |= 0x02; else val &= ~0x02; - cve2_set_reg(PMINFO 0x05, val); + cve2_set_reg(minfo, 0x05, val); } break; } @@ -208,11 +215,11 @@ static int g450_set_ctrl(void* md, struct v4l2_control *p) { static int g450_get_ctrl(void* md, struct v4l2_control *p) { int i; - MINFO_FROM(md); + struct matrox_fb_info *minfo = md; i = get_ctrl_id(p->id); if (i < 0) return -EINVAL; - p->value = *get_ctrl_ptr(PMINFO i); + p->value = *get_ctrl_ptr(minfo, i); return 0; } @@ -226,7 +233,9 @@ struct output_desc { unsigned int v_total; }; -static void computeRegs(WPMINFO struct mavenregs* r, struct my_timming* mt, const struct output_desc* outd) { +static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r, + struct my_timming *mt, const struct output_desc *outd) +{ u_int32_t chromasc; u_int32_t hlen; u_int32_t hsl; @@ -251,10 +260,10 @@ static void computeRegs(WPMINFO struct mavenregs* r, struct my_timming* mt, cons dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic); - mnp = matroxfb_g450_setclk(PMINFO piic, M_VIDEO_PLL); + mnp = matroxfb_g450_setclk(minfo, piic, M_VIDEO_PLL); mt->mnp = mnp; - mt->pixclock = g450_mnp2f(PMINFO mnp); + mt->pixclock = g450_mnp2f(minfo, mnp); dprintk(KERN_DEBUG "MNP=%08X\n", mnp); @@ -490,65 +499,67 @@ static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct outp return; } -#define LR(x) cve2_set_reg(PMINFO (x), m->regs[(x)]) -static void cve2_init_TV(WPMINFO const struct mavenregs* m) { +#define LR(x) cve2_set_reg(minfo, (x), m->regs[(x)]) +static void cve2_init_TV(struct matrox_fb_info *minfo, + const struct mavenregs *m) +{ int i; LR(0x80); LR(0x82); LR(0x83); LR(0x84); LR(0x85); - cve2_set_reg(PMINFO 0x3E, 0x01); + cve2_set_reg(minfo, 0x3E, 0x01); for (i = 0; i < 0x3E; i++) { LR(i); } - cve2_set_reg(PMINFO 0x3E, 0x00); + cve2_set_reg(minfo, 0x3E, 0x00); } static int matroxfb_g450_compute(void* md, struct my_timming* mt) { - MINFO_FROM(md); + struct matrox_fb_info *minfo = md; - dprintk(KERN_DEBUG "Computing, mode=%u\n", ACCESS_FBINFO(outputs[1]).mode); + dprintk(KERN_DEBUG "Computing, mode=%u\n", minfo->outputs[1].mode); if (mt->crtc == MATROXFB_SRC_CRTC2 && - ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { + minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) { const struct output_desc* outd; - cve2_init_TVdata(ACCESS_FBINFO(outputs[1]).mode, &ACCESS_FBINFO(hw).maven, &outd); + cve2_init_TVdata(minfo->outputs[1].mode, &minfo->hw.maven, &outd); { int blacklevel, whitelevel; - g450_compute_bwlevel(PMINFO &blacklevel, &whitelevel); - ACCESS_FBINFO(hw).maven.regs[0x0E] = blacklevel >> 2; - ACCESS_FBINFO(hw).maven.regs[0x0F] = blacklevel & 3; - ACCESS_FBINFO(hw).maven.regs[0x1E] = whitelevel >> 2; - ACCESS_FBINFO(hw).maven.regs[0x1F] = whitelevel & 3; + g450_compute_bwlevel(minfo, &blacklevel, &whitelevel); + minfo->hw.maven.regs[0x0E] = blacklevel >> 2; + minfo->hw.maven.regs[0x0F] = blacklevel & 3; + minfo->hw.maven.regs[0x1E] = whitelevel >> 2; + minfo->hw.maven.regs[0x1F] = whitelevel & 3; - ACCESS_FBINFO(hw).maven.regs[0x20] = - ACCESS_FBINFO(hw).maven.regs[0x22] = ACCESS_FBINFO(altout.tvo_params.saturation); + minfo->hw.maven.regs[0x20] = + minfo->hw.maven.regs[0x22] = minfo->altout.tvo_params.saturation; - ACCESS_FBINFO(hw).maven.regs[0x25] = ACCESS_FBINFO(altout.tvo_params.hue); + minfo->hw.maven.regs[0x25] = minfo->altout.tvo_params.hue; - if (ACCESS_FBINFO(altout.tvo_params.testout)) { - ACCESS_FBINFO(hw).maven.regs[0x05] |= 0x02; + if (minfo->altout.tvo_params.testout) { + minfo->hw.maven.regs[0x05] |= 0x02; } } - computeRegs(PMINFO &ACCESS_FBINFO(hw).maven, mt, outd); + computeRegs(minfo, &minfo->hw.maven, mt, outd); } else if (mt->mnp < 0) { /* We must program clocks before CRTC2, otherwise interlaced mode startup may fail */ - mt->mnp = matroxfb_g450_setclk(PMINFO mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); - mt->pixclock = g450_mnp2f(PMINFO mt->mnp); + mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); + mt->pixclock = g450_mnp2f(minfo, mt->mnp); } dprintk(KERN_DEBUG "Pixclock = %u\n", mt->pixclock); return 0; } static int matroxfb_g450_program(void* md) { - MINFO_FROM(md); + struct matrox_fb_info *minfo = md; - if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { - cve2_init_TV(PMINFO &ACCESS_FBINFO(hw).maven); + if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) { + cve2_init_TV(minfo, &minfo->hw.maven); } return 0; } @@ -564,11 +575,11 @@ static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) { } static int g450_dvi_compute(void* md, struct my_timming* mt) { - MINFO_FROM(md); + struct matrox_fb_info *minfo = md; if (mt->mnp < 0) { - mt->mnp = matroxfb_g450_setclk(PMINFO mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); - mt->pixclock = g450_mnp2f(PMINFO mt->mnp); + mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); + mt->pixclock = g450_mnp2f(minfo, mt->mnp); } return 0; } @@ -588,34 +599,36 @@ static struct matrox_altout matroxfb_g450_dvi = { .compute = g450_dvi_compute, }; -void matroxfb_g450_connect(WPMINFO2) { - if (ACCESS_FBINFO(devflags.g450dac)) { - down_write(&ACCESS_FBINFO(altout.lock)); - tvo_fill_defaults(PMINFO2); - ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; - ACCESS_FBINFO(outputs[1]).data = MINFO; - ACCESS_FBINFO(outputs[1]).output = &matroxfb_g450_altout; - ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; - ACCESS_FBINFO(outputs[2]).src = ACCESS_FBINFO(outputs[2]).default_src; - ACCESS_FBINFO(outputs[2]).data = MINFO; - ACCESS_FBINFO(outputs[2]).output = &matroxfb_g450_dvi; - ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR; - up_write(&ACCESS_FBINFO(altout.lock)); +void matroxfb_g450_connect(struct matrox_fb_info *minfo) +{ + if (minfo->devflags.g450dac) { + down_write(&minfo->altout.lock); + tvo_fill_defaults(minfo); + minfo->outputs[1].src = minfo->outputs[1].default_src; + minfo->outputs[1].data = minfo; + minfo->outputs[1].output = &matroxfb_g450_altout; + minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR; + minfo->outputs[2].src = minfo->outputs[2].default_src; + minfo->outputs[2].data = minfo; + minfo->outputs[2].output = &matroxfb_g450_dvi; + minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR; + up_write(&minfo->altout.lock); } } -void matroxfb_g450_shutdown(WPMINFO2) { - if (ACCESS_FBINFO(devflags.g450dac)) { - down_write(&ACCESS_FBINFO(altout.lock)); - ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE; - ACCESS_FBINFO(outputs[1]).output = NULL; - ACCESS_FBINFO(outputs[1]).data = NULL; - ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; - ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_NONE; - ACCESS_FBINFO(outputs[2]).output = NULL; - ACCESS_FBINFO(outputs[2]).data = NULL; - ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR; - up_write(&ACCESS_FBINFO(altout.lock)); +void matroxfb_g450_shutdown(struct matrox_fb_info *minfo) +{ + if (minfo->devflags.g450dac) { + down_write(&minfo->altout.lock); + minfo->outputs[1].src = MATROXFB_SRC_NONE; + minfo->outputs[1].output = NULL; + minfo->outputs[1].data = NULL; + minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR; + minfo->outputs[2].src = MATROXFB_SRC_NONE; + minfo->outputs[2].output = NULL; + minfo->outputs[2].data = NULL; + minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR; + up_write(&minfo->altout.lock); } } diff --git a/drivers/video/matrox/matroxfb_g450.h b/drivers/video/matrox/matroxfb_g450.h index a0822a6033e5..3a3e654444b8 100644 --- a/drivers/video/matrox/matroxfb_g450.h +++ b/drivers/video/matrox/matroxfb_g450.h @@ -4,11 +4,11 @@ #include "matroxfb_base.h" #ifdef CONFIG_FB_MATROX_G -void matroxfb_g450_connect(WPMINFO2); -void matroxfb_g450_shutdown(WPMINFO2); +void matroxfb_g450_connect(struct matrox_fb_info *minfo); +void matroxfb_g450_shutdown(struct matrox_fb_info *minfo); #else -static inline void matroxfb_g450_connect(WPMINFO2) { }; -static inline void matroxfb_g450_shutdown(WPMINFO2) { }; +static inline void matroxfb_g450_connect(struct matrox_fb_info *minfo) { }; +static inline void matroxfb_g450_shutdown(struct matrox_fb_info *minfo) { }; #endif #endif /* __MATROXFB_G450_H__ */ diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 042408a8c631..91af9159111f 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -458,9 +458,9 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat 0x00, /* 3E written multiple times */ 0x00, /* never written */ }, MATROXFB_OUTPUT_MODE_NTSC, 525, 60 }; - MINFO_FROM(md->primary_head); + struct matrox_fb_info *minfo = md->primary_head; - if (ACCESS_FBINFO(outputs[1]).mode == MATROXFB_OUTPUT_MODE_PAL) + if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_PAL) *data = palregs; else *data = ntscregs; @@ -496,11 +496,11 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat /* Set saturation */ { data->regs[0x20] = - data->regs[0x22] = ACCESS_FBINFO(altout.tvo_params.saturation); + data->regs[0x22] = minfo->altout.tvo_params.saturation; } /* Set HUE */ - data->regs[0x25] = ACCESS_FBINFO(altout.tvo_params.hue); + data->regs[0x25] = minfo->altout.tvo_params.hue; return; } @@ -741,9 +741,9 @@ static inline int maven_compute_timming(struct maven_data* md, struct mavenregs* m) { unsigned int tmpi; unsigned int a, bv, c; - MINFO_FROM(md->primary_head); + struct matrox_fb_info *minfo = md->primary_head; - m->mode = ACCESS_FBINFO(outputs[1]).mode; + m->mode = minfo->outputs[1].mode; if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) { unsigned int lmargin; unsigned int umargin; @@ -1132,7 +1132,7 @@ static int maven_get_control (struct maven_data* md, static int maven_out_compute(void* md, struct my_timming* mt) { #define mdinfo ((struct maven_data*)md) #define minfo (mdinfo->primary_head) - return maven_compute_timming(md, mt, &ACCESS_FBINFO(hw).maven); + return maven_compute_timming(md, mt, &minfo->hw.maven); #undef minfo #undef mdinfo } @@ -1140,7 +1140,7 @@ static int maven_out_compute(void* md, struct my_timming* mt) { static int maven_out_program(void* md) { #define mdinfo ((struct maven_data*)md) #define minfo (mdinfo->primary_head) - return maven_program_timming(md, &ACCESS_FBINFO(hw).maven); + return maven_program_timming(md, &minfo->hw.maven); #undef minfo #undef mdinfo } @@ -1184,16 +1184,18 @@ static struct matrox_altout maven_altout = { static int maven_init_client(struct i2c_client* clnt) { struct maven_data* md = i2c_get_clientdata(clnt); - MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); + struct matrox_fb_info *minfo = container_of(clnt->adapter, + struct i2c_bit_adapter, + adapter)->minfo; - md->primary_head = MINFO; + md->primary_head = minfo; md->client = clnt; - down_write(&ACCESS_FBINFO(altout.lock)); - ACCESS_FBINFO(outputs[1]).output = &maven_altout; - ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; - ACCESS_FBINFO(outputs[1]).data = md; - ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; - up_write(&ACCESS_FBINFO(altout.lock)); + down_write(&minfo->altout.lock); + minfo->outputs[1].output = &maven_altout; + minfo->outputs[1].src = minfo->outputs[1].default_src; + minfo->outputs[1].data = md; + minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR; + up_write(&minfo->altout.lock); if (maven_get_reg(clnt, 0xB2) < 0x14) { md->version = MGATVO_B; /* Tweak some things for this old chip */ @@ -1218,14 +1220,14 @@ static int maven_shutdown_client(struct i2c_client* clnt) { struct maven_data* md = i2c_get_clientdata(clnt); if (md->primary_head) { - MINFO_FROM(md->primary_head); - - down_write(&ACCESS_FBINFO(altout.lock)); - ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE; - ACCESS_FBINFO(outputs[1]).output = NULL; - ACCESS_FBINFO(outputs[1]).data = NULL; - ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; - up_write(&ACCESS_FBINFO(altout.lock)); + struct matrox_fb_info *minfo = md->primary_head; + + down_write(&minfo->altout.lock); + minfo->outputs[1].src = MATROXFB_SRC_NONE; + minfo->outputs[1].output = NULL; + minfo->outputs[1].data = NULL; + minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR; + up_write(&minfo->altout.lock); md->primary_head = NULL; } return 0; diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c index 5b5f072fc1a8..9948ca2a3046 100644 --- a/drivers/video/matrox/matroxfb_misc.c +++ b/drivers/video/matrox/matroxfb_misc.c @@ -89,13 +89,15 @@ #include <linux/interrupt.h> #include <linux/matroxfb.h> -void matroxfb_DAC_out(CPMINFO int reg, int val) { +void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg, int val) +{ DBG_REG(__func__) mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg); mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val); } -int matroxfb_DAC_in(CPMINFO int reg) { +int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg) +{ DBG_REG(__func__) mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg); return mga_inb(M_RAMDAC_BASE+M_X_DATAREG); @@ -184,13 +186,14 @@ int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int f return bestvco; } -int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) { +int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming *m) +{ unsigned int hd, hs, he, hbe, ht; unsigned int vd, vs, ve, vt, lc; unsigned int wd; unsigned int divider; int i; - struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state * const hw = &minfo->hw; DBG(__func__) @@ -240,7 +243,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) { /* standard timmings are in 8pixels, but for interleaved we cannot */ /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */ /* using 16 or more pixels per unit can save us */ - divider = ACCESS_FBINFO(curr.final_bppShift); + divider = minfo->curr.final_bppShift; while (divider & 3) { hd >>= 1; hs >>= 1; @@ -270,7 +273,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) { if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04)) ht++; hbe = ht; - wd = ACCESS_FBINFO(fbcon).var.xres_virtual * ACCESS_FBINFO(curr.final_bppShift) / 64; + wd = minfo->fbcon.var.xres_virtual * minfo->curr.final_bppShift / 64; hw->CRTCEXT[0] = 0; hw->CRTCEXT[5] = 0; @@ -287,7 +290,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) { ((hs & 0x100) >> 6) | /* sync start */ (hbe & 0x040); /* end hor. blanking */ /* FIXME: Enable vidrst only on G400, and only if TV-out is used */ - if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1) + if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1) hw->CRTCEXT[1] |= 0x88; /* enable horizontal and vertical vidrst */ hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) | ((vd & 0x400) >> 8) | /* disp end */ @@ -331,9 +334,10 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) { return 0; }; -void matroxfb_vgaHWrestore(WPMINFO2) { +void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo) +{ int i; - struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw); + struct matrox_hw_state * const hw = &minfo->hw; CRITFLAGS DBG(__func__) @@ -522,7 +526,9 @@ static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) { #endif } -static int parse_pins1(WPMINFO const struct matrox_bios* bd) { +static int parse_pins1(struct matrox_fb_info *minfo, + const struct matrox_bios *bd) +{ unsigned int maxdac; switch (bd->pins[22]) { @@ -533,173 +539,188 @@ static int parse_pins1(WPMINFO const struct matrox_bios* bd) { if (get_unaligned_le16(bd->pins + 24)) { maxdac = get_unaligned_le16(bd->pins + 24) * 10; } - MINFO->limits.pixel.vcomax = maxdac; - MINFO->values.pll.system = get_unaligned_le16(bd->pins + 28) ? + minfo->limits.pixel.vcomax = maxdac; + minfo->values.pll.system = get_unaligned_le16(bd->pins + 28) ? get_unaligned_le16(bd->pins + 28) * 10 : 50000; /* ignore 4MB, 8MB, module clocks */ - MINFO->features.pll.ref_freq = 14318; - MINFO->values.reg.mctlwtst = 0x00030101; + minfo->features.pll.ref_freq = 14318; + minfo->values.reg.mctlwtst = 0x00030101; return 0; } -static void default_pins1(WPMINFO2) { +static void default_pins1(struct matrox_fb_info *minfo) +{ /* Millennium */ - MINFO->limits.pixel.vcomax = 220000; - MINFO->values.pll.system = 50000; - MINFO->features.pll.ref_freq = 14318; - MINFO->values.reg.mctlwtst = 0x00030101; + minfo->limits.pixel.vcomax = 220000; + minfo->values.pll.system = 50000; + minfo->features.pll.ref_freq = 14318; + minfo->values.reg.mctlwtst = 0x00030101; } -static int parse_pins2(WPMINFO const struct matrox_bios* bd) { - MINFO->limits.pixel.vcomax = - MINFO->limits.system.vcomax = (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000); - MINFO->values.reg.mctlwtst = ((bd->pins[51] & 0x01) ? 0x00000001 : 0) | +static int parse_pins2(struct matrox_fb_info *minfo, + const struct matrox_bios *bd) +{ + minfo->limits.pixel.vcomax = + minfo->limits.system.vcomax = (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000); + minfo->values.reg.mctlwtst = ((bd->pins[51] & 0x01) ? 0x00000001 : 0) | ((bd->pins[51] & 0x02) ? 0x00000100 : 0) | ((bd->pins[51] & 0x04) ? 0x00010000 : 0) | ((bd->pins[51] & 0x08) ? 0x00020000 : 0); - MINFO->values.pll.system = (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000); - MINFO->features.pll.ref_freq = 14318; + minfo->values.pll.system = (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000); + minfo->features.pll.ref_freq = 14318; return 0; } -static void default_pins2(WPMINFO2) { +static void default_pins2(struct matrox_fb_info *minfo) +{ /* Millennium II, Mystique */ - MINFO->limits.pixel.vcomax = - MINFO->limits.system.vcomax = 230000; - MINFO->values.reg.mctlwtst = 0x00030101; - MINFO->values.pll.system = 50000; - MINFO->features.pll.ref_freq = 14318; + minfo->limits.pixel.vcomax = + minfo->limits.system.vcomax = 230000; + minfo->values.reg.mctlwtst = 0x00030101; + minfo->values.pll.system = 50000; + minfo->features.pll.ref_freq = 14318; } -static int parse_pins3(WPMINFO const struct matrox_bios* bd) { - MINFO->limits.pixel.vcomax = - MINFO->limits.system.vcomax = (bd->pins[36] == 0xFF) ? 230000 : ((bd->pins[36] + 100) * 1000); - MINFO->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ? +static int parse_pins3(struct matrox_fb_info *minfo, + const struct matrox_bios *bd) +{ + minfo->limits.pixel.vcomax = + minfo->limits.system.vcomax = (bd->pins[36] == 0xFF) ? 230000 : ((bd->pins[36] + 100) * 1000); + minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ? 0x01250A21 : get_unaligned_le32(bd->pins + 48); /* memory config */ - MINFO->values.reg.memrdbk = ((bd->pins[57] << 21) & 0x1E000000) | + minfo->values.reg.memrdbk = ((bd->pins[57] << 21) & 0x1E000000) | ((bd->pins[57] << 22) & 0x00C00000) | ((bd->pins[56] << 1) & 0x000001E0) | ( bd->pins[56] & 0x0000000F); - MINFO->values.reg.opt = (bd->pins[54] & 7) << 10; - MINFO->values.reg.opt2 = bd->pins[58] << 12; - MINFO->features.pll.ref_freq = (bd->pins[52] & 0x20) ? 14318 : 27000; + minfo->values.reg.opt = (bd->pins[54] & 7) << 10; + minfo->values.reg.opt2 = bd->pins[58] << 12; + minfo->features.pll.ref_freq = (bd->pins[52] & 0x20) ? 14318 : 27000; return 0; } -static void default_pins3(WPMINFO2) { +static void default_pins3(struct matrox_fb_info *minfo) +{ /* G100, G200 */ - MINFO->limits.pixel.vcomax = - MINFO->limits.system.vcomax = 230000; - MINFO->values.reg.mctlwtst = 0x01250A21; - MINFO->values.reg.memrdbk = 0x00000000; - MINFO->values.reg.opt = 0x00000C00; - MINFO->values.reg.opt2 = 0x00000000; - MINFO->features.pll.ref_freq = 27000; + minfo->limits.pixel.vcomax = + minfo->limits.system.vcomax = 230000; + minfo->values.reg.mctlwtst = 0x01250A21; + minfo->values.reg.memrdbk = 0x00000000; + minfo->values.reg.opt = 0x00000C00; + minfo->values.reg.opt2 = 0x00000000; + minfo->features.pll.ref_freq = 27000; } -static int parse_pins4(WPMINFO const struct matrox_bios* bd) { - MINFO->limits.pixel.vcomax = (bd->pins[ 39] == 0xFF) ? 230000 : bd->pins[ 39] * 4000; - MINFO->limits.system.vcomax = (bd->pins[ 38] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 38] * 4000; - MINFO->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 71); - MINFO->values.reg.memrdbk = ((bd->pins[87] << 21) & 0x1E000000) | +static int parse_pins4(struct matrox_fb_info *minfo, + const struct matrox_bios *bd) +{ + minfo->limits.pixel.vcomax = (bd->pins[ 39] == 0xFF) ? 230000 : bd->pins[ 39] * 4000; + minfo->limits.system.vcomax = (bd->pins[ 38] == 0xFF) ? minfo->limits.pixel.vcomax : bd->pins[ 38] * 4000; + minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 71); + minfo->values.reg.memrdbk = ((bd->pins[87] << 21) & 0x1E000000) | ((bd->pins[87] << 22) & 0x00C00000) | ((bd->pins[86] << 1) & 0x000001E0) | ( bd->pins[86] & 0x0000000F); - MINFO->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) | + minfo->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) | ((bd->pins[53] << 22) & 0x10000000) | ((bd->pins[53] << 7) & 0x00001C00); - MINFO->values.reg.opt3 = get_unaligned_le32(bd->pins + 67); - MINFO->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000 : bd->pins[ 65] * 4000; - MINFO->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000; + minfo->values.reg.opt3 = get_unaligned_le32(bd->pins + 67); + minfo->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000 : bd->pins[ 65] * 4000; + minfo->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000; return 0; } -static void default_pins4(WPMINFO2) { +static void default_pins4(struct matrox_fb_info *minfo) +{ /* G400 */ - MINFO->limits.pixel.vcomax = - MINFO->limits.system.vcomax = 252000; - MINFO->values.reg.mctlwtst = 0x04A450A1; - MINFO->values.reg.memrdbk = 0x000000E7; - MINFO->values.reg.opt = 0x10000400; - MINFO->values.reg.opt3 = 0x0190A419; - MINFO->values.pll.system = 200000; - MINFO->features.pll.ref_freq = 27000; + minfo->limits.pixel.vcomax = + minfo->limits.system.vcomax = 252000; + minfo->values.reg.mctlwtst = 0x04A450A1; + minfo->values.reg.memrdbk = 0x000000E7; + minfo->values.reg.opt = 0x10000400; + minfo->values.reg.opt3 = 0x0190A419; + minfo->values.pll.system = 200000; + minfo->features.pll.ref_freq = 27000; } -static int parse_pins5(WPMINFO const struct matrox_bios* bd) { +static int parse_pins5(struct matrox_fb_info *minfo, + const struct matrox_bios *bd) +{ unsigned int mult; mult = bd->pins[4]?8000:6000; - MINFO->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult; - MINFO->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 36] * mult; - MINFO->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? MINFO->limits.system.vcomax : bd->pins[ 37] * mult; - MINFO->limits.pixel.vcomin = (bd->pins[123] == 0xFF) ? 256000 : bd->pins[123] * mult; - MINFO->limits.system.vcomin = (bd->pins[121] == 0xFF) ? MINFO->limits.pixel.vcomin : bd->pins[121] * mult; - MINFO->limits.video.vcomin = (bd->pins[122] == 0xFF) ? MINFO->limits.system.vcomin : bd->pins[122] * mult; - MINFO->values.pll.system = - MINFO->values.pll.video = (bd->pins[ 92] == 0xFF) ? 284000 : bd->pins[ 92] * 4000; - MINFO->values.reg.opt = get_unaligned_le32(bd->pins + 48); - MINFO->values.reg.opt2 = get_unaligned_le32(bd->pins + 52); - MINFO->values.reg.opt3 = get_unaligned_le32(bd->pins + 94); - MINFO->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 98); - MINFO->values.reg.memmisc = get_unaligned_le32(bd->pins + 102); - MINFO->values.reg.memrdbk = get_unaligned_le32(bd->pins + 106); - MINFO->features.pll.ref_freq = (bd->pins[110] & 0x01) ? 14318 : 27000; - MINFO->values.memory.ddr = (bd->pins[114] & 0x60) == 0x20; - MINFO->values.memory.dll = (bd->pins[115] & 0x02) != 0; - MINFO->values.memory.emrswen = (bd->pins[115] & 0x01) != 0; - MINFO->values.reg.maccess = MINFO->values.memory.emrswen ? 0x00004000 : 0x00000000; + minfo->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult; + minfo->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? minfo->limits.pixel.vcomax : bd->pins[ 36] * mult; + minfo->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? minfo->limits.system.vcomax : bd->pins[ 37] * mult; + minfo->limits.pixel.vcomin = (bd->pins[123] == 0xFF) ? 256000 : bd->pins[123] * mult; + minfo->limits.system.vcomin = (bd->pins[121] == 0xFF) ? minfo->limits.pixel.vcomin : bd->pins[121] * mult; + minfo->limits.video.vcomin = (bd->pins[122] == 0xFF) ? minfo->limits.system.vcomin : bd->pins[122] * mult; + minfo->values.pll.system = + minfo->values.pll.video = (bd->pins[ 92] == 0xFF) ? 284000 : bd->pins[ 92] * 4000; + minfo->values.reg.opt = get_unaligned_le32(bd->pins + 48); + minfo->values.reg.opt2 = get_unaligned_le32(bd->pins + 52); + minfo->values.reg.opt3 = get_unaligned_le32(bd->pins + 94); + minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 98); + minfo->values.reg.memmisc = get_unaligned_le32(bd->pins + 102); + minfo->values.reg.memrdbk = get_unaligned_le32(bd->pins + 106); + minfo->features.pll.ref_freq = (bd->pins[110] & 0x01) ? 14318 : 27000; + minfo->values.memory.ddr = (bd->pins[114] & 0x60) == 0x20; + minfo->values.memory.dll = (bd->pins[115] & 0x02) != 0; + minfo->values.memory.emrswen = (bd->pins[115] & 0x01) != 0; + minfo->values.reg.maccess = minfo->values.memory.emrswen ? 0x00004000 : 0x00000000; if (bd->pins[115] & 4) { - MINFO->values.reg.mctlwtst_core = MINFO->values.reg.mctlwtst; + minfo->values.reg.mctlwtst_core = minfo->values.reg.mctlwtst; } else { u_int32_t wtst_xlat[] = { 0, 1, 5, 6, 7, 5, 2, 3 }; - MINFO->values.reg.mctlwtst_core = (MINFO->values.reg.mctlwtst & ~7) | - wtst_xlat[MINFO->values.reg.mctlwtst & 7]; + minfo->values.reg.mctlwtst_core = (minfo->values.reg.mctlwtst & ~7) | + wtst_xlat[minfo->values.reg.mctlwtst & 7]; } - MINFO->max_pixel_clock_panellink = bd->pins[47] * 4000; + minfo->max_pixel_clock_panellink = bd->pins[47] * 4000; return 0; } -static void default_pins5(WPMINFO2) { +static void default_pins5(struct matrox_fb_info *minfo) +{ /* Mine 16MB G450 with SDRAM DDR */ - MINFO->limits.pixel.vcomax = - MINFO->limits.system.vcomax = - MINFO->limits.video.vcomax = 600000; - MINFO->limits.pixel.vcomin = - MINFO->limits.system.vcomin = - MINFO->limits.video.vcomin = 256000; - MINFO->values.pll.system = - MINFO->values.pll.video = 284000; - MINFO->values.reg.opt = 0x404A1160; - MINFO->values.reg.opt2 = 0x0000AC00; - MINFO->values.reg.opt3 = 0x0090A409; - MINFO->values.reg.mctlwtst_core = - MINFO->values.reg.mctlwtst = 0x0C81462B; - MINFO->values.reg.memmisc = 0x80000004; - MINFO->values.reg.memrdbk = 0x01001103; - MINFO->features.pll.ref_freq = 27000; - MINFO->values.memory.ddr = 1; - MINFO->values.memory.dll = 1; - MINFO->values.memory.emrswen = 1; - MINFO->values.reg.maccess = 0x00004000; + minfo->limits.pixel.vcomax = + minfo->limits.system.vcomax = + minfo->limits.video.vcomax = 600000; + minfo->limits.pixel.vcomin = + minfo->limits.system.vcomin = + minfo->limits.video.vcomin = 256000; + minfo->values.pll.system = + minfo->values.pll.video = 284000; + minfo->values.reg.opt = 0x404A1160; + minfo->values.reg.opt2 = 0x0000AC00; + minfo->values.reg.opt3 = 0x0090A409; + minfo->values.reg.mctlwtst_core = + minfo->values.reg.mctlwtst = 0x0C81462B; + minfo->values.reg.memmisc = 0x80000004; + minfo->values.reg.memrdbk = 0x01001103; + minfo->features.pll.ref_freq = 27000; + minfo->values.memory.ddr = 1; + minfo->values.memory.dll = 1; + minfo->values.memory.emrswen = 1; + minfo->values.reg.maccess = 0x00004000; } -static int matroxfb_set_limits(WPMINFO const struct matrox_bios* bd) { +static int matroxfb_set_limits(struct matrox_fb_info *minfo, + const struct matrox_bios *bd) +{ unsigned int pins_version; static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 }; - switch (ACCESS_FBINFO(chip)) { - case MGA_2064: default_pins1(PMINFO2); break; + switch (minfo->chip) { + case MGA_2064: default_pins1(minfo); break; case MGA_2164: case MGA_1064: - case MGA_1164: default_pins2(PMINFO2); break; + case MGA_1164: default_pins2(minfo); break; case MGA_G100: - case MGA_G200: default_pins3(PMINFO2); break; - case MGA_G400: default_pins4(PMINFO2); break; + case MGA_G200: default_pins3(minfo); break; + case MGA_G400: default_pins4(minfo); break; case MGA_G450: - case MGA_G550: default_pins5(PMINFO2); break; + case MGA_G550: default_pins5(minfo); break; } if (!bd->bios_valid) { printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOS\n"); @@ -724,38 +745,39 @@ static int matroxfb_set_limits(WPMINFO const struct matrox_bios* bd) { } switch (pins_version) { case 1: - return parse_pins1(PMINFO bd); + return parse_pins1(minfo, bd); case 2: - return parse_pins2(PMINFO bd); + return parse_pins2(minfo, bd); case 3: - return parse_pins3(PMINFO bd); + return parse_pins3(minfo, bd); case 4: - return parse_pins4(PMINFO bd); + return parse_pins4(minfo, bd); case 5: - return parse_pins5(PMINFO bd); + return parse_pins5(minfo, bd); default: printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supported\n", pins_version); return -1; } } -void matroxfb_read_pins(WPMINFO2) { +void matroxfb_read_pins(struct matrox_fb_info *minfo) +{ u32 opt; u32 biosbase; u32 fbbase; - struct pci_dev* pdev = ACCESS_FBINFO(pcidev); + struct pci_dev *pdev = minfo->pcidev; - memset(&ACCESS_FBINFO(bios), 0, sizeof(ACCESS_FBINFO(bios))); + memset(&minfo->bios, 0, sizeof(minfo->bios)); pci_read_config_dword(pdev, PCI_OPTION_REG, &opt); pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM); pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase); - pci_read_config_dword(pdev, ACCESS_FBINFO(devflags.fbResource), &fbbase); + pci_read_config_dword(pdev, minfo->devflags.fbResource, &fbbase); pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE); - parse_bios(vaddr_va(ACCESS_FBINFO(video).vbase), &ACCESS_FBINFO(bios)); + parse_bios(vaddr_va(minfo->video.vbase), &minfo->bios); pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase); pci_write_config_dword(pdev, PCI_OPTION_REG, opt); #ifdef CONFIG_X86 - if (!ACCESS_FBINFO(bios).bios_valid) { + if (!minfo->bios.bios_valid) { unsigned char __iomem* b; b = ioremap(0x000C0000, 65536); @@ -769,25 +791,21 @@ void matroxfb_read_pins(WPMINFO2) { printk(KERN_INFO "matroxfb: Legacy BIOS is for %04X:%04X, while this device is %04X:%04X\n", ven, dev, pdev->vendor, pdev->device); } else { - parse_bios(b, &ACCESS_FBINFO(bios)); + parse_bios(b, &minfo->bios); } iounmap(b); } } #endif - matroxfb_set_limits(PMINFO &ACCESS_FBINFO(bios)); + matroxfb_set_limits(minfo, &minfo->bios); printk(KERN_INFO "PInS memtype = %u\n", - (ACCESS_FBINFO(values).reg.opt & 0x1C00) >> 10); + (minfo->values.reg.opt & 0x1C00) >> 10); } EXPORT_SYMBOL(matroxfb_DAC_in); EXPORT_SYMBOL(matroxfb_DAC_out); EXPORT_SYMBOL(matroxfb_var2my); EXPORT_SYMBOL(matroxfb_PLL_calcclock); -#ifndef CONFIG_FB_MATROX_MULTIHEAD -struct matrox_fb_info matroxfb_global_mxinfo; -EXPORT_SYMBOL(matroxfb_global_mxinfo); -#endif EXPORT_SYMBOL(matroxfb_vgaHWinit); /* DAC1064, Ti3026 */ EXPORT_SYMBOL(matroxfb_vgaHWrestore); /* DAC1064, Ti3026 */ EXPORT_SYMBOL(matroxfb_read_pins); diff --git a/drivers/video/matrox/matroxfb_misc.h b/drivers/video/matrox/matroxfb_misc.h index cb62cc0ead96..351c823f1f74 100644 --- a/drivers/video/matrox/matroxfb_misc.h +++ b/drivers/video/matrox/matroxfb_misc.h @@ -6,13 +6,16 @@ /* also for modules */ int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax, unsigned int* in, unsigned int* feed, unsigned int* post); -static inline int PLL_calcclock(CPMINFO unsigned int freq, unsigned int fmax, - unsigned int* in, unsigned int* feed, unsigned int* post) { - return matroxfb_PLL_calcclock(&ACCESS_FBINFO(features.pll), freq, fmax, in, feed, post); +static inline int PLL_calcclock(const struct matrox_fb_info *minfo, + unsigned int freq, unsigned int fmax, + unsigned int *in, unsigned int *feed, + unsigned int *post) +{ + return matroxfb_PLL_calcclock(&minfo->features.pll, freq, fmax, in, feed, post); } -int matroxfb_vgaHWinit(WPMINFO struct my_timming* m); -void matroxfb_vgaHWrestore(WPMINFO2); -void matroxfb_read_pins(WPMINFO2); +int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming* m); +void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo); +void matroxfb_read_pins(struct matrox_fb_info *minfo); #endif /* __MATROXFB_MISC_H__ */ diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile new file mode 100644 index 000000000000..802d6ae523fb --- /dev/null +++ b/drivers/video/msm/Makefile @@ -0,0 +1,19 @@ + +# core framebuffer +# +obj-y := msm_fb.o + +# MDP DMA/PPP engine +# +obj-y += mdp.o mdp_scale_tables.o mdp_ppp.o + +# MDDI interface +# +obj-y += mddi.o + +# MDDI client/panel drivers +# +obj-y += mddi_client_dummy.o +obj-y += mddi_client_toshiba.o +obj-y += mddi_client_nt35399.o + diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c new file mode 100644 index 000000000000..f2de5a1acd6d --- /dev/null +++ b/drivers/video/msm/mddi.c @@ -0,0 +1,828 @@ +/* + * MSM MDDI Transport + * + * Copyright (C) 2007 Google Incorporated + * Copyright (C) 2007 QUALCOMM Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/spinlock.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <mach/msm_iomap.h> +#include <mach/irqs.h> +#include <mach/board.h> +#include <linux/delay.h> + +#include <mach/msm_fb.h> +#include "mddi_hw.h" + +#define FLAG_DISABLE_HIBERNATION 0x0001 +#define FLAG_HAVE_CAPS 0x0002 +#define FLAG_HAS_VSYNC_IRQ 0x0004 +#define FLAG_HAVE_STATUS 0x0008 + +#define CMD_GET_CLIENT_CAP 0x0601 +#define CMD_GET_CLIENT_STATUS 0x0602 + +union mddi_rev { + unsigned char raw[MDDI_REV_BUFFER_SIZE]; + struct mddi_rev_packet hdr; + struct mddi_client_status status; + struct mddi_client_caps caps; + struct mddi_register_access reg; +}; + +struct reg_read_info { + struct completion done; + uint32_t reg; + uint32_t status; + uint32_t result; +}; + +struct mddi_info { + uint16_t flags; + uint16_t version; + char __iomem *base; + int irq; + struct clk *clk; + struct msm_mddi_client_data client_data; + + /* buffer for rev encap packets */ + void *rev_data; + dma_addr_t rev_addr; + struct mddi_llentry *reg_write_data; + dma_addr_t reg_write_addr; + struct mddi_llentry *reg_read_data; + dma_addr_t reg_read_addr; + size_t rev_data_curr; + + spinlock_t int_lock; + uint32_t int_enable; + uint32_t got_int; + wait_queue_head_t int_wait; + + struct mutex reg_write_lock; + struct mutex reg_read_lock; + struct reg_read_info *reg_read; + + struct mddi_client_caps caps; + struct mddi_client_status status; + + void (*power_client)(struct msm_mddi_client_data *, int); + + /* client device published to bind us to the + * appropriate mddi_client driver + */ + char client_name[20]; + + struct platform_device client_pdev; +}; + +static void mddi_init_rev_encap(struct mddi_info *mddi); + +#define mddi_readl(r) readl(mddi->base + (MDDI_##r)) +#define mddi_writel(v, r) writel((v), mddi->base + (MDDI_##r)) + +void mddi_activate_link(struct msm_mddi_client_data *cdata) +{ + struct mddi_info *mddi = container_of(cdata, struct mddi_info, + client_data); + + mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD); +} + +static void mddi_handle_link_list_done(struct mddi_info *mddi) +{ +} + +static void mddi_reset_rev_encap_ptr(struct mddi_info *mddi) +{ + printk(KERN_INFO "mddi: resetting rev ptr\n"); + mddi->rev_data_curr = 0; + mddi_writel(mddi->rev_addr, REV_PTR); + mddi_writel(mddi->rev_addr, REV_PTR); + mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD); +} + +static void mddi_handle_rev_data(struct mddi_info *mddi, union mddi_rev *rev) +{ + int i; + struct reg_read_info *ri; + + if ((rev->hdr.length <= MDDI_REV_BUFFER_SIZE - 2) && + (rev->hdr.length >= sizeof(struct mddi_rev_packet) - 2)) { + + switch (rev->hdr.type) { + case TYPE_CLIENT_CAPS: + memcpy(&mddi->caps, &rev->caps, + sizeof(struct mddi_client_caps)); + mddi->flags |= FLAG_HAVE_CAPS; + wake_up(&mddi->int_wait); + break; + case TYPE_CLIENT_STATUS: + memcpy(&mddi->status, &rev->status, + sizeof(struct mddi_client_status)); + mddi->flags |= FLAG_HAVE_STATUS; + wake_up(&mddi->int_wait); + break; + case TYPE_REGISTER_ACCESS: + ri = mddi->reg_read; + if (ri == 0) { + printk(KERN_INFO "rev: got reg %x = %x without " + " pending read\n", + rev->reg.register_address, + rev->reg.register_data_list); + break; + } + if (ri->reg != rev->reg.register_address) { + printk(KERN_INFO "rev: got reg %x = %x for " + "wrong register, expected " + "%x\n", + rev->reg.register_address, + rev->reg.register_data_list, ri->reg); + break; + } + mddi->reg_read = NULL; + ri->status = 0; + ri->result = rev->reg.register_data_list; + complete(&ri->done); + break; + default: + printk(KERN_INFO "rev: unknown reverse packet: " + "len=%04x type=%04x CURR_REV_PTR=%x\n", + rev->hdr.length, rev->hdr.type, + mddi_readl(CURR_REV_PTR)); + for (i = 0; i < rev->hdr.length + 2; i++) { + if ((i % 16) == 0) + printk(KERN_INFO "\n"); + printk(KERN_INFO " %02x", rev->raw[i]); + } + printk(KERN_INFO "\n"); + mddi_reset_rev_encap_ptr(mddi); + } + } else { + printk(KERN_INFO "bad rev length, %d, CURR_REV_PTR %x\n", + rev->hdr.length, mddi_readl(CURR_REV_PTR)); + mddi_reset_rev_encap_ptr(mddi); + } +} + +static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask); + +static void mddi_handle_rev_data_avail(struct mddi_info *mddi) +{ + union mddi_rev *rev = mddi->rev_data; + uint32_t rev_data_count; + uint32_t rev_crc_err_count; + int i; + struct reg_read_info *ri; + size_t prev_offset; + uint16_t length; + + union mddi_rev *crev = mddi->rev_data + mddi->rev_data_curr; + + /* clear the interrupt */ + mddi_writel(MDDI_INT_REV_DATA_AVAIL, INT); + rev_data_count = mddi_readl(REV_PKT_CNT); + rev_crc_err_count = mddi_readl(REV_CRC_ERR); + if (rev_data_count > 1) + printk(KERN_INFO "rev_data_count %d\n", rev_data_count); + + if (rev_crc_err_count) { + printk(KERN_INFO "rev_crc_err_count %d, INT %x\n", + rev_crc_err_count, mddi_readl(INT)); + ri = mddi->reg_read; + if (ri == 0) { + printk(KERN_INFO "rev: got crc error without pending " + "read\n"); + } else { + mddi->reg_read = NULL; + ri->status = -EIO; + ri->result = -1; + complete(&ri->done); + } + } + + if (rev_data_count == 0) + return; + + prev_offset = mddi->rev_data_curr; + + length = *((uint8_t *)mddi->rev_data + mddi->rev_data_curr); + mddi->rev_data_curr++; + if (mddi->rev_data_curr == MDDI_REV_BUFFER_SIZE) + mddi->rev_data_curr = 0; + length += *((uint8_t *)mddi->rev_data + mddi->rev_data_curr) << 8; + mddi->rev_data_curr += 1 + length; + if (mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE) + mddi->rev_data_curr = + mddi->rev_data_curr % MDDI_REV_BUFFER_SIZE; + + if (length > MDDI_REV_BUFFER_SIZE - 2) { + printk(KERN_INFO "mddi: rev data length greater than buffer" + "size\n"); + mddi_reset_rev_encap_ptr(mddi); + return; + } + + if (prev_offset + 2 + length >= MDDI_REV_BUFFER_SIZE) { + union mddi_rev tmprev; + size_t rem = MDDI_REV_BUFFER_SIZE - prev_offset; + memcpy(&tmprev.raw[0], mddi->rev_data + prev_offset, rem); + memcpy(&tmprev.raw[rem], mddi->rev_data, 2 + length - rem); + mddi_handle_rev_data(mddi, &tmprev); + } else { + mddi_handle_rev_data(mddi, crev); + } + + if (prev_offset < MDDI_REV_BUFFER_SIZE / 2 && + mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE / 2) { + mddi_writel(mddi->rev_addr, REV_PTR); + } +} + +static irqreturn_t mddi_isr(int irq, void *data) +{ + struct msm_mddi_client_data *cdata = data; + struct mddi_info *mddi = container_of(cdata, struct mddi_info, + client_data); + uint32_t active, status; + + spin_lock(&mddi->int_lock); + + active = mddi_readl(INT); + status = mddi_readl(STAT); + + mddi_writel(active, INT); + + /* ignore any interrupts we have disabled */ + active &= mddi->int_enable; + + mddi->got_int |= active; + wake_up(&mddi->int_wait); + + if (active & MDDI_INT_PRI_LINK_LIST_DONE) { + mddi->int_enable &= (~MDDI_INT_PRI_LINK_LIST_DONE); + mddi_handle_link_list_done(mddi); + } + if (active & MDDI_INT_REV_DATA_AVAIL) + mddi_handle_rev_data_avail(mddi); + + if (active & ~MDDI_INT_NEED_CLEAR) + mddi->int_enable &= ~(active & ~MDDI_INT_NEED_CLEAR); + + if (active & MDDI_INT_LINK_ACTIVE) { + mddi->int_enable &= (~MDDI_INT_LINK_ACTIVE); + mddi->int_enable |= MDDI_INT_IN_HIBERNATION; + } + + if (active & MDDI_INT_IN_HIBERNATION) { + mddi->int_enable &= (~MDDI_INT_IN_HIBERNATION); + mddi->int_enable |= MDDI_INT_LINK_ACTIVE; + } + + mddi_writel(mddi->int_enable, INTEN); + spin_unlock(&mddi->int_lock); + + return IRQ_HANDLED; +} + +static long mddi_wait_interrupt_timeout(struct mddi_info *mddi, + uint32_t intmask, int timeout) +{ + unsigned long irq_flags; + + spin_lock_irqsave(&mddi->int_lock, irq_flags); + mddi->got_int &= ~intmask; + mddi->int_enable |= intmask; + mddi_writel(mddi->int_enable, INTEN); + spin_unlock_irqrestore(&mddi->int_lock, irq_flags); + return wait_event_timeout(mddi->int_wait, mddi->got_int & intmask, + timeout); +} + +static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask) +{ + if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0) + printk(KERN_INFO KERN_ERR "mddi_wait_interrupt %d, timeout " + "waiting for %x, INT = %x, STAT = %x gotint = %x\n", + current->pid, intmask, mddi_readl(INT), mddi_readl(STAT), + mddi->got_int); +} + +static void mddi_init_rev_encap(struct mddi_info *mddi) +{ + memset(mddi->rev_data, 0xee, MDDI_REV_BUFFER_SIZE); + mddi_writel(mddi->rev_addr, REV_PTR); + mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); +} + +void mddi_set_auto_hibernate(struct msm_mddi_client_data *cdata, int on) +{ + struct mddi_info *mddi = container_of(cdata, struct mddi_info, + client_data); + mddi_writel(MDDI_CMD_POWERDOWN, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_IN_HIBERNATION); + mddi_writel(MDDI_CMD_HIBERNATE | !!on, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); +} + + +static uint16_t mddi_init_registers(struct mddi_info *mddi) +{ + mddi_writel(0x0001, VERSION); + mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS); + mddi_writel(0x0003, SPM); /* subframes per media */ + mddi_writel(0x0005, TA1_LEN); + mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN); + mddi_writel(0x0096, DRIVE_HI); + /* 0x32 normal, 0x50 for Toshiba display */ + mddi_writel(0x0050, DRIVE_LO); + mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */ + mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV); + + mddi_writel(MDDI_REV_BUFFER_SIZE, REV_SIZE); + mddi_writel(MDDI_MAX_REV_PKT_SIZE, REV_ENCAP_SZ); + + /* disable periodic rev encap */ + mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + + if (mddi_readl(PAD_CTL) == 0) { + /* If we are turning on band gap, need to wait 5us before + * turning on the rest of the PAD */ + mddi_writel(0x08000, PAD_CTL); + udelay(5); + } + + /* Recommendation from PAD hw team */ + mddi_writel(0xa850f, PAD_CTL); + + + /* Need an even number for counts */ + mddi_writel(0x60006, DRIVER_START_CNT); + + mddi_set_auto_hibernate(&mddi->client_data, 0); + + mddi_writel(MDDI_CMD_DISP_IGNORE, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + + mddi_init_rev_encap(mddi); + return mddi_readl(CORE_VER) & 0xffff; +} + +static void mddi_suspend(struct msm_mddi_client_data *cdata) +{ + struct mddi_info *mddi = container_of(cdata, struct mddi_info, + client_data); + /* turn off the client */ + if (mddi->power_client) + mddi->power_client(&mddi->client_data, 0); + /* turn off the link */ + mddi_writel(MDDI_CMD_RESET, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + /* turn off the clock */ + clk_disable(mddi->clk); +} + +static void mddi_resume(struct msm_mddi_client_data *cdata) +{ + struct mddi_info *mddi = container_of(cdata, struct mddi_info, + client_data); + mddi_set_auto_hibernate(&mddi->client_data, 0); + /* turn on the client */ + if (mddi->power_client) + mddi->power_client(&mddi->client_data, 1); + /* turn on the clock */ + clk_enable(mddi->clk); + /* set up the local registers */ + mddi->rev_data_curr = 0; + mddi_init_registers(mddi); + mddi_writel(mddi->int_enable, INTEN); + mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD); + mddi_writel(MDDI_CMD_SEND_RTD, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + mddi_set_auto_hibernate(&mddi->client_data, 1); +} + +static int __init mddi_get_client_caps(struct mddi_info *mddi) +{ + int i, j; + + /* clear any stale interrupts */ + mddi_writel(0xffffffff, INT); + + mddi->int_enable = MDDI_INT_LINK_ACTIVE | + MDDI_INT_IN_HIBERNATION | + MDDI_INT_PRI_LINK_LIST_DONE | + MDDI_INT_REV_DATA_AVAIL | + MDDI_INT_REV_OVERFLOW | + MDDI_INT_REV_OVERWRITE | + MDDI_INT_RTD_FAILURE; + mddi_writel(mddi->int_enable, INTEN); + + mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + + for (j = 0; j < 3; j++) { + /* the toshiba vga panel does not respond to get + * caps unless you SEND_RTD, but the first SEND_RTD + * will fail... + */ + for (i = 0; i < 4; i++) { + uint32_t stat; + + mddi_writel(MDDI_CMD_SEND_RTD, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + stat = mddi_readl(STAT); + printk(KERN_INFO "mddi cmd send rtd: int %x, stat %x, " + "rtd val %x\n", mddi_readl(INT), stat, + mddi_readl(RTD_VAL)); + if ((stat & MDDI_STAT_RTD_MEAS_FAIL) == 0) + break; + msleep(1); + } + + mddi_writel(CMD_GET_CLIENT_CAP, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + wait_event_timeout(mddi->int_wait, mddi->flags & FLAG_HAVE_CAPS, + HZ / 100); + + if (mddi->flags & FLAG_HAVE_CAPS) + break; + printk(KERN_INFO KERN_ERR "mddi_init, timeout waiting for " + "caps\n"); + } + return mddi->flags & FLAG_HAVE_CAPS; +} + +/* link must be active when this is called */ +int mddi_check_status(struct mddi_info *mddi) +{ + int ret = -1, retry = 3; + mutex_lock(&mddi->reg_read_lock); + mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + + do { + mddi->flags &= ~FLAG_HAVE_STATUS; + mddi_writel(CMD_GET_CLIENT_STATUS, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + wait_event_timeout(mddi->int_wait, + mddi->flags & FLAG_HAVE_STATUS, + HZ / 100); + + if (mddi->flags & FLAG_HAVE_STATUS) { + if (mddi->status.crc_error_count) + printk(KERN_INFO "mddi status: crc_error " + "count: %d\n", + mddi->status.crc_error_count); + else + ret = 0; + break; + } else + printk(KERN_INFO "mddi status: failed to get client " + "status\n"); + mddi_writel(MDDI_CMD_SEND_RTD, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + } while (--retry); + + mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + mutex_unlock(&mddi->reg_read_lock); + return ret; +} + + +void mddi_remote_write(struct msm_mddi_client_data *cdata, uint32_t val, + uint32_t reg) +{ + struct mddi_info *mddi = container_of(cdata, struct mddi_info, + client_data); + struct mddi_llentry *ll; + struct mddi_register_access *ra; + + mutex_lock(&mddi->reg_write_lock); + + ll = mddi->reg_write_data; + + ra = &(ll->u.r); + ra->length = 14 + 4; + ra->type = TYPE_REGISTER_ACCESS; + ra->client_id = 0; + ra->read_write_info = MDDI_WRITE | 1; + ra->crc16 = 0; + + ra->register_address = reg; + ra->register_data_list = val; + + ll->flags = 1; + ll->header_count = 14; + ll->data_count = 4; + ll->data = mddi->reg_write_addr + offsetof(struct mddi_llentry, + u.r.register_data_list); + ll->next = 0; + ll->reserved = 0; + + mddi_writel(mddi->reg_write_addr, PRI_PTR); + + mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE); + mutex_unlock(&mddi->reg_write_lock); +} + +uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg) +{ + struct mddi_info *mddi = container_of(cdata, struct mddi_info, + client_data); + struct mddi_llentry *ll; + struct mddi_register_access *ra; + struct reg_read_info ri; + unsigned s; + int retry_count = 2; + unsigned long irq_flags; + + mutex_lock(&mddi->reg_read_lock); + + ll = mddi->reg_read_data; + + ra = &(ll->u.r); + ra->length = 14; + ra->type = TYPE_REGISTER_ACCESS; + ra->client_id = 0; + ra->read_write_info = MDDI_READ | 1; + ra->crc16 = 0; + + ra->register_address = reg; + + ll->flags = 0x11; + ll->header_count = 14; + ll->data_count = 0; + ll->data = 0; + ll->next = 0; + ll->reserved = 0; + + s = mddi_readl(STAT); + + ri.reg = reg; + ri.status = -1; + + do { + init_completion(&ri.done); + mddi->reg_read = &ri; + mddi_writel(mddi->reg_read_addr, PRI_PTR); + + mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE); + + /* Enable Periodic Reverse Encapsulation. */ + mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + if (wait_for_completion_timeout(&ri.done, HZ/10) == 0 && + !ri.done.done) { + printk(KERN_INFO "mddi_remote_read(%x) timeout " + "(%d %d %d)\n", + reg, ri.status, ri.result, ri.done.done); + spin_lock_irqsave(&mddi->int_lock, irq_flags); + mddi->reg_read = NULL; + spin_unlock_irqrestore(&mddi->int_lock, irq_flags); + ri.status = -1; + ri.result = -1; + } + if (ri.status == 0) + break; + + mddi_writel(MDDI_CMD_SEND_RTD, CMD); + mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + printk(KERN_INFO "mddi_remote_read: failed, sent " + "MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x " + "curr_rev_ptr %x\n", mddi_readl(INT), mddi_readl(STAT), + mddi_readl(RTD_VAL), mddi_readl(CURR_REV_PTR)); + } while (retry_count-- > 0); + /* Disable Periodic Reverse Encapsulation. */ + mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + mddi->reg_read = NULL; + mutex_unlock(&mddi->reg_read_lock); + return ri.result; +} + +static struct mddi_info mddi_info[2]; + +static int __init mddi_clk_setup(struct platform_device *pdev, + struct mddi_info *mddi, + unsigned long clk_rate) +{ + int ret; + + /* set up the clocks */ + mddi->clk = clk_get(&pdev->dev, "mddi_clk"); + if (IS_ERR(mddi->clk)) { + printk(KERN_INFO "mddi: failed to get clock\n"); + return PTR_ERR(mddi->clk); + } + ret = clk_enable(mddi->clk); + if (ret) + goto fail; + ret = clk_set_rate(mddi->clk, clk_rate); + if (ret) + goto fail; + return 0; + +fail: + clk_put(mddi->clk); + return ret; +} + +static int __init mddi_rev_data_setup(struct mddi_info *mddi) +{ + void *dma; + dma_addr_t dma_addr; + + /* set up dma buffer */ + dma = dma_alloc_coherent(NULL, 0x1000, &dma_addr, GFP_KERNEL); + if (dma == 0) + return -ENOMEM; + mddi->rev_data = dma; + mddi->rev_data_curr = 0; + mddi->rev_addr = dma_addr; + mddi->reg_write_data = dma + MDDI_REV_BUFFER_SIZE; + mddi->reg_write_addr = dma_addr + MDDI_REV_BUFFER_SIZE; + mddi->reg_read_data = mddi->reg_write_data + 1; + mddi->reg_read_addr = mddi->reg_write_addr + + sizeof(*mddi->reg_write_data); + return 0; +} + +static int __init mddi_probe(struct platform_device *pdev) +{ + struct msm_mddi_platform_data *pdata = pdev->dev.platform_data; + struct mddi_info *mddi = &mddi_info[pdev->id]; + struct resource *resource; + int ret, i; + + resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!resource) { + printk(KERN_ERR "mddi: no associated mem resource!\n"); + return -ENOMEM; + } + mddi->base = ioremap(resource->start, resource->end - resource->start); + if (!mddi->base) { + printk(KERN_ERR "mddi: failed to remap base!\n"); + ret = -EINVAL; + goto error_ioremap; + } + resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!resource) { + printk(KERN_ERR "mddi: no associated irq resource!\n"); + ret = -EINVAL; + goto error_get_irq_resource; + } + mddi->irq = resource->start; + printk(KERN_INFO "mddi: init() base=0x%p irq=%d\n", mddi->base, + mddi->irq); + mddi->power_client = pdata->power_client; + + mutex_init(&mddi->reg_write_lock); + mutex_init(&mddi->reg_read_lock); + spin_lock_init(&mddi->int_lock); + init_waitqueue_head(&mddi->int_wait); + + ret = mddi_clk_setup(pdev, mddi, pdata->clk_rate); + if (ret) { + printk(KERN_ERR "mddi: failed to setup clock!\n"); + goto error_clk_setup; + } + + ret = mddi_rev_data_setup(mddi); + if (ret) { + printk(KERN_ERR "mddi: failed to setup rev data!\n"); + goto error_rev_data; + } + + mddi->int_enable = 0; + mddi_writel(mddi->int_enable, INTEN); + ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi", + &mddi->client_data); + if (ret) { + printk(KERN_ERR "mddi: failed to request enable irq!\n"); + goto error_request_irq; + } + + /* turn on the mddi client bridge chip */ + if (mddi->power_client) + mddi->power_client(&mddi->client_data, 1); + + /* initialize the mddi registers */ + mddi_set_auto_hibernate(&mddi->client_data, 0); + mddi_writel(MDDI_CMD_RESET, CMD); + mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND); + mddi->version = mddi_init_registers(mddi); + if (mddi->version < 0x20) { + printk(KERN_ERR "mddi: unsupported version 0x%x\n", + mddi->version); + ret = -ENODEV; + goto error_mddi_version; + } + + /* read the capabilities off the client */ + if (!mddi_get_client_caps(mddi)) { + printk(KERN_INFO "mddi: no client found\n"); + /* power down the panel */ + mddi_writel(MDDI_CMD_POWERDOWN, CMD); + printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT)); + msleep(100); + printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT)); + return 0; + } + mddi_set_auto_hibernate(&mddi->client_data, 1); + + if (mddi->caps.Mfr_Name == 0 && mddi->caps.Product_Code == 0) + pdata->fixup(&mddi->caps.Mfr_Name, &mddi->caps.Product_Code); + + mddi->client_pdev.id = 0; + for (i = 0; i < pdata->num_clients; i++) { + if (pdata->client_platform_data[i].product_id == + (mddi->caps.Mfr_Name << 16 | mddi->caps.Product_Code)) { + mddi->client_data.private_client_data = + pdata->client_platform_data[i].client_data; + mddi->client_pdev.name = + pdata->client_platform_data[i].name; + mddi->client_pdev.id = + pdata->client_platform_data[i].id; + /* XXX: possibly set clock */ + break; + } + } + + if (i >= pdata->num_clients) + mddi->client_pdev.name = "mddi_c_dummy"; + printk(KERN_INFO "mddi: registering panel %s\n", + mddi->client_pdev.name); + + mddi->client_data.suspend = mddi_suspend; + mddi->client_data.resume = mddi_resume; + mddi->client_data.activate_link = mddi_activate_link; + mddi->client_data.remote_write = mddi_remote_write; + mddi->client_data.remote_read = mddi_remote_read; + mddi->client_data.auto_hibernate = mddi_set_auto_hibernate; + mddi->client_data.fb_resource = pdata->fb_resource; + if (pdev->id == 0) + mddi->client_data.interface_type = MSM_MDDI_PMDH_INTERFACE; + else if (pdev->id == 1) + mddi->client_data.interface_type = MSM_MDDI_EMDH_INTERFACE; + else { + printk(KERN_ERR "mddi: can not determine interface %d!\n", + pdev->id); + ret = -EINVAL; + goto error_mddi_interface; + } + + mddi->client_pdev.dev.platform_data = &mddi->client_data; + printk(KERN_INFO "mddi: publish: %s\n", mddi->client_name); + platform_device_register(&mddi->client_pdev); + return 0; + +error_mddi_interface: +error_mddi_version: + free_irq(mddi->irq, 0); +error_request_irq: + dma_free_coherent(NULL, 0x1000, mddi->rev_data, mddi->rev_addr); +error_rev_data: +error_clk_setup: +error_get_irq_resource: + iounmap(mddi->base); +error_ioremap: + + printk(KERN_INFO "mddi: mddi_init() failed (%d)\n", ret); + return ret; +} + + +static struct platform_driver mddi_driver = { + .probe = mddi_probe, + .driver = { .name = "msm_mddi" }, +}; + +static int __init _mddi_init(void) +{ + return platform_driver_register(&mddi_driver); +} + +module_init(_mddi_init); diff --git a/drivers/video/msm/mddi_client_dummy.c b/drivers/video/msm/mddi_client_dummy.c new file mode 100644 index 000000000000..ebbae87885b6 --- /dev/null +++ b/drivers/video/msm/mddi_client_dummy.c @@ -0,0 +1,97 @@ +/* drivers/video/msm_fb/mddi_client_dummy.c + * + * Support for "dummy" mddi client devices which require no + * special initialization code. + * + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <mach/msm_fb.h> + +struct panel_info { + struct platform_device pdev; + struct msm_panel_data panel_data; +}; + +static int mddi_dummy_suspend(struct msm_panel_data *panel_data) +{ + return 0; +} + +static int mddi_dummy_resume(struct msm_panel_data *panel_data) +{ + return 0; +} + +static int mddi_dummy_blank(struct msm_panel_data *panel_data) +{ + return 0; +} + +static int mddi_dummy_unblank(struct msm_panel_data *panel_data) +{ + return 0; +} + +static int mddi_dummy_probe(struct platform_device *pdev) +{ + struct msm_mddi_client_data *client_data = pdev->dev.platform_data; + struct panel_info *panel = + kzalloc(sizeof(struct panel_info), GFP_KERNEL); + int ret; + if (!panel) + return -ENOMEM; + platform_set_drvdata(pdev, panel); + panel->panel_data.suspend = mddi_dummy_suspend; + panel->panel_data.resume = mddi_dummy_resume; + panel->panel_data.blank = mddi_dummy_blank; + panel->panel_data.unblank = mddi_dummy_unblank; + panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES; + panel->pdev.name = "msm_panel"; + panel->pdev.id = pdev->id; + platform_device_add_resources(&panel->pdev, + client_data->fb_resource, 1); + panel->panel_data.fb_data = client_data->private_client_data; + panel->pdev.dev.platform_data = &panel->panel_data; + ret = platform_device_register(&panel->pdev); + if (ret) { + kfree(panel); + return ret; + } + return 0; +} + +static int mddi_dummy_remove(struct platform_device *pdev) +{ + struct panel_info *panel = platform_get_drvdata(pdev); + kfree(panel); + return 0; +} + +static struct platform_driver mddi_client_dummy = { + .probe = mddi_dummy_probe, + .remove = mddi_dummy_remove, + .driver = { .name = "mddi_c_dummy" }, +}; + +static int __init mddi_client_dummy_init(void) +{ + platform_driver_register(&mddi_client_dummy); + return 0; +} + +module_init(mddi_client_dummy_init); + diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c new file mode 100644 index 000000000000..9c78050ac799 --- /dev/null +++ b/drivers/video/msm/mddi_client_nt35399.c @@ -0,0 +1,255 @@ +/* drivers/video/msm_fb/mddi_client_nt35399.c + * + * Support for Novatek NT35399 MDDI client of Sapphire + * + * Copyright (C) 2008 HTC Incorporated + * Author: Solomon Chiu (solomon_chiu@htc.com) + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <mach/msm_fb.h> + +static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait); + +struct panel_info { + struct msm_mddi_client_data *client_data; + struct platform_device pdev; + struct msm_panel_data panel_data; + struct msmfb_callback *fb_callback; + struct work_struct panel_work; + struct workqueue_struct *fb_wq; + int nt35399_got_int; +}; + +static void +nt35399_request_vsync(struct msm_panel_data *panel_data, + struct msmfb_callback *callback) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + + panel->fb_callback = callback; + if (panel->nt35399_got_int) { + panel->nt35399_got_int = 0; + client_data->activate_link(client_data); /* clears interrupt */ + } +} + +static void nt35399_wait_vsync(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + + if (panel->nt35399_got_int) { + panel->nt35399_got_int = 0; + client_data->activate_link(client_data); /* clears interrupt */ + } + + if (wait_event_timeout(nt35399_vsync_wait, panel->nt35399_got_int, + HZ/2) == 0) + printk(KERN_ERR "timeout waiting for VSYNC\n"); + + panel->nt35399_got_int = 0; + /* interrupt clears when screen dma starts */ +} + +static int nt35399_suspend(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + int ret; + + ret = bridge_data->uninit(bridge_data, client_data); + if (ret) { + printk(KERN_INFO "mddi nt35399 client: non zero return from " + "uninit\n"); + return ret; + } + client_data->suspend(client_data); + return 0; +} + +static int nt35399_resume(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + int ret; + + client_data->resume(client_data); + ret = bridge_data->init(bridge_data, client_data); + if (ret) + return ret; + return 0; +} + +static int nt35399_blank(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + + return bridge_data->blank(bridge_data, client_data); +} + +static int nt35399_unblank(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + + return bridge_data->unblank(bridge_data, client_data); +} + +irqreturn_t nt35399_vsync_interrupt(int irq, void *data) +{ + struct panel_info *panel = data; + + panel->nt35399_got_int = 1; + + if (panel->fb_callback) { + panel->fb_callback->func(panel->fb_callback); + panel->fb_callback = NULL; + } + + wake_up(&nt35399_vsync_wait); + + return IRQ_HANDLED; +} + +static int setup_vsync(struct panel_info *panel, int init) +{ + int ret; + int gpio = 97; + unsigned int irq; + + if (!init) { + ret = 0; + goto uninit; + } + ret = gpio_request(gpio, "vsync"); + if (ret) + goto err_request_gpio_failed; + + ret = gpio_direction_input(gpio); + if (ret) + goto err_gpio_direction_input_failed; + + ret = irq = gpio_to_irq(gpio); + if (ret < 0) + goto err_get_irq_num_failed; + + ret = request_irq(irq, nt35399_vsync_interrupt, IRQF_TRIGGER_RISING, + "vsync", panel); + if (ret) + goto err_request_irq_failed; + + printk(KERN_INFO "vsync on gpio %d now %d\n", + gpio, gpio_get_value(gpio)); + return 0; + +uninit: + free_irq(gpio_to_irq(gpio), panel->client_data); +err_request_irq_failed: +err_get_irq_num_failed: +err_gpio_direction_input_failed: + gpio_free(gpio); +err_request_gpio_failed: + return ret; +} + +static int mddi_nt35399_probe(struct platform_device *pdev) +{ + struct msm_mddi_client_data *client_data = pdev->dev.platform_data; + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + + int ret; + + struct panel_info *panel = kzalloc(sizeof(struct panel_info), + GFP_KERNEL); + + printk(KERN_DEBUG "%s: enter.\n", __func__); + + if (!panel) + return -ENOMEM; + platform_set_drvdata(pdev, panel); + + ret = setup_vsync(panel, 1); + if (ret) { + dev_err(&pdev->dev, "mddi_nt35399_setup_vsync failed\n"); + return ret; + } + + panel->client_data = client_data; + panel->panel_data.suspend = nt35399_suspend; + panel->panel_data.resume = nt35399_resume; + panel->panel_data.wait_vsync = nt35399_wait_vsync; + panel->panel_data.request_vsync = nt35399_request_vsync; + panel->panel_data.blank = nt35399_blank; + panel->panel_data.unblank = nt35399_unblank; + panel->panel_data.fb_data = &bridge_data->fb_data; + panel->panel_data.caps = 0; + + panel->pdev.name = "msm_panel"; + panel->pdev.id = pdev->id; + panel->pdev.resource = client_data->fb_resource; + panel->pdev.num_resources = 1; + panel->pdev.dev.platform_data = &panel->panel_data; + + if (bridge_data->init) + bridge_data->init(bridge_data, client_data); + + platform_device_register(&panel->pdev); + + return 0; +} + +static int mddi_nt35399_remove(struct platform_device *pdev) +{ + struct panel_info *panel = platform_get_drvdata(pdev); + + setup_vsync(panel, 0); + kfree(panel); + return 0; +} + +static struct platform_driver mddi_client_0bda_8a47 = { + .probe = mddi_nt35399_probe, + .remove = mddi_nt35399_remove, + .driver = { .name = "mddi_c_0bda_8a47" }, +}; + +static int __init mddi_client_nt35399_init(void) +{ + return platform_driver_register(&mddi_client_0bda_8a47); +} + +module_init(mddi_client_nt35399_init); + diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c new file mode 100644 index 000000000000..80d0f5fdf0b1 --- /dev/null +++ b/drivers/video/msm/mddi_client_toshiba.c @@ -0,0 +1,283 @@ +/* drivers/video/msm_fb/mddi_client_toshiba.c + * + * Support for Toshiba TC358720XBG mddi client devices which require no + * special initialization code. + * + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <mach/msm_fb.h> + + +#define LCD_CONTROL_BLOCK_BASE 0x110000 +#define CMN (LCD_CONTROL_BLOCK_BASE|0x10) +#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18) +#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34) +#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C) +#define VPOS (LCD_CONTROL_BLOCK_BASE|0xC0) +#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20) +#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54) +#define WSYN_DLY (LCD_CONTROL_BLOCK_BASE|0x58) +#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C) + +#define BASE5 0x150000 +#define BASE6 0x160000 +#define BASE7 0x170000 + +#define GPIOIEV (BASE5 + 0x10) +#define GPIOIE (BASE5 + 0x14) +#define GPIORIS (BASE5 + 0x18) +#define GPIOMIS (BASE5 + 0x1C) +#define GPIOIC (BASE5 + 0x20) + +#define INTMASK (BASE6 + 0x0C) +#define INTMASK_VWAKEOUT (1U << 0) +#define INTMASK_VWAKEOUT_ACTIVE_LOW (1U << 8) +#define GPIOSEL (BASE7 + 0x00) +#define GPIOSEL_VWAKEINT (1U << 0) + +static DECLARE_WAIT_QUEUE_HEAD(toshiba_vsync_wait); + +struct panel_info { + struct msm_mddi_client_data *client_data; + struct platform_device pdev; + struct msm_panel_data panel_data; + struct msmfb_callback *toshiba_callback; + int toshiba_got_int; +}; + + +static void toshiba_request_vsync(struct msm_panel_data *panel_data, + struct msmfb_callback *callback) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + + panel->toshiba_callback = callback; + if (panel->toshiba_got_int) { + panel->toshiba_got_int = 0; + client_data->activate_link(client_data); + } +} + +static void toshiba_clear_vsync(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + + client_data->activate_link(client_data); +} + +static void toshiba_wait_vsync(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + + if (panel->toshiba_got_int) { + panel->toshiba_got_int = 0; + client_data->activate_link(client_data); /* clears interrupt */ + } + if (wait_event_timeout(toshiba_vsync_wait, panel->toshiba_got_int, + HZ/2) == 0) + printk(KERN_ERR "timeout waiting for VSYNC\n"); + panel->toshiba_got_int = 0; + /* interrupt clears when screen dma starts */ +} + +static int toshiba_suspend(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + int ret; + + ret = bridge_data->uninit(bridge_data, client_data); + if (ret) { + printk(KERN_INFO "mddi toshiba client: non zero return from " + "uninit\n"); + return ret; + } + client_data->suspend(client_data); + return 0; +} + +static int toshiba_resume(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + int ret; + + client_data->resume(client_data); + ret = bridge_data->init(bridge_data, client_data); + if (ret) + return ret; + return 0; +} + +static int toshiba_blank(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + + return bridge_data->blank(bridge_data, client_data); +} + +static int toshiba_unblank(struct msm_panel_data *panel_data) +{ + struct panel_info *panel = container_of(panel_data, struct panel_info, + panel_data); + struct msm_mddi_client_data *client_data = panel->client_data; + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + + return bridge_data->unblank(bridge_data, client_data); +} + +irqreturn_t toshiba_vsync_interrupt(int irq, void *data) +{ + struct panel_info *panel = data; + + panel->toshiba_got_int = 1; + if (panel->toshiba_callback) { + panel->toshiba_callback->func(panel->toshiba_callback); + panel->toshiba_callback = 0; + } + wake_up(&toshiba_vsync_wait); + return IRQ_HANDLED; +} + +static int setup_vsync(struct panel_info *panel, + int init) +{ + int ret; + int gpio = 97; + unsigned int irq; + + if (!init) { + ret = 0; + goto uninit; + } + ret = gpio_request(gpio, "vsync"); + if (ret) + goto err_request_gpio_failed; + + ret = gpio_direction_input(gpio); + if (ret) + goto err_gpio_direction_input_failed; + + ret = irq = gpio_to_irq(gpio); + if (ret < 0) + goto err_get_irq_num_failed; + + ret = request_irq(irq, toshiba_vsync_interrupt, IRQF_TRIGGER_RISING, + "vsync", panel); + if (ret) + goto err_request_irq_failed; + printk(KERN_INFO "vsync on gpio %d now %d\n", + gpio, gpio_get_value(gpio)); + return 0; + +uninit: + free_irq(gpio_to_irq(gpio), panel); +err_request_irq_failed: +err_get_irq_num_failed: +err_gpio_direction_input_failed: + gpio_free(gpio); +err_request_gpio_failed: + return ret; +} + +static int mddi_toshiba_probe(struct platform_device *pdev) +{ + int ret; + struct msm_mddi_client_data *client_data = pdev->dev.platform_data; + struct msm_mddi_bridge_platform_data *bridge_data = + client_data->private_client_data; + struct panel_info *panel = + kzalloc(sizeof(struct panel_info), GFP_KERNEL); + if (!panel) + return -ENOMEM; + platform_set_drvdata(pdev, panel); + + /* mddi_remote_write(mddi, 0, WAKEUP); */ + client_data->remote_write(client_data, GPIOSEL_VWAKEINT, GPIOSEL); + client_data->remote_write(client_data, INTMASK_VWAKEOUT, INTMASK); + + ret = setup_vsync(panel, 1); + if (ret) { + dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n"); + return ret; + } + + panel->client_data = client_data; + panel->panel_data.suspend = toshiba_suspend; + panel->panel_data.resume = toshiba_resume; + panel->panel_data.wait_vsync = toshiba_wait_vsync; + panel->panel_data.request_vsync = toshiba_request_vsync; + panel->panel_data.clear_vsync = toshiba_clear_vsync; + panel->panel_data.blank = toshiba_blank; + panel->panel_data.unblank = toshiba_unblank; + panel->panel_data.fb_data = &bridge_data->fb_data; + panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES; + + panel->pdev.name = "msm_panel"; + panel->pdev.id = pdev->id; + panel->pdev.resource = client_data->fb_resource; + panel->pdev.num_resources = 1; + panel->pdev.dev.platform_data = &panel->panel_data; + bridge_data->init(bridge_data, client_data); + platform_device_register(&panel->pdev); + + return 0; +} + +static int mddi_toshiba_remove(struct platform_device *pdev) +{ + struct panel_info *panel = platform_get_drvdata(pdev); + + setup_vsync(panel, 0); + kfree(panel); + return 0; +} + +static struct platform_driver mddi_client_d263_0000 = { + .probe = mddi_toshiba_probe, + .remove = mddi_toshiba_remove, + .driver = { .name = "mddi_c_d263_0000" }, +}; + +static int __init mddi_client_toshiba_init(void) +{ + platform_driver_register(&mddi_client_d263_0000); + return 0; +} + +module_init(mddi_client_toshiba_init); + diff --git a/drivers/video/msm/mddi_hw.h b/drivers/video/msm/mddi_hw.h new file mode 100644 index 000000000000..45cc01fc1e7f --- /dev/null +++ b/drivers/video/msm/mddi_hw.h @@ -0,0 +1,305 @@ +/* drivers/video/msm_fb/mddi_hw.h + * + * MSM MDDI Hardware Registers and Structures + * + * Copyright (C) 2007 QUALCOMM Incorporated + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _MDDI_HW_H_ +#define _MDDI_HW_H_ + +#include <linux/types.h> + +#define MDDI_CMD 0x0000 +#define MDDI_VERSION 0x0004 +#define MDDI_PRI_PTR 0x0008 +#define MDDI_SEC_PTR 0x000c +#define MDDI_BPS 0x0010 +#define MDDI_SPM 0x0014 +#define MDDI_INT 0x0018 +#define MDDI_INTEN 0x001c +#define MDDI_REV_PTR 0x0020 +#define MDDI_REV_SIZE 0x0024 +#define MDDI_STAT 0x0028 +#define MDDI_REV_RATE_DIV 0x002c +#define MDDI_REV_CRC_ERR 0x0030 +#define MDDI_TA1_LEN 0x0034 +#define MDDI_TA2_LEN 0x0038 +#define MDDI_TEST_BUS 0x003c +#define MDDI_TEST 0x0040 +#define MDDI_REV_PKT_CNT 0x0044 +#define MDDI_DRIVE_HI 0x0048 +#define MDDI_DRIVE_LO 0x004c +#define MDDI_DISP_WAKE 0x0050 +#define MDDI_REV_ENCAP_SZ 0x0054 +#define MDDI_RTD_VAL 0x0058 +#define MDDI_PAD_CTL 0x0068 +#define MDDI_DRIVER_START_CNT 0x006c +#define MDDI_NEXT_PRI_PTR 0x0070 +#define MDDI_NEXT_SEC_PTR 0x0074 +#define MDDI_MISR_CTL 0x0078 +#define MDDI_MISR_DATA 0x007c +#define MDDI_SF_CNT 0x0080 +#define MDDI_MF_CNT 0x0084 +#define MDDI_CURR_REV_PTR 0x0088 +#define MDDI_CORE_VER 0x008c + +#define MDDI_INT_PRI_PTR_READ 0x0001 +#define MDDI_INT_SEC_PTR_READ 0x0002 +#define MDDI_INT_REV_DATA_AVAIL 0x0004 +#define MDDI_INT_DISP_REQ 0x0008 +#define MDDI_INT_PRI_UNDERFLOW 0x0010 +#define MDDI_INT_SEC_UNDERFLOW 0x0020 +#define MDDI_INT_REV_OVERFLOW 0x0040 +#define MDDI_INT_CRC_ERROR 0x0080 +#define MDDI_INT_MDDI_IN 0x0100 +#define MDDI_INT_PRI_OVERWRITE 0x0200 +#define MDDI_INT_SEC_OVERWRITE 0x0400 +#define MDDI_INT_REV_OVERWRITE 0x0800 +#define MDDI_INT_DMA_FAILURE 0x1000 +#define MDDI_INT_LINK_ACTIVE 0x2000 +#define MDDI_INT_IN_HIBERNATION 0x4000 +#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000 +#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000 +#define MDDI_INT_NO_CMD_PKTS_PEND 0x20000 +#define MDDI_INT_RTD_FAILURE 0x40000 +#define MDDI_INT_REV_PKT_RECEIVED 0x80000 +#define MDDI_INT_REV_PKTS_AVAIL 0x100000 + +#define MDDI_INT_NEED_CLEAR ( \ + MDDI_INT_REV_DATA_AVAIL | \ + MDDI_INT_PRI_UNDERFLOW | \ + MDDI_INT_SEC_UNDERFLOW | \ + MDDI_INT_REV_OVERFLOW | \ + MDDI_INT_CRC_ERROR | \ + MDDI_INT_REV_PKT_RECEIVED) + + +#define MDDI_STAT_LINK_ACTIVE 0x0001 +#define MDDI_STAT_NEW_REV_PTR 0x0002 +#define MDDI_STAT_NEW_PRI_PTR 0x0004 +#define MDDI_STAT_NEW_SEC_PTR 0x0008 +#define MDDI_STAT_IN_HIBERNATION 0x0010 +#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020 +#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040 +#define MDDI_STAT_PENDING_TIMING_PKT 0x0080 +#define MDDI_STAT_PENDING_REV_ENCAP 0x0100 +#define MDDI_STAT_PENDING_POWERDOWN 0x0200 +#define MDDI_STAT_RTD_MEAS_FAIL 0x0800 +#define MDDI_STAT_CLIENT_WAKEUP_REQ 0x1000 + + +#define MDDI_CMD_POWERDOWN 0x0100 +#define MDDI_CMD_POWERUP 0x0200 +#define MDDI_CMD_HIBERNATE 0x0300 +#define MDDI_CMD_RESET 0x0400 +#define MDDI_CMD_DISP_IGNORE 0x0501 +#define MDDI_CMD_DISP_LISTEN 0x0500 +#define MDDI_CMD_SEND_REV_ENCAP 0x0600 +#define MDDI_CMD_GET_CLIENT_CAP 0x0601 +#define MDDI_CMD_GET_CLIENT_STATUS 0x0602 +#define MDDI_CMD_SEND_RTD 0x0700 +#define MDDI_CMD_LINK_ACTIVE 0x0900 +#define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00 +#define MDDI_CMD_FORCE_NEW_REV_PTR 0x0C00 + + + +#define MDDI_VIDEO_REV_PKT_SIZE 0x40 +#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60 +#define MDDI_MAX_REV_PKT_SIZE 0x60 + +/* #define MDDI_REV_BUFFER_SIZE 128 */ +#define MDDI_REV_BUFFER_SIZE (MDDI_MAX_REV_PKT_SIZE * 4) + +/* MDP sends 256 pixel packets, so lower value hibernates more without + * significantly increasing latency of waiting for next subframe */ +#define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00 +#define MDDI_HOST_TA2_LEN 0x000c +#define MDDI_HOST_REV_RATE_DIV 0x0002 + + +struct __attribute__((packed)) mddi_rev_packet { + uint16_t length; + uint16_t type; + uint16_t client_id; +}; + +struct __attribute__((packed)) mddi_client_status { + uint16_t length; + uint16_t type; + uint16_t client_id; + uint16_t reverse_link_request; /* bytes needed in rev encap message */ + uint8_t crc_error_count; + uint8_t capability_change; + uint16_t graphics_busy_flags; + uint16_t crc16; +}; + +struct __attribute__((packed)) mddi_client_caps { + uint16_t length; /* length, exclusive of this field */ + uint16_t type; /* 66 */ + uint16_t client_id; + + uint16_t Protocol_Version; + uint16_t Minimum_Protocol_Version; + uint16_t Data_Rate_Capability; + uint8_t Interface_Type_Capability; + uint8_t Number_of_Alt_Displays; + uint16_t PostCal_Data_Rate; + uint16_t Bitmap_Width; + uint16_t Bitmap_Height; + uint16_t Display_Window_Width; + uint16_t Display_Window_Height; + uint32_t Color_Map_Size; + uint16_t Color_Map_RGB_Width; + uint16_t RGB_Capability; + uint8_t Monochrome_Capability; + uint8_t Reserved_1; + uint16_t Y_Cb_Cr_Capability; + uint16_t Bayer_Capability; + uint16_t Alpha_Cursor_Image_Planes; + uint32_t Client_Feature_Capability_Indicators; + uint8_t Maximum_Video_Frame_Rate_Capability; + uint8_t Minimum_Video_Frame_Rate_Capability; + uint16_t Minimum_Sub_frame_Rate; + uint16_t Audio_Buffer_Depth; + uint16_t Audio_Channel_Capability; + uint16_t Audio_Sample_Rate_Capability; + uint8_t Audio_Sample_Resolution; + uint8_t Mic_Audio_Sample_Resolution; + uint16_t Mic_Sample_Rate_Capability; + uint8_t Keyboard_Data_Format; + uint8_t pointing_device_data_format; + uint16_t content_protection_type; + uint16_t Mfr_Name; + uint16_t Product_Code; + uint16_t Reserved_3; + uint32_t Serial_Number; + uint8_t Week_of_Manufacture; + uint8_t Year_of_Manufacture; + + uint16_t crc16; +} mddi_client_capability_type; + + +struct __attribute__((packed)) mddi_video_stream { + uint16_t length; + uint16_t type; /* 16 */ + uint16_t client_id; /* 0 */ + + uint16_t video_data_format_descriptor; +/* format of each pixel in the Pixel Data in the present stream in the + * present packet. + * If bits [15:13] = 000 monochrome + * If bits [15:13] = 001 color pixels (palette). + * If bits [15:13] = 010 color pixels in raw RGB + * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format + * If bits [15:13] = 100 Bayer pixels + */ + + uint16_t pixel_data_attributes; +/* interpreted as follows: + * Bits [1:0] = 11 pixel data is displayed to both eyes + * Bits [1:0] = 10 pixel data is routed to the left eye only. + * Bits [1:0] = 01 pixel data is routed to the right eye only. + * Bits [1:0] = 00 pixel data is routed to the alternate display. + * Bit 2 is 0 Pixel Data is in the standard progressive format. + * Bit 2 is 1 Pixel Data is in interlace format. + * Bit 3 is 0 Pixel Data is in the standard progressive format. + * Bit 3 is 1 Pixel Data is in alternate pixel format. + * Bit 4 is 0 Pixel Data is to or from the display frame buffer. + * Bit 4 is 1 Pixel Data is to or from the camera. + * Bit 5 is 0 pixel data contains the next consecutive row of pixels. + * Bit 5 is 1 X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge, + * X Start, and Y Start parameters are not defined and + * shall be ignored by the client. + * Bits [7:6] = 01 Pixel data is written to the offline image buffer. + * Bits [7:6] = 00 Pixel data is written to the buffer to refresh display. + * Bits [7:6] = 11 Pixel data is written to all image buffers. + * Bits [7:6] = 10 Invalid. Reserved for future use. + * Bits 8 through 11 alternate display number. + * Bits 12 through 14 are reserved for future use and shall be set to zero. + * Bit 15 is 1 the row of pixels is the last row of pixels in a frame. + */ + + uint16_t x_left_edge; + uint16_t y_top_edge; + /* X,Y coordinate of the top left edge of the screen window */ + + uint16_t x_right_edge; + uint16_t y_bottom_edge; + /* X,Y coordinate of the bottom right edge of the window being + * updated. */ + + uint16_t x_start; + uint16_t y_start; + /* (X Start, Y Start) is the first pixel in the Pixel Data field + * below. */ + + uint16_t pixel_count; + /* number of pixels in the Pixel Data field below. */ + + uint16_t parameter_CRC; + /* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */ + + uint16_t reserved; + /* 16-bit variable to make structure align on 4 byte boundary */ +}; + +#define TYPE_VIDEO_STREAM 16 +#define TYPE_CLIENT_CAPS 66 +#define TYPE_REGISTER_ACCESS 146 +#define TYPE_CLIENT_STATUS 70 + +struct __attribute__((packed)) mddi_register_access { + uint16_t length; + uint16_t type; /* 146 */ + uint16_t client_id; + + uint16_t read_write_info; + /* Bits 13:0 a 14-bit unsigned integer that specifies the number of + * 32-bit Register Data List items to be transferred in the + * Register Data List field. + * Bits[15:14] = 00 Write to register(s); + * Bits[15:14] = 10 Read from register(s); + * Bits[15:14] = 11 Response to a Read. + * Bits[15:14] = 01 this value is reserved for future use. */ +#define MDDI_WRITE (0 << 14) +#define MDDI_READ (2 << 14) +#define MDDI_READ_RESP (3 << 14) + + uint32_t register_address; + /* the register address that is to be written to or read from. */ + + uint16_t crc16; + + uint32_t register_data_list; + /* list of 4-byte register data values for/from client registers */ +}; + +struct __attribute__((packed)) mddi_llentry { + uint16_t flags; + uint16_t header_count; + uint16_t data_count; + dma_addr_t data; /* 32 bit */ + struct mddi_llentry *next; + uint16_t reserved; + union { + struct mddi_video_stream v; + struct mddi_register_access r; + uint32_t _[12]; + } u; +}; + +#endif diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c new file mode 100644 index 000000000000..99636a2b20f2 --- /dev/null +++ b/drivers/video/msm/mdp.c @@ -0,0 +1,538 @@ +/* drivers/video/msm_fb/mdp.c + * + * MSM MDP Interface (used by framebuffer core) + * + * Copyright (C) 2007 QUALCOMM Incorporated + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/fb.h> +#include <linux/msm_mdp.h> +#include <linux/interrupt.h> +#include <linux/wait.h> +#include <linux/clk.h> +#include <linux/file.h> +#ifdef CONFIG_ANDROID_PMEM +#include <linux/android_pmem.h> +#endif +#include <linux/major.h> + +#include <mach/msm_iomap.h> +#include <mach/msm_fb.h> +#include <linux/platform_device.h> + +#include "mdp_hw.h" + +struct class *mdp_class; + +#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000) + +static uint16_t mdp_default_ccs[] = { + 0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000, + 0x010, 0x080, 0x080 +}; + +static DECLARE_WAIT_QUEUE_HEAD(mdp_dma2_waitqueue); +static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue); +static struct msmfb_callback *dma_callback; +static struct clk *clk; +static unsigned int mdp_irq_mask; +static DEFINE_SPINLOCK(mdp_lock); +DEFINE_MUTEX(mdp_mutex); + +static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask) +{ + unsigned long irq_flags; + int ret = 0; + + BUG_ON(!mask); + + spin_lock_irqsave(&mdp_lock, irq_flags); + /* if the mask bits are already set return an error, this interrupt + * is already enabled */ + if (mdp_irq_mask & mask) { + printk(KERN_ERR "mdp irq already on already on %x %x\n", + mdp_irq_mask, mask); + ret = -1; + } + /* if the mdp irq is not already enabled enable it */ + if (!mdp_irq_mask) { + if (clk) + clk_enable(clk); + enable_irq(mdp->irq); + } + + /* update the irq mask to reflect the fact that the interrupt is + * enabled */ + mdp_irq_mask |= mask; + spin_unlock_irqrestore(&mdp_lock, irq_flags); + return ret; +} + +static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask) +{ + /* this interrupt is already disabled! */ + if (!(mdp_irq_mask & mask)) { + printk(KERN_ERR "mdp irq already off %x %x\n", + mdp_irq_mask, mask); + return -1; + } + /* update the irq mask to reflect the fact that the interrupt is + * disabled */ + mdp_irq_mask &= ~(mask); + /* if no one is waiting on the interrupt, disable it */ + if (!mdp_irq_mask) { + disable_irq(mdp->irq); + if (clk) + clk_disable(clk); + } + return 0; +} + +static int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask) +{ + unsigned long irq_flags; + int ret; + + spin_lock_irqsave(&mdp_lock, irq_flags); + ret = locked_disable_mdp_irq(mdp, mask); + spin_unlock_irqrestore(&mdp_lock, irq_flags); + return ret; +} + +static irqreturn_t mdp_isr(int irq, void *data) +{ + uint32_t status; + unsigned long irq_flags; + struct mdp_info *mdp = data; + + spin_lock_irqsave(&mdp_lock, irq_flags); + + status = mdp_readl(mdp, MDP_INTR_STATUS); + mdp_writel(mdp, status, MDP_INTR_CLEAR); + + status &= mdp_irq_mask; + if (status & DL0_DMA2_TERM_DONE) { + if (dma_callback) { + dma_callback->func(dma_callback); + dma_callback = NULL; + } + wake_up(&mdp_dma2_waitqueue); + } + + if (status & DL0_ROI_DONE) + wake_up(&mdp_ppp_waitqueue); + + if (status) + locked_disable_mdp_irq(mdp, status); + + spin_unlock_irqrestore(&mdp_lock, irq_flags); + return IRQ_HANDLED; +} + +static uint32_t mdp_check_mask(uint32_t mask) +{ + uint32_t ret; + unsigned long irq_flags; + + spin_lock_irqsave(&mdp_lock, irq_flags); + ret = mdp_irq_mask & mask; + spin_unlock_irqrestore(&mdp_lock, irq_flags); + return ret; +} + +static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq) +{ + int ret = 0; + unsigned long irq_flags; + + wait_event_timeout(*wq, !mdp_check_mask(mask), HZ); + + spin_lock_irqsave(&mdp_lock, irq_flags); + if (mdp_irq_mask & mask) { + locked_disable_mdp_irq(mdp, mask); + printk(KERN_WARNING "timeout waiting for mdp to complete %x\n", + mask); + ret = -ETIMEDOUT; + } + spin_unlock_irqrestore(&mdp_lock, irq_flags); + + return ret; +} + +void mdp_dma_wait(struct mdp_device *mdp_dev) +{ +#define MDP_MAX_TIMEOUTS 20 + static int timeout_count; + struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev); + + if (mdp_wait(mdp, DL0_DMA2_TERM_DONE, &mdp_dma2_waitqueue) == -ETIMEDOUT) + timeout_count++; + else + timeout_count = 0; + + if (timeout_count > MDP_MAX_TIMEOUTS) { + printk(KERN_ERR "mdp: dma failed %d times, somethings wrong!\n", + MDP_MAX_TIMEOUTS); + BUG(); + } +} + +static int mdp_ppp_wait(struct mdp_info *mdp) +{ + return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue); +} + +void mdp_dma_to_mddi(struct mdp_info *mdp, uint32_t addr, uint32_t stride, + uint32_t width, uint32_t height, uint32_t x, uint32_t y, + struct msmfb_callback *callback) +{ + uint32_t dma2_cfg; + uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */ + + if (enable_mdp_irq(mdp, DL0_DMA2_TERM_DONE)) { + printk(KERN_ERR "mdp_dma_to_mddi: busy\n"); + return; + } + + dma_callback = callback; + + dma2_cfg = DMA_PACK_TIGHT | + DMA_PACK_ALIGN_LSB | + DMA_PACK_PATTERN_RGB | + DMA_OUT_SEL_AHB | + DMA_IBUF_NONCONTIGUOUS; + + dma2_cfg |= DMA_IBUF_FORMAT_RGB565; + + dma2_cfg |= DMA_OUT_SEL_MDDI; + + dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY; + + dma2_cfg |= DMA_DITHER_EN; + + /* setup size, address, and stride */ + mdp_writel(mdp, (height << 16) | (width), + MDP_CMD_DEBUG_ACCESS_BASE + 0x0184); + mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188); + mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C); + + /* 666 18BPP */ + dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; + + /* set y & x offset and MDDI transaction parameters */ + mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194); + mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0); + mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM, + MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4); + + mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180); + + /* start DMA2 */ + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044); +} + +void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride, + uint32_t width, uint32_t height, uint32_t x, uint32_t y, + struct msmfb_callback *callback, int interface) +{ + struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev); + + if (interface == MSM_MDDI_PMDH_INTERFACE) { + mdp_dma_to_mddi(mdp, addr, stride, width, height, x, y, + callback); + } +} + +int get_img(struct mdp_img *img, struct fb_info *info, + unsigned long *start, unsigned long *len, + struct file **filep) +{ + int put_needed, ret = 0; + struct file *file; + unsigned long vstart; + +#ifdef CONFIG_ANDROID_PMEM + if (!get_pmem_file(img->memory_id, start, &vstart, len, filep)) + return 0; +#endif + + file = fget_light(img->memory_id, &put_needed); + if (file == NULL) + return -1; + + if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) { + *start = info->fix.smem_start; + *len = info->fix.smem_len; + } else + ret = -1; + fput_light(file, put_needed); + + return ret; +} + +void put_img(struct file *src_file, struct file *dst_file) +{ +#ifdef CONFIG_ANDROID_PMEM + if (src_file) + put_pmem_file(src_file); + if (dst_file) + put_pmem_file(dst_file); +#endif +} + +int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb, + struct mdp_blit_req *req) +{ + int ret; + unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0; + struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev); + struct file *src_file = 0, *dst_file = 0; + + /* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */ + if (unlikely(req->src_rect.h == 0 || + req->src_rect.w == 0)) { + printk(KERN_ERR "mpd_ppp: src img of zero size!\n"); + return -EINVAL; + } + if (unlikely(req->dst_rect.h == 0 || + req->dst_rect.w == 0)) + return -EINVAL; + + /* do this first so that if this fails, the caller can always + * safely call put_img */ + if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) { + printk(KERN_ERR "mpd_ppp: could not retrieve src image from " + "memory\n"); + return -EINVAL; + } + + if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) { + printk(KERN_ERR "mpd_ppp: could not retrieve dst image from " + "memory\n"); +#ifdef CONFIG_ANDROID_PMEM + put_pmem_file(src_file); +#endif + return -EINVAL; + } + mutex_lock(&mdp_mutex); + + /* transp_masking unimplemented */ + req->transp_mask = MDP_TRANSP_NOP; + if (unlikely((req->transp_mask != MDP_TRANSP_NOP || + req->alpha != MDP_ALPHA_NOP || + HAS_ALPHA(req->src.format)) && + (req->flags & MDP_ROT_90 && + req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) { + int i; + unsigned int tiles = req->dst_rect.h / 16; + unsigned int remainder = req->dst_rect.h % 16; + req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h; + req->dst_rect.h = 16; + for (i = 0; i < tiles; i++) { + enable_mdp_irq(mdp, DL0_ROI_DONE); + ret = mdp_ppp_blit(mdp, req, src_file, src_start, + src_len, dst_file, dst_start, + dst_len); + if (ret) + goto err_bad_blit; + ret = mdp_ppp_wait(mdp); + if (ret) + goto err_wait_failed; + req->dst_rect.y += 16; + req->src_rect.x += req->src_rect.w; + } + if (!remainder) + goto end; + req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h; + req->dst_rect.h = remainder; + } + enable_mdp_irq(mdp, DL0_ROI_DONE); + ret = mdp_ppp_blit(mdp, req, src_file, src_start, src_len, dst_file, + dst_start, + dst_len); + if (ret) + goto err_bad_blit; + ret = mdp_ppp_wait(mdp); + if (ret) + goto err_wait_failed; +end: + put_img(src_file, dst_file); + mutex_unlock(&mdp_mutex); + return 0; +err_bad_blit: + disable_mdp_irq(mdp, DL0_ROI_DONE); +err_wait_failed: + put_img(src_file, dst_file); + mutex_unlock(&mdp_mutex); + return ret; +} + +void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id) +{ + struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev); + + disp_id &= 0xf; + mdp_writel(mdp, disp_id, MDP_FULL_BYPASS_WORD43); +} + +int register_mdp_client(struct class_interface *cint) +{ + if (!mdp_class) { + pr_err("mdp: no mdp_class when registering mdp client\n"); + return -ENODEV; + } + cint->class = mdp_class; + return class_interface_register(cint); +} + +#include "mdp_csc_table.h" +#include "mdp_scale_tables.h" + +int mdp_probe(struct platform_device *pdev) +{ + struct resource *resource; + int ret; + int n; + struct mdp_info *mdp; + + resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!resource) { + pr_err("mdp: can not get mdp mem resource!\n"); + return -ENOMEM; + } + + mdp = kzalloc(sizeof(struct mdp_info), GFP_KERNEL); + if (!mdp) + return -ENOMEM; + + mdp->irq = platform_get_irq(pdev, 0); + if (mdp->irq < 0) { + pr_err("mdp: can not get mdp irq\n"); + ret = mdp->irq; + goto error_get_irq; + } + + mdp->base = ioremap(resource->start, + resource->end - resource->start); + if (mdp->base == 0) { + printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n"); + ret = -ENOMEM; + goto error_ioremap; + } + + mdp->mdp_dev.dma = mdp_dma; + mdp->mdp_dev.dma_wait = mdp_dma_wait; + mdp->mdp_dev.blit = mdp_blit; + mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp; + + clk = clk_get(&pdev->dev, "mdp_clk"); + if (IS_ERR(clk)) { + printk(KERN_INFO "mdp: failed to get mdp clk"); + return PTR_ERR(clk); + } + + ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp); + if (ret) + goto error_request_irq; + disable_irq(mdp->irq); + mdp_irq_mask = 0; + + /* debug interface write access */ + mdp_writel(mdp, 1, 0x60); + + mdp_writel(mdp, MDP_ANY_INTR_MASK, MDP_INTR_ENABLE); + mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE); + + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc); + + for (n = 0; n < ARRAY_SIZE(csc_table); n++) + mdp_writel(mdp, csc_table[n].val, csc_table[n].reg); + + /* clear up unused fg/main registers */ + /* comp.plane 2&3 ystride */ + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120); + + /* unpacked pattern */ + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c); + + /* comp.plane 2 & 3 */ + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118); + + /* clear unused bg registers */ + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0); + mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4); + + for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++) + mdp_writel(mdp, mdp_upscale_table[n].val, + mdp_upscale_table[n].reg); + + for (n = 0; n < 9; n++) + mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n); + mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0); + mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0); + mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0); + + /* register mdp device */ + mdp->mdp_dev.dev.parent = &pdev->dev; + mdp->mdp_dev.dev.class = mdp_class; + snprintf(mdp->mdp_dev.dev.bus_id, BUS_ID_SIZE, "mdp%d", pdev->id); + + /* if you can remove the platform device you'd have to implement + * this: + mdp_dev.release = mdp_class; */ + + ret = device_register(&mdp->mdp_dev.dev); + if (ret) + goto error_device_register; + return 0; + +error_device_register: + free_irq(mdp->irq, mdp); +error_request_irq: + iounmap(mdp->base); +error_get_irq: +error_ioremap: + kfree(mdp); + return ret; +} + +static struct platform_driver msm_mdp_driver = { + .probe = mdp_probe, + .driver = {.name = "msm_mdp"}, +}; + +static int __init mdp_init(void) +{ + mdp_class = class_create(THIS_MODULE, "msm_mdp"); + if (IS_ERR(mdp_class)) { + printk(KERN_ERR "Error creating mdp class\n"); + return PTR_ERR(mdp_class); + } + return platform_driver_register(&msm_mdp_driver); +} + +subsys_initcall(mdp_init); diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/msm/mdp_csc_table.h new file mode 100644 index 000000000000..d1cde30ead52 --- /dev/null +++ b/drivers/video/msm/mdp_csc_table.h @@ -0,0 +1,582 @@ +/* drivers/video/msm_fb/mdp_csc_table.h + * + * Copyright (C) 2007 QUALCOMM Incorporated + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +static struct { + uint32_t reg; + uint32_t val; +} csc_table[] = { + { 0x40400, 0x83 }, + { 0x40404, 0x102 }, + { 0x40408, 0x32 }, + { 0x4040c, 0xffffffb5 }, + { 0x40410, 0xffffff6c }, + { 0x40414, 0xe1 }, + { 0x40418, 0xe1 }, + { 0x4041c, 0xffffff45 }, + { 0x40420, 0xffffffdc }, + { 0x40440, 0x254 }, + { 0x40444, 0x0 }, + { 0x40448, 0x331 }, + { 0x4044c, 0x254 }, + { 0x40450, 0xffffff38 }, + { 0x40454, 0xfffffe61 }, + { 0x40458, 0x254 }, + { 0x4045c, 0x409 }, + { 0x40460, 0x0 }, + { 0x40480, 0x5d }, + { 0x40484, 0x13a }, + { 0x40488, 0x20 }, + { 0x4048c, 0xffffffcd }, + { 0x40490, 0xffffff54 }, + { 0x40494, 0xe1 }, + { 0x40498, 0xe1 }, + { 0x4049c, 0xffffff35 }, + { 0x404a0, 0xffffffec }, + { 0x404c0, 0x254 }, + { 0x404c4, 0x0 }, + { 0x404c8, 0x396 }, + { 0x404cc, 0x254 }, + { 0x404d0, 0xffffff94 }, + { 0x404d4, 0xfffffef0 }, + { 0x404d8, 0x254 }, + { 0x404dc, 0x43a }, + { 0x404e0, 0x0 }, + { 0x40500, 0x10 }, + { 0x40504, 0x80 }, + { 0x40508, 0x80 }, + { 0x40540, 0x10 }, + { 0x40544, 0x80 }, + { 0x40548, 0x80 }, + { 0x40580, 0x10 }, + { 0x40584, 0xeb }, + { 0x40588, 0x10 }, + { 0x4058c, 0xf0 }, + { 0x405c0, 0x10 }, + { 0x405c4, 0xeb }, + { 0x405c8, 0x10 }, + { 0x405cc, 0xf0 }, + { 0x40800, 0x0 }, + { 0x40804, 0x151515 }, + { 0x40808, 0x1d1d1d }, + { 0x4080c, 0x232323 }, + { 0x40810, 0x272727 }, + { 0x40814, 0x2b2b2b }, + { 0x40818, 0x2f2f2f }, + { 0x4081c, 0x333333 }, + { 0x40820, 0x363636 }, + { 0x40824, 0x393939 }, + { 0x40828, 0x3b3b3b }, + { 0x4082c, 0x3e3e3e }, + { 0x40830, 0x404040 }, + { 0x40834, 0x434343 }, + { 0x40838, 0x454545 }, + { 0x4083c, 0x474747 }, + { 0x40840, 0x494949 }, + { 0x40844, 0x4b4b4b }, + { 0x40848, 0x4d4d4d }, + { 0x4084c, 0x4f4f4f }, + { 0x40850, 0x515151 }, + { 0x40854, 0x535353 }, + { 0x40858, 0x555555 }, + { 0x4085c, 0x565656 }, + { 0x40860, 0x585858 }, + { 0x40864, 0x5a5a5a }, + { 0x40868, 0x5b5b5b }, + { 0x4086c, 0x5d5d5d }, + { 0x40870, 0x5e5e5e }, + { 0x40874, 0x606060 }, + { 0x40878, 0x616161 }, + { 0x4087c, 0x636363 }, + { 0x40880, 0x646464 }, + { 0x40884, 0x666666 }, + { 0x40888, 0x676767 }, + { 0x4088c, 0x686868 }, + { 0x40890, 0x6a6a6a }, + { 0x40894, 0x6b6b6b }, + { 0x40898, 0x6c6c6c }, + { 0x4089c, 0x6e6e6e }, + { 0x408a0, 0x6f6f6f }, + { 0x408a4, 0x707070 }, + { 0x408a8, 0x717171 }, + { 0x408ac, 0x727272 }, + { 0x408b0, 0x747474 }, + { 0x408b4, 0x757575 }, + { 0x408b8, 0x767676 }, + { 0x408bc, 0x777777 }, + { 0x408c0, 0x787878 }, + { 0x408c4, 0x797979 }, + { 0x408c8, 0x7a7a7a }, + { 0x408cc, 0x7c7c7c }, + { 0x408d0, 0x7d7d7d }, + { 0x408d4, 0x7e7e7e }, + { 0x408d8, 0x7f7f7f }, + { 0x408dc, 0x808080 }, + { 0x408e0, 0x818181 }, + { 0x408e4, 0x828282 }, + { 0x408e8, 0x838383 }, + { 0x408ec, 0x848484 }, + { 0x408f0, 0x858585 }, + { 0x408f4, 0x868686 }, + { 0x408f8, 0x878787 }, + { 0x408fc, 0x888888 }, + { 0x40900, 0x898989 }, + { 0x40904, 0x8a8a8a }, + { 0x40908, 0x8b8b8b }, + { 0x4090c, 0x8c8c8c }, + { 0x40910, 0x8d8d8d }, + { 0x40914, 0x8e8e8e }, + { 0x40918, 0x8f8f8f }, + { 0x4091c, 0x8f8f8f }, + { 0x40920, 0x909090 }, + { 0x40924, 0x919191 }, + { 0x40928, 0x929292 }, + { 0x4092c, 0x939393 }, + { 0x40930, 0x949494 }, + { 0x40934, 0x959595 }, + { 0x40938, 0x969696 }, + { 0x4093c, 0x969696 }, + { 0x40940, 0x979797 }, + { 0x40944, 0x989898 }, + { 0x40948, 0x999999 }, + { 0x4094c, 0x9a9a9a }, + { 0x40950, 0x9b9b9b }, + { 0x40954, 0x9c9c9c }, + { 0x40958, 0x9c9c9c }, + { 0x4095c, 0x9d9d9d }, + { 0x40960, 0x9e9e9e }, + { 0x40964, 0x9f9f9f }, + { 0x40968, 0xa0a0a0 }, + { 0x4096c, 0xa0a0a0 }, + { 0x40970, 0xa1a1a1 }, + { 0x40974, 0xa2a2a2 }, + { 0x40978, 0xa3a3a3 }, + { 0x4097c, 0xa4a4a4 }, + { 0x40980, 0xa4a4a4 }, + { 0x40984, 0xa5a5a5 }, + { 0x40988, 0xa6a6a6 }, + { 0x4098c, 0xa7a7a7 }, + { 0x40990, 0xa7a7a7 }, + { 0x40994, 0xa8a8a8 }, + { 0x40998, 0xa9a9a9 }, + { 0x4099c, 0xaaaaaa }, + { 0x409a0, 0xaaaaaa }, + { 0x409a4, 0xababab }, + { 0x409a8, 0xacacac }, + { 0x409ac, 0xadadad }, + { 0x409b0, 0xadadad }, + { 0x409b4, 0xaeaeae }, + { 0x409b8, 0xafafaf }, + { 0x409bc, 0xafafaf }, + { 0x409c0, 0xb0b0b0 }, + { 0x409c4, 0xb1b1b1 }, + { 0x409c8, 0xb2b2b2 }, + { 0x409cc, 0xb2b2b2 }, + { 0x409d0, 0xb3b3b3 }, + { 0x409d4, 0xb4b4b4 }, + { 0x409d8, 0xb4b4b4 }, + { 0x409dc, 0xb5b5b5 }, + { 0x409e0, 0xb6b6b6 }, + { 0x409e4, 0xb6b6b6 }, + { 0x409e8, 0xb7b7b7 }, + { 0x409ec, 0xb8b8b8 }, + { 0x409f0, 0xb8b8b8 }, + { 0x409f4, 0xb9b9b9 }, + { 0x409f8, 0xbababa }, + { 0x409fc, 0xbababa }, + { 0x40a00, 0xbbbbbb }, + { 0x40a04, 0xbcbcbc }, + { 0x40a08, 0xbcbcbc }, + { 0x40a0c, 0xbdbdbd }, + { 0x40a10, 0xbebebe }, + { 0x40a14, 0xbebebe }, + { 0x40a18, 0xbfbfbf }, + { 0x40a1c, 0xc0c0c0 }, + { 0x40a20, 0xc0c0c0 }, + { 0x40a24, 0xc1c1c1 }, + { 0x40a28, 0xc1c1c1 }, + { 0x40a2c, 0xc2c2c2 }, + { 0x40a30, 0xc3c3c3 }, + { 0x40a34, 0xc3c3c3 }, + { 0x40a38, 0xc4c4c4 }, + { 0x40a3c, 0xc5c5c5 }, + { 0x40a40, 0xc5c5c5 }, + { 0x40a44, 0xc6c6c6 }, + { 0x40a48, 0xc6c6c6 }, + { 0x40a4c, 0xc7c7c7 }, + { 0x40a50, 0xc8c8c8 }, + { 0x40a54, 0xc8c8c8 }, + { 0x40a58, 0xc9c9c9 }, + { 0x40a5c, 0xc9c9c9 }, + { 0x40a60, 0xcacaca }, + { 0x40a64, 0xcbcbcb }, + { 0x40a68, 0xcbcbcb }, + { 0x40a6c, 0xcccccc }, + { 0x40a70, 0xcccccc }, + { 0x40a74, 0xcdcdcd }, + { 0x40a78, 0xcecece }, + { 0x40a7c, 0xcecece }, + { 0x40a80, 0xcfcfcf }, + { 0x40a84, 0xcfcfcf }, + { 0x40a88, 0xd0d0d0 }, + { 0x40a8c, 0xd0d0d0 }, + { 0x40a90, 0xd1d1d1 }, + { 0x40a94, 0xd2d2d2 }, + { 0x40a98, 0xd2d2d2 }, + { 0x40a9c, 0xd3d3d3 }, + { 0x40aa0, 0xd3d3d3 }, + { 0x40aa4, 0xd4d4d4 }, + { 0x40aa8, 0xd4d4d4 }, + { 0x40aac, 0xd5d5d5 }, + { 0x40ab0, 0xd6d6d6 }, + { 0x40ab4, 0xd6d6d6 }, + { 0x40ab8, 0xd7d7d7 }, + { 0x40abc, 0xd7d7d7 }, + { 0x40ac0, 0xd8d8d8 }, + { 0x40ac4, 0xd8d8d8 }, + { 0x40ac8, 0xd9d9d9 }, + { 0x40acc, 0xd9d9d9 }, + { 0x40ad0, 0xdadada }, + { 0x40ad4, 0xdbdbdb }, + { 0x40ad8, 0xdbdbdb }, + { 0x40adc, 0xdcdcdc }, + { 0x40ae0, 0xdcdcdc }, + { 0x40ae4, 0xdddddd }, + { 0x40ae8, 0xdddddd }, + { 0x40aec, 0xdedede }, + { 0x40af0, 0xdedede }, + { 0x40af4, 0xdfdfdf }, + { 0x40af8, 0xdfdfdf }, + { 0x40afc, 0xe0e0e0 }, + { 0x40b00, 0xe0e0e0 }, + { 0x40b04, 0xe1e1e1 }, + { 0x40b08, 0xe1e1e1 }, + { 0x40b0c, 0xe2e2e2 }, + { 0x40b10, 0xe3e3e3 }, + { 0x40b14, 0xe3e3e3 }, + { 0x40b18, 0xe4e4e4 }, + { 0x40b1c, 0xe4e4e4 }, + { 0x40b20, 0xe5e5e5 }, + { 0x40b24, 0xe5e5e5 }, + { 0x40b28, 0xe6e6e6 }, + { 0x40b2c, 0xe6e6e6 }, + { 0x40b30, 0xe7e7e7 }, + { 0x40b34, 0xe7e7e7 }, + { 0x40b38, 0xe8e8e8 }, + { 0x40b3c, 0xe8e8e8 }, + { 0x40b40, 0xe9e9e9 }, + { 0x40b44, 0xe9e9e9 }, + { 0x40b48, 0xeaeaea }, + { 0x40b4c, 0xeaeaea }, + { 0x40b50, 0xebebeb }, + { 0x40b54, 0xebebeb }, + { 0x40b58, 0xececec }, + { 0x40b5c, 0xececec }, + { 0x40b60, 0xededed }, + { 0x40b64, 0xededed }, + { 0x40b68, 0xeeeeee }, + { 0x40b6c, 0xeeeeee }, + { 0x40b70, 0xefefef }, + { 0x40b74, 0xefefef }, + { 0x40b78, 0xf0f0f0 }, + { 0x40b7c, 0xf0f0f0 }, + { 0x40b80, 0xf1f1f1 }, + { 0x40b84, 0xf1f1f1 }, + { 0x40b88, 0xf2f2f2 }, + { 0x40b8c, 0xf2f2f2 }, + { 0x40b90, 0xf2f2f2 }, + { 0x40b94, 0xf3f3f3 }, + { 0x40b98, 0xf3f3f3 }, + { 0x40b9c, 0xf4f4f4 }, + { 0x40ba0, 0xf4f4f4 }, + { 0x40ba4, 0xf5f5f5 }, + { 0x40ba8, 0xf5f5f5 }, + { 0x40bac, 0xf6f6f6 }, + { 0x40bb0, 0xf6f6f6 }, + { 0x40bb4, 0xf7f7f7 }, + { 0x40bb8, 0xf7f7f7 }, + { 0x40bbc, 0xf8f8f8 }, + { 0x40bc0, 0xf8f8f8 }, + { 0x40bc4, 0xf9f9f9 }, + { 0x40bc8, 0xf9f9f9 }, + { 0x40bcc, 0xfafafa }, + { 0x40bd0, 0xfafafa }, + { 0x40bd4, 0xfafafa }, + { 0x40bd8, 0xfbfbfb }, + { 0x40bdc, 0xfbfbfb }, + { 0x40be0, 0xfcfcfc }, + { 0x40be4, 0xfcfcfc }, + { 0x40be8, 0xfdfdfd }, + { 0x40bec, 0xfdfdfd }, + { 0x40bf0, 0xfefefe }, + { 0x40bf4, 0xfefefe }, + { 0x40bf8, 0xffffff }, + { 0x40bfc, 0xffffff }, + { 0x40c00, 0x0 }, + { 0x40c04, 0x0 }, + { 0x40c08, 0x0 }, + { 0x40c0c, 0x0 }, + { 0x40c10, 0x0 }, + { 0x40c14, 0x0 }, + { 0x40c18, 0x0 }, + { 0x40c1c, 0x0 }, + { 0x40c20, 0x0 }, + { 0x40c24, 0x0 }, + { 0x40c28, 0x0 }, + { 0x40c2c, 0x0 }, + { 0x40c30, 0x0 }, + { 0x40c34, 0x0 }, + { 0x40c38, 0x0 }, + { 0x40c3c, 0x0 }, + { 0x40c40, 0x10101 }, + { 0x40c44, 0x10101 }, + { 0x40c48, 0x10101 }, + { 0x40c4c, 0x10101 }, + { 0x40c50, 0x10101 }, + { 0x40c54, 0x10101 }, + { 0x40c58, 0x10101 }, + { 0x40c5c, 0x10101 }, + { 0x40c60, 0x10101 }, + { 0x40c64, 0x10101 }, + { 0x40c68, 0x20202 }, + { 0x40c6c, 0x20202 }, + { 0x40c70, 0x20202 }, + { 0x40c74, 0x20202 }, + { 0x40c78, 0x20202 }, + { 0x40c7c, 0x20202 }, + { 0x40c80, 0x30303 }, + { 0x40c84, 0x30303 }, + { 0x40c88, 0x30303 }, + { 0x40c8c, 0x30303 }, + { 0x40c90, 0x30303 }, + { 0x40c94, 0x40404 }, + { 0x40c98, 0x40404 }, + { 0x40c9c, 0x40404 }, + { 0x40ca0, 0x40404 }, + { 0x40ca4, 0x40404 }, + { 0x40ca8, 0x50505 }, + { 0x40cac, 0x50505 }, + { 0x40cb0, 0x50505 }, + { 0x40cb4, 0x50505 }, + { 0x40cb8, 0x60606 }, + { 0x40cbc, 0x60606 }, + { 0x40cc0, 0x60606 }, + { 0x40cc4, 0x70707 }, + { 0x40cc8, 0x70707 }, + { 0x40ccc, 0x70707 }, + { 0x40cd0, 0x70707 }, + { 0x40cd4, 0x80808 }, + { 0x40cd8, 0x80808 }, + { 0x40cdc, 0x80808 }, + { 0x40ce0, 0x90909 }, + { 0x40ce4, 0x90909 }, + { 0x40ce8, 0xa0a0a }, + { 0x40cec, 0xa0a0a }, + { 0x40cf0, 0xa0a0a }, + { 0x40cf4, 0xb0b0b }, + { 0x40cf8, 0xb0b0b }, + { 0x40cfc, 0xb0b0b }, + { 0x40d00, 0xc0c0c }, + { 0x40d04, 0xc0c0c }, + { 0x40d08, 0xd0d0d }, + { 0x40d0c, 0xd0d0d }, + { 0x40d10, 0xe0e0e }, + { 0x40d14, 0xe0e0e }, + { 0x40d18, 0xe0e0e }, + { 0x40d1c, 0xf0f0f }, + { 0x40d20, 0xf0f0f }, + { 0x40d24, 0x101010 }, + { 0x40d28, 0x101010 }, + { 0x40d2c, 0x111111 }, + { 0x40d30, 0x111111 }, + { 0x40d34, 0x121212 }, + { 0x40d38, 0x121212 }, + { 0x40d3c, 0x131313 }, + { 0x40d40, 0x131313 }, + { 0x40d44, 0x141414 }, + { 0x40d48, 0x151515 }, + { 0x40d4c, 0x151515 }, + { 0x40d50, 0x161616 }, + { 0x40d54, 0x161616 }, + { 0x40d58, 0x171717 }, + { 0x40d5c, 0x171717 }, + { 0x40d60, 0x181818 }, + { 0x40d64, 0x191919 }, + { 0x40d68, 0x191919 }, + { 0x40d6c, 0x1a1a1a }, + { 0x40d70, 0x1b1b1b }, + { 0x40d74, 0x1b1b1b }, + { 0x40d78, 0x1c1c1c }, + { 0x40d7c, 0x1c1c1c }, + { 0x40d80, 0x1d1d1d }, + { 0x40d84, 0x1e1e1e }, + { 0x40d88, 0x1f1f1f }, + { 0x40d8c, 0x1f1f1f }, + { 0x40d90, 0x202020 }, + { 0x40d94, 0x212121 }, + { 0x40d98, 0x212121 }, + { 0x40d9c, 0x222222 }, + { 0x40da0, 0x232323 }, + { 0x40da4, 0x242424 }, + { 0x40da8, 0x242424 }, + { 0x40dac, 0x252525 }, + { 0x40db0, 0x262626 }, + { 0x40db4, 0x272727 }, + { 0x40db8, 0x272727 }, + { 0x40dbc, 0x282828 }, + { 0x40dc0, 0x292929 }, + { 0x40dc4, 0x2a2a2a }, + { 0x40dc8, 0x2b2b2b }, + { 0x40dcc, 0x2c2c2c }, + { 0x40dd0, 0x2c2c2c }, + { 0x40dd4, 0x2d2d2d }, + { 0x40dd8, 0x2e2e2e }, + { 0x40ddc, 0x2f2f2f }, + { 0x40de0, 0x303030 }, + { 0x40de4, 0x313131 }, + { 0x40de8, 0x323232 }, + { 0x40dec, 0x333333 }, + { 0x40df0, 0x333333 }, + { 0x40df4, 0x343434 }, + { 0x40df8, 0x353535 }, + { 0x40dfc, 0x363636 }, + { 0x40e00, 0x373737 }, + { 0x40e04, 0x383838 }, + { 0x40e08, 0x393939 }, + { 0x40e0c, 0x3a3a3a }, + { 0x40e10, 0x3b3b3b }, + { 0x40e14, 0x3c3c3c }, + { 0x40e18, 0x3d3d3d }, + { 0x40e1c, 0x3e3e3e }, + { 0x40e20, 0x3f3f3f }, + { 0x40e24, 0x404040 }, + { 0x40e28, 0x414141 }, + { 0x40e2c, 0x424242 }, + { 0x40e30, 0x434343 }, + { 0x40e34, 0x444444 }, + { 0x40e38, 0x464646 }, + { 0x40e3c, 0x474747 }, + { 0x40e40, 0x484848 }, + { 0x40e44, 0x494949 }, + { 0x40e48, 0x4a4a4a }, + { 0x40e4c, 0x4b4b4b }, + { 0x40e50, 0x4c4c4c }, + { 0x40e54, 0x4d4d4d }, + { 0x40e58, 0x4f4f4f }, + { 0x40e5c, 0x505050 }, + { 0x40e60, 0x515151 }, + { 0x40e64, 0x525252 }, + { 0x40e68, 0x535353 }, + { 0x40e6c, 0x545454 }, + { 0x40e70, 0x565656 }, + { 0x40e74, 0x575757 }, + { 0x40e78, 0x585858 }, + { 0x40e7c, 0x595959 }, + { 0x40e80, 0x5b5b5b }, + { 0x40e84, 0x5c5c5c }, + { 0x40e88, 0x5d5d5d }, + { 0x40e8c, 0x5e5e5e }, + { 0x40e90, 0x606060 }, + { 0x40e94, 0x616161 }, + { 0x40e98, 0x626262 }, + { 0x40e9c, 0x646464 }, + { 0x40ea0, 0x656565 }, + { 0x40ea4, 0x666666 }, + { 0x40ea8, 0x686868 }, + { 0x40eac, 0x696969 }, + { 0x40eb0, 0x6a6a6a }, + { 0x40eb4, 0x6c6c6c }, + { 0x40eb8, 0x6d6d6d }, + { 0x40ebc, 0x6f6f6f }, + { 0x40ec0, 0x707070 }, + { 0x40ec4, 0x717171 }, + { 0x40ec8, 0x737373 }, + { 0x40ecc, 0x747474 }, + { 0x40ed0, 0x767676 }, + { 0x40ed4, 0x777777 }, + { 0x40ed8, 0x797979 }, + { 0x40edc, 0x7a7a7a }, + { 0x40ee0, 0x7c7c7c }, + { 0x40ee4, 0x7d7d7d }, + { 0x40ee8, 0x7f7f7f }, + { 0x40eec, 0x808080 }, + { 0x40ef0, 0x828282 }, + { 0x40ef4, 0x838383 }, + { 0x40ef8, 0x858585 }, + { 0x40efc, 0x868686 }, + { 0x40f00, 0x888888 }, + { 0x40f04, 0x898989 }, + { 0x40f08, 0x8b8b8b }, + { 0x40f0c, 0x8d8d8d }, + { 0x40f10, 0x8e8e8e }, + { 0x40f14, 0x909090 }, + { 0x40f18, 0x919191 }, + { 0x40f1c, 0x939393 }, + { 0x40f20, 0x959595 }, + { 0x40f24, 0x969696 }, + { 0x40f28, 0x989898 }, + { 0x40f2c, 0x9a9a9a }, + { 0x40f30, 0x9b9b9b }, + { 0x40f34, 0x9d9d9d }, + { 0x40f38, 0x9f9f9f }, + { 0x40f3c, 0xa1a1a1 }, + { 0x40f40, 0xa2a2a2 }, + { 0x40f44, 0xa4a4a4 }, + { 0x40f48, 0xa6a6a6 }, + { 0x40f4c, 0xa7a7a7 }, + { 0x40f50, 0xa9a9a9 }, + { 0x40f54, 0xababab }, + { 0x40f58, 0xadadad }, + { 0x40f5c, 0xafafaf }, + { 0x40f60, 0xb0b0b0 }, + { 0x40f64, 0xb2b2b2 }, + { 0x40f68, 0xb4b4b4 }, + { 0x40f6c, 0xb6b6b6 }, + { 0x40f70, 0xb8b8b8 }, + { 0x40f74, 0xbababa }, + { 0x40f78, 0xbbbbbb }, + { 0x40f7c, 0xbdbdbd }, + { 0x40f80, 0xbfbfbf }, + { 0x40f84, 0xc1c1c1 }, + { 0x40f88, 0xc3c3c3 }, + { 0x40f8c, 0xc5c5c5 }, + { 0x40f90, 0xc7c7c7 }, + { 0x40f94, 0xc9c9c9 }, + { 0x40f98, 0xcbcbcb }, + { 0x40f9c, 0xcdcdcd }, + { 0x40fa0, 0xcfcfcf }, + { 0x40fa4, 0xd1d1d1 }, + { 0x40fa8, 0xd3d3d3 }, + { 0x40fac, 0xd5d5d5 }, + { 0x40fb0, 0xd7d7d7 }, + { 0x40fb4, 0xd9d9d9 }, + { 0x40fb8, 0xdbdbdb }, + { 0x40fbc, 0xdddddd }, + { 0x40fc0, 0xdfdfdf }, + { 0x40fc4, 0xe1e1e1 }, + { 0x40fc8, 0xe3e3e3 }, + { 0x40fcc, 0xe5e5e5 }, + { 0x40fd0, 0xe7e7e7 }, + { 0x40fd4, 0xe9e9e9 }, + { 0x40fd8, 0xebebeb }, + { 0x40fdc, 0xeeeeee }, + { 0x40fe0, 0xf0f0f0 }, + { 0x40fe4, 0xf2f2f2 }, + { 0x40fe8, 0xf4f4f4 }, + { 0x40fec, 0xf6f6f6 }, + { 0x40ff0, 0xf8f8f8 }, + { 0x40ff4, 0xfbfbfb }, + { 0x40ff8, 0xfdfdfd }, + { 0x40ffc, 0xffffff }, +}; diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h new file mode 100644 index 000000000000..4e3deb4e592b --- /dev/null +++ b/drivers/video/msm/mdp_hw.h @@ -0,0 +1,621 @@ +/* drivers/video/msm_fb/mdp_hw.h + * + * Copyright (C) 2007 QUALCOMM Incorporated + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _MDP_HW_H_ +#define _MDP_HW_H_ + +#include <mach/msm_iomap.h> +#include <mach/msm_fb.h> + +struct mdp_info { + struct mdp_device mdp_dev; + char * __iomem base; + int irq; +}; +struct mdp_blit_req; +struct mdp_device; +int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req, + struct file *src_file, unsigned long src_start, + unsigned long src_len, struct file *dst_file, + unsigned long dst_start, unsigned long dst_len); +#define mdp_writel(mdp, value, offset) writel(value, mdp->base + offset) +#define mdp_readl(mdp, offset) readl(mdp->base + offset) + +#define MDP_SYNC_CONFIG_0 (0x00000) +#define MDP_SYNC_CONFIG_1 (0x00004) +#define MDP_SYNC_CONFIG_2 (0x00008) +#define MDP_SYNC_STATUS_0 (0x0000c) +#define MDP_SYNC_STATUS_1 (0x00010) +#define MDP_SYNC_STATUS_2 (0x00014) +#define MDP_SYNC_THRESH_0 (0x00018) +#define MDP_SYNC_THRESH_1 (0x0001c) +#define MDP_INTR_ENABLE (0x00020) +#define MDP_INTR_STATUS (0x00024) +#define MDP_INTR_CLEAR (0x00028) +#define MDP_DISPLAY0_START (0x00030) +#define MDP_DISPLAY1_START (0x00034) +#define MDP_DISPLAY_STATUS (0x00038) +#define MDP_EBI2_LCD0 (0x0003c) +#define MDP_EBI2_LCD1 (0x00040) +#define MDP_DISPLAY0_ADDR (0x00054) +#define MDP_DISPLAY1_ADDR (0x00058) +#define MDP_EBI2_PORTMAP_MODE (0x0005c) +#define MDP_MODE (0x00060) +#define MDP_TV_OUT_STATUS (0x00064) +#define MDP_HW_VERSION (0x00070) +#define MDP_SW_RESET (0x00074) +#define MDP_AXI_ERROR_MASTER_STOP (0x00078) +#define MDP_SEL_CLK_OR_HCLK_TEST_BUS (0x0007c) +#define MDP_PRIMARY_VSYNC_OUT_CTRL (0x00080) +#define MDP_SECONDARY_VSYNC_OUT_CTRL (0x00084) +#define MDP_EXTERNAL_VSYNC_OUT_CTRL (0x00088) +#define MDP_VSYNC_CTRL (0x0008c) +#define MDP_CGC_EN (0x00100) +#define MDP_CMD_STATUS (0x10008) +#define MDP_PROFILE_EN (0x10010) +#define MDP_PROFILE_COUNT (0x10014) +#define MDP_DMA_START (0x10044) +#define MDP_FULL_BYPASS_WORD0 (0x10100) +#define MDP_FULL_BYPASS_WORD1 (0x10104) +#define MDP_COMMAND_CONFIG (0x10104) +#define MDP_FULL_BYPASS_WORD2 (0x10108) +#define MDP_FULL_BYPASS_WORD3 (0x1010c) +#define MDP_FULL_BYPASS_WORD4 (0x10110) +#define MDP_FULL_BYPASS_WORD6 (0x10118) +#define MDP_FULL_BYPASS_WORD7 (0x1011c) +#define MDP_FULL_BYPASS_WORD8 (0x10120) +#define MDP_FULL_BYPASS_WORD9 (0x10124) +#define MDP_PPP_SOURCE_CONFIG (0x10124) +#define MDP_FULL_BYPASS_WORD10 (0x10128) +#define MDP_FULL_BYPASS_WORD11 (0x1012c) +#define MDP_FULL_BYPASS_WORD12 (0x10130) +#define MDP_FULL_BYPASS_WORD13 (0x10134) +#define MDP_FULL_BYPASS_WORD14 (0x10138) +#define MDP_PPP_OPERATION_CONFIG (0x10138) +#define MDP_FULL_BYPASS_WORD15 (0x1013c) +#define MDP_FULL_BYPASS_WORD16 (0x10140) +#define MDP_FULL_BYPASS_WORD17 (0x10144) +#define MDP_FULL_BYPASS_WORD18 (0x10148) +#define MDP_FULL_BYPASS_WORD19 (0x1014c) +#define MDP_FULL_BYPASS_WORD20 (0x10150) +#define MDP_PPP_DESTINATION_CONFIG (0x10150) +#define MDP_FULL_BYPASS_WORD21 (0x10154) +#define MDP_FULL_BYPASS_WORD22 (0x10158) +#define MDP_FULL_BYPASS_WORD23 (0x1015c) +#define MDP_FULL_BYPASS_WORD24 (0x10160) +#define MDP_FULL_BYPASS_WORD25 (0x10164) +#define MDP_FULL_BYPASS_WORD26 (0x10168) +#define MDP_FULL_BYPASS_WORD27 (0x1016c) +#define MDP_FULL_BYPASS_WORD29 (0x10174) +#define MDP_FULL_BYPASS_WORD30 (0x10178) +#define MDP_FULL_BYPASS_WORD31 (0x1017c) +#define MDP_FULL_BYPASS_WORD32 (0x10180) +#define MDP_DMA_CONFIG (0x10180) +#define MDP_FULL_BYPASS_WORD33 (0x10184) +#define MDP_FULL_BYPASS_WORD34 (0x10188) +#define MDP_FULL_BYPASS_WORD35 (0x1018c) +#define MDP_FULL_BYPASS_WORD37 (0x10194) +#define MDP_FULL_BYPASS_WORD39 (0x1019c) +#define MDP_FULL_BYPASS_WORD40 (0x101a0) +#define MDP_FULL_BYPASS_WORD41 (0x101a4) +#define MDP_FULL_BYPASS_WORD43 (0x101ac) +#define MDP_FULL_BYPASS_WORD46 (0x101b8) +#define MDP_FULL_BYPASS_WORD47 (0x101bc) +#define MDP_FULL_BYPASS_WORD48 (0x101c0) +#define MDP_FULL_BYPASS_WORD49 (0x101c4) +#define MDP_FULL_BYPASS_WORD50 (0x101c8) +#define MDP_FULL_BYPASS_WORD51 (0x101cc) +#define MDP_FULL_BYPASS_WORD52 (0x101d0) +#define MDP_FULL_BYPASS_WORD53 (0x101d4) +#define MDP_FULL_BYPASS_WORD54 (0x101d8) +#define MDP_FULL_BYPASS_WORD55 (0x101dc) +#define MDP_FULL_BYPASS_WORD56 (0x101e0) +#define MDP_FULL_BYPASS_WORD57 (0x101e4) +#define MDP_FULL_BYPASS_WORD58 (0x101e8) +#define MDP_FULL_BYPASS_WORD59 (0x101ec) +#define MDP_FULL_BYPASS_WORD60 (0x101f0) +#define MDP_VSYNC_THRESHOLD (0x101f0) +#define MDP_FULL_BYPASS_WORD61 (0x101f4) +#define MDP_FULL_BYPASS_WORD62 (0x101f8) +#define MDP_FULL_BYPASS_WORD63 (0x101fc) +#define MDP_TFETCH_TEST_MODE (0x20004) +#define MDP_TFETCH_STATUS (0x20008) +#define MDP_TFETCH_TILE_COUNT (0x20010) +#define MDP_TFETCH_FETCH_COUNT (0x20014) +#define MDP_TFETCH_CONSTANT_COLOR (0x20040) +#define MDP_CSC_BYPASS (0x40004) +#define MDP_SCALE_COEFF_LSB (0x5fffc) +#define MDP_TV_OUT_CTL (0xc0000) +#define MDP_TV_OUT_FIR_COEFF (0xc0004) +#define MDP_TV_OUT_BUF_ADDR (0xc0008) +#define MDP_TV_OUT_CC_DATA (0xc000c) +#define MDP_TV_OUT_SOBEL (0xc0010) +#define MDP_TV_OUT_Y_CLAMP (0xc0018) +#define MDP_TV_OUT_CB_CLAMP (0xc001c) +#define MDP_TV_OUT_CR_CLAMP (0xc0020) +#define MDP_TEST_MODE_CLK (0xd0000) +#define MDP_TEST_MISR_RESET_CLK (0xd0004) +#define MDP_TEST_EXPORT_MISR_CLK (0xd0008) +#define MDP_TEST_MISR_CURR_VAL_CLK (0xd000c) +#define MDP_TEST_MODE_HCLK (0xd0100) +#define MDP_TEST_MISR_RESET_HCLK (0xd0104) +#define MDP_TEST_EXPORT_MISR_HCLK (0xd0108) +#define MDP_TEST_MISR_CURR_VAL_HCLK (0xd010c) +#define MDP_TEST_MODE_DCLK (0xd0200) +#define MDP_TEST_MISR_RESET_DCLK (0xd0204) +#define MDP_TEST_EXPORT_MISR_DCLK (0xd0208) +#define MDP_TEST_MISR_CURR_VAL_DCLK (0xd020c) +#define MDP_TEST_CAPTURED_DCLK (0xd0210) +#define MDP_TEST_MISR_CAPT_VAL_DCLK (0xd0214) +#define MDP_LCDC_CTL (0xe0000) +#define MDP_LCDC_HSYNC_CTL (0xe0004) +#define MDP_LCDC_VSYNC_CTL (0xe0008) +#define MDP_LCDC_ACTIVE_HCTL (0xe000c) +#define MDP_LCDC_ACTIVE_VCTL (0xe0010) +#define MDP_LCDC_BORDER_CLR (0xe0014) +#define MDP_LCDC_H_BLANK (0xe0018) +#define MDP_LCDC_V_BLANK (0xe001c) +#define MDP_LCDC_UNDERFLOW_CLR (0xe0020) +#define MDP_LCDC_HSYNC_SKEW (0xe0024) +#define MDP_LCDC_TEST_CTL (0xe0028) +#define MDP_LCDC_LINE_IRQ (0xe002c) +#define MDP_LCDC_CTL_POLARITY (0xe0030) +#define MDP_LCDC_DMA_CONFIG (0xe1000) +#define MDP_LCDC_DMA_SIZE (0xe1004) +#define MDP_LCDC_DMA_IBUF_ADDR (0xe1008) +#define MDP_LCDC_DMA_IBUF_Y_STRIDE (0xe100c) + + +#define MDP_DMA2_TERM 0x1 +#define MDP_DMA3_TERM 0x2 +#define MDP_PPP_TERM 0x3 + +/* MDP_INTR_ENABLE */ +#define DL0_ROI_DONE (1<<0) +#define DL1_ROI_DONE (1<<1) +#define DL0_DMA2_TERM_DONE (1<<2) +#define DL1_DMA2_TERM_DONE (1<<3) +#define DL0_PPP_TERM_DONE (1<<4) +#define DL1_PPP_TERM_DONE (1<<5) +#define TV_OUT_DMA3_DONE (1<<6) +#define TV_ENC_UNDERRUN (1<<7) +#define DL0_FETCH_DONE (1<<11) +#define DL1_FETCH_DONE (1<<12) + +#define MDP_PPP_BUSY_STATUS (DL0_ROI_DONE| \ + DL1_ROI_DONE| \ + DL0_PPP_TERM_DONE| \ + DL1_PPP_TERM_DONE) + +#define MDP_ANY_INTR_MASK (DL0_ROI_DONE| \ + DL1_ROI_DONE| \ + DL0_DMA2_TERM_DONE| \ + DL1_DMA2_TERM_DONE| \ + DL0_PPP_TERM_DONE| \ + DL1_PPP_TERM_DONE| \ + DL0_FETCH_DONE| \ + DL1_FETCH_DONE| \ + TV_ENC_UNDERRUN) + +#define MDP_TOP_LUMA 16 +#define MDP_TOP_CHROMA 0 +#define MDP_BOTTOM_LUMA 19 +#define MDP_BOTTOM_CHROMA 3 +#define MDP_LEFT_LUMA 22 +#define MDP_LEFT_CHROMA 6 +#define MDP_RIGHT_LUMA 25 +#define MDP_RIGHT_CHROMA 9 + +#define CLR_G 0x0 +#define CLR_B 0x1 +#define CLR_R 0x2 +#define CLR_ALPHA 0x3 + +#define CLR_Y CLR_G +#define CLR_CB CLR_B +#define CLR_CR CLR_R + +/* from lsb to msb */ +#define MDP_GET_PACK_PATTERN(a, x, y, z, bit) \ + (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z)) + +/* MDP_SYNC_CONFIG_0/1/2 */ +#define MDP_SYNCFG_HGT_LOC 22 +#define MDP_SYNCFG_VSYNC_EXT_EN (1<<21) +#define MDP_SYNCFG_VSYNC_INT_EN (1<<20) + +/* MDP_SYNC_THRESH_0 */ +#define MDP_PRIM_BELOW_LOC 0 +#define MDP_PRIM_ABOVE_LOC 8 + +/* MDP_{PRIMARY,SECONDARY,EXTERNAL}_VSYNC_OUT_CRL */ +#define VSYNC_PULSE_EN (1<<31) +#define VSYNC_PULSE_INV (1<<30) + +/* MDP_VSYNC_CTRL */ +#define DISP0_VSYNC_MAP_VSYNC0 0 +#define DISP0_VSYNC_MAP_VSYNC1 (1<<0) +#define DISP0_VSYNC_MAP_VSYNC2 ((1<<0)|(1<<1)) + +#define DISP1_VSYNC_MAP_VSYNC0 0 +#define DISP1_VSYNC_MAP_VSYNC1 (1<<2) +#define DISP1_VSYNC_MAP_VSYNC2 ((1<<2)|(1<<3)) + +#define PRIMARY_LCD_SYNC_EN (1<<4) +#define PRIMARY_LCD_SYNC_DISABLE 0 + +#define SECONDARY_LCD_SYNC_EN (1<<5) +#define SECONDARY_LCD_SYNC_DISABLE 0 + +#define EXTERNAL_LCD_SYNC_EN (1<<6) +#define EXTERNAL_LCD_SYNC_DISABLE 0 + +/* MDP_VSYNC_THRESHOLD / MDP_FULL_BYPASS_WORD60 */ +#define VSYNC_THRESHOLD_ABOVE_LOC 0 +#define VSYNC_THRESHOLD_BELOW_LOC 16 +#define VSYNC_ANTI_TEAR_EN (1<<31) + +/* MDP_COMMAND_CONFIG / MDP_FULL_BYPASS_WORD1 */ +#define MDP_CMD_DBGBUS_EN (1<<0) + +/* MDP_PPP_SOURCE_CONFIG / MDP_FULL_BYPASS_WORD9&53 */ +#define PPP_SRC_C0G_8BIT ((1<<1)|(1<<0)) +#define PPP_SRC_C1B_8BIT ((1<<3)|(1<<2)) +#define PPP_SRC_C2R_8BIT ((1<<5)|(1<<4)) +#define PPP_SRC_C3A_8BIT ((1<<7)|(1<<6)) + +#define PPP_SRC_C0G_6BIT (1<<1) +#define PPP_SRC_C1B_6BIT (1<<3) +#define PPP_SRC_C2R_6BIT (1<<5) + +#define PPP_SRC_C0G_5BIT (1<<0) +#define PPP_SRC_C1B_5BIT (1<<2) +#define PPP_SRC_C2R_5BIT (1<<4) + +#define PPP_SRC_C3ALPHA_EN (1<<8) + +#define PPP_SRC_BPP_1BYTES 0 +#define PPP_SRC_BPP_2BYTES (1<<9) +#define PPP_SRC_BPP_3BYTES (1<<10) +#define PPP_SRC_BPP_4BYTES ((1<<10)|(1<<9)) + +#define PPP_SRC_BPP_ROI_ODD_X (1<<11) +#define PPP_SRC_BPP_ROI_ODD_Y (1<<12) +#define PPP_SRC_INTERLVD_2COMPONENTS (1<<13) +#define PPP_SRC_INTERLVD_3COMPONENTS (1<<14) +#define PPP_SRC_INTERLVD_4COMPONENTS ((1<<14)|(1<<13)) + + +/* RGB666 unpack format +** TIGHT means R6+G6+B6 together +** LOOSE means R6+2 +G6+2+ B6+2 (with MSB) +** or 2+R6 +2+G6 +2+B6 (with LSB) +*/ +#define PPP_SRC_PACK_TIGHT (1<<17) +#define PPP_SRC_PACK_LOOSE 0 +#define PPP_SRC_PACK_ALIGN_LSB 0 +#define PPP_SRC_PACK_ALIGN_MSB (1<<18) + +#define PPP_SRC_PLANE_INTERLVD 0 +#define PPP_SRC_PLANE_PSEUDOPLNR (1<<20) + +#define PPP_SRC_WMV9_MODE (1<<21) + +/* MDP_PPP_OPERATION_CONFIG / MDP_FULL_BYPASS_WORD14 */ +#define PPP_OP_SCALE_X_ON (1<<0) +#define PPP_OP_SCALE_Y_ON (1<<1) + +#define PPP_OP_CONVERT_RGB2YCBCR 0 +#define PPP_OP_CONVERT_YCBCR2RGB (1<<2) +#define PPP_OP_CONVERT_ON (1<<3) + +#define PPP_OP_CONVERT_MATRIX_PRIMARY 0 +#define PPP_OP_CONVERT_MATRIX_SECONDARY (1<<4) + +#define PPP_OP_LUT_C0_ON (1<<5) +#define PPP_OP_LUT_C1_ON (1<<6) +#define PPP_OP_LUT_C2_ON (1<<7) + +/* rotate or blend enable */ +#define PPP_OP_ROT_ON (1<<8) + +#define PPP_OP_ROT_90 (1<<9) +#define PPP_OP_FLIP_LR (1<<10) +#define PPP_OP_FLIP_UD (1<<11) + +#define PPP_OP_BLEND_ON (1<<12) + +#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0 +#define PPP_OP_BLEND_DSTPIXEL_ALPHA (1<<13) +#define PPP_OP_BLEND_CONSTANT_ALPHA (1<<14) +#define PPP_OP_BLEND_SRCPIXEL_TRANSP ((1<<13)|(1<<14)) + +#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0 +#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE (1<<15) + +#define PPP_OP_DITHER_EN (1<<16) + +#define PPP_OP_COLOR_SPACE_RGB 0 +#define PPP_OP_COLOR_SPACE_YCBCR (1<<17) + +#define PPP_OP_SRC_CHROMA_RGB 0 +#define PPP_OP_SRC_CHROMA_H2V1 (1<<18) +#define PPP_OP_SRC_CHROMA_H1V2 (1<<19) +#define PPP_OP_SRC_CHROMA_420 ((1<<18)|(1<<19)) +#define PPP_OP_SRC_CHROMA_COSITE 0 +#define PPP_OP_SRC_CHROMA_OFFSITE (1<<20) + +#define PPP_OP_DST_CHROMA_RGB 0 +#define PPP_OP_DST_CHROMA_H2V1 (1<<21) +#define PPP_OP_DST_CHROMA_H1V2 (1<<22) +#define PPP_OP_DST_CHROMA_420 ((1<<21)|(1<<22)) +#define PPP_OP_DST_CHROMA_COSITE 0 +#define PPP_OP_DST_CHROMA_OFFSITE (1<<23) + +#define PPP_BLEND_ALPHA_TRANSP (1<<24) + +#define PPP_OP_BG_CHROMA_RGB 0 +#define PPP_OP_BG_CHROMA_H2V1 (1<<25) +#define PPP_OP_BG_CHROMA_H1V2 (1<<26) +#define PPP_OP_BG_CHROMA_420 ((1<<25)|(1<<26)) +#define PPP_OP_BG_CHROMA_SITE_COSITE 0 +#define PPP_OP_BG_CHROMA_SITE_OFFSITE (1<<27) + +/* MDP_PPP_DESTINATION_CONFIG / MDP_FULL_BYPASS_WORD20 */ +#define PPP_DST_C0G_8BIT ((1<<0)|(1<<1)) +#define PPP_DST_C1B_8BIT ((1<<3)|(1<<2)) +#define PPP_DST_C2R_8BIT ((1<<5)|(1<<4)) +#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6)) + +#define PPP_DST_C0G_6BIT (1<<1) +#define PPP_DST_C1B_6BIT (1<<3) +#define PPP_DST_C2R_6BIT (1<<5) + +#define PPP_DST_C0G_5BIT (1<<0) +#define PPP_DST_C1B_5BIT (1<<2) +#define PPP_DST_C2R_5BIT (1<<4) + +#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6)) +#define PPP_DST_C3ALPHA_EN (1<<8) + +#define PPP_DST_INTERLVD_2COMPONENTS (1<<9) +#define PPP_DST_INTERLVD_3COMPONENTS (1<<10) +#define PPP_DST_INTERLVD_4COMPONENTS ((1<<10)|(1<<9)) +#define PPP_DST_INTERLVD_6COMPONENTS ((1<<11)|(1<<9)) + +#define PPP_DST_PACK_LOOSE 0 +#define PPP_DST_PACK_TIGHT (1<<13) +#define PPP_DST_PACK_ALIGN_LSB 0 +#define PPP_DST_PACK_ALIGN_MSB (1<<14) + +#define PPP_DST_OUT_SEL_AXI 0 +#define PPP_DST_OUT_SEL_MDDI (1<<15) + +#define PPP_DST_BPP_2BYTES (1<<16) +#define PPP_DST_BPP_3BYTES (1<<17) +#define PPP_DST_BPP_4BYTES ((1<<17)|(1<<16)) + +#define PPP_DST_PLANE_INTERLVD 0 +#define PPP_DST_PLANE_PLANAR (1<<18) +#define PPP_DST_PLANE_PSEUDOPLNR (1<<19) + +#define PPP_DST_TO_TV (1<<20) + +#define PPP_DST_MDDI_PRIMARY 0 +#define PPP_DST_MDDI_SECONDARY (1<<21) +#define PPP_DST_MDDI_EXTERNAL (1<<22) + +/* image configurations by image type */ +#define PPP_CFG_MDP_RGB_565(dir) (PPP_##dir##_C2R_5BIT | \ + PPP_##dir##_C0G_6BIT | \ + PPP_##dir##_C1B_5BIT | \ + PPP_##dir##_BPP_2BYTES | \ + PPP_##dir##_INTERLVD_3COMPONENTS | \ + PPP_##dir##_PACK_TIGHT | \ + PPP_##dir##_PACK_ALIGN_LSB | \ + PPP_##dir##_PLANE_INTERLVD) + +#define PPP_CFG_MDP_RGB_888(dir) (PPP_##dir##_C2R_8BIT | \ + PPP_##dir##_C0G_8BIT | \ + PPP_##dir##_C1B_8BIT | \ + PPP_##dir##_BPP_3BYTES | \ + PPP_##dir##_INTERLVD_3COMPONENTS | \ + PPP_##dir##_PACK_TIGHT | \ + PPP_##dir##_PACK_ALIGN_LSB | \ + PPP_##dir##_PLANE_INTERLVD) + +#define PPP_CFG_MDP_ARGB_8888(dir) (PPP_##dir##_C2R_8BIT | \ + PPP_##dir##_C0G_8BIT | \ + PPP_##dir##_C1B_8BIT | \ + PPP_##dir##_C3A_8BIT | \ + PPP_##dir##_C3ALPHA_EN | \ + PPP_##dir##_BPP_4BYTES | \ + PPP_##dir##_INTERLVD_4COMPONENTS | \ + PPP_##dir##_PACK_TIGHT | \ + PPP_##dir##_PACK_ALIGN_LSB | \ + PPP_##dir##_PLANE_INTERLVD) + +#define PPP_CFG_MDP_XRGB_8888(dir) PPP_CFG_MDP_ARGB_8888(dir) +#define PPP_CFG_MDP_RGBA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir) +#define PPP_CFG_MDP_BGRA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir) + +#define PPP_CFG_MDP_Y_CBCR_H2V2(dir) (PPP_##dir##_C2R_8BIT | \ + PPP_##dir##_C0G_8BIT | \ + PPP_##dir##_C1B_8BIT | \ + PPP_##dir##_C3A_8BIT | \ + PPP_##dir##_BPP_2BYTES | \ + PPP_##dir##_INTERLVD_2COMPONENTS | \ + PPP_##dir##_PACK_TIGHT | \ + PPP_##dir##_PACK_ALIGN_LSB | \ + PPP_##dir##_PLANE_PSEUDOPLNR) + +#define PPP_CFG_MDP_Y_CRCB_H2V2(dir) PPP_CFG_MDP_Y_CBCR_H2V2(dir) + +#define PPP_CFG_MDP_YCRYCB_H2V1(dir) (PPP_##dir##_C2R_8BIT | \ + PPP_##dir##_C0G_8BIT | \ + PPP_##dir##_C1B_8BIT | \ + PPP_##dir##_C3A_8BIT | \ + PPP_##dir##_BPP_2BYTES | \ + PPP_##dir##_INTERLVD_4COMPONENTS | \ + PPP_##dir##_PACK_TIGHT | \ + PPP_##dir##_PACK_ALIGN_LSB |\ + PPP_##dir##_PLANE_INTERLVD) + +#define PPP_CFG_MDP_Y_CBCR_H2V1(dir) (PPP_##dir##_C2R_8BIT | \ + PPP_##dir##_C0G_8BIT | \ + PPP_##dir##_C1B_8BIT | \ + PPP_##dir##_C3A_8BIT | \ + PPP_##dir##_BPP_2BYTES | \ + PPP_##dir##_INTERLVD_2COMPONENTS | \ + PPP_##dir##_PACK_TIGHT | \ + PPP_##dir##_PACK_ALIGN_LSB | \ + PPP_##dir##_PLANE_PSEUDOPLNR) + +#define PPP_CFG_MDP_Y_CRCB_H2V1(dir) PPP_CFG_MDP_Y_CBCR_H2V1(dir) + +#define PPP_PACK_PATTERN_MDP_RGB_565 \ + MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8) +#define PPP_PACK_PATTERN_MDP_RGB_888 PPP_PACK_PATTERN_MDP_RGB_565 +#define PPP_PACK_PATTERN_MDP_XRGB_8888 \ + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8) +#define PPP_PACK_PATTERN_MDP_ARGB_8888 PPP_PACK_PATTERN_MDP_XRGB_8888 +#define PPP_PACK_PATTERN_MDP_RGBA_8888 \ + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8) +#define PPP_PACK_PATTERN_MDP_BGRA_8888 \ + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8) +#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 \ + MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8) +#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V2 PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 +#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1 \ + MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8) +#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V2 PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1 +#define PPP_PACK_PATTERN_MDP_YCRYCB_H2V1 \ + MDP_GET_PACK_PATTERN(CLR_Y, CLR_R, CLR_Y, CLR_B, 8) + +#define PPP_CHROMA_SAMP_MDP_RGB_565(dir) PPP_OP_##dir##_CHROMA_RGB +#define PPP_CHROMA_SAMP_MDP_RGB_888(dir) PPP_OP_##dir##_CHROMA_RGB +#define PPP_CHROMA_SAMP_MDP_XRGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB +#define PPP_CHROMA_SAMP_MDP_ARGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB +#define PPP_CHROMA_SAMP_MDP_RGBA_8888(dir) PPP_OP_##dir##_CHROMA_RGB +#define PPP_CHROMA_SAMP_MDP_BGRA_8888(dir) PPP_OP_##dir##_CHROMA_RGB +#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1 +#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V2(dir) PPP_OP_##dir##_CHROMA_420 +#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1 +#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V2(dir) PPP_OP_##dir##_CHROMA_420 +#define PPP_CHROMA_SAMP_MDP_YCRYCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1 + +/* Helpful array generation macros */ +#define PPP_ARRAY0(name) \ + [MDP_RGB_565] = PPP_##name##_MDP_RGB_565,\ + [MDP_RGB_888] = PPP_##name##_MDP_RGB_888,\ + [MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888,\ + [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888,\ + [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888,\ + [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888,\ + [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1,\ + [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2,\ + [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1,\ + [MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2,\ + [MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1 + +#define PPP_ARRAY1(name, dir) \ + [MDP_RGB_565] = PPP_##name##_MDP_RGB_565(dir),\ + [MDP_RGB_888] = PPP_##name##_MDP_RGB_888(dir),\ + [MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888(dir),\ + [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888(dir),\ + [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888(dir),\ + [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888(dir),\ + [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1(dir),\ + [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2(dir),\ + [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1(dir),\ + [MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2(dir),\ + [MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1(dir) + +#define IS_YCRCB(img) ((img == MDP_Y_CRCB_H2V2) | (img == MDP_Y_CBCR_H2V2) | \ + (img == MDP_Y_CRCB_H2V1) | (img == MDP_Y_CBCR_H2V1) | \ + (img == MDP_YCRYCB_H2V1)) +#define IS_RGB(img) ((img == MDP_RGB_565) | (img == MDP_RGB_888) | \ + (img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \ + (img == MDP_XRGB_8888) | (img == MDP_BGRA_8888)) +#define HAS_ALPHA(img) ((img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \ + (img == MDP_BGRA_8888)) + +#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \ + (img == MDP_Y_CBCR_H2V2) | \ + (img == MDP_Y_CRCB_H2V1) | \ + (img == MDP_Y_CBCR_H2V1)) + +/* Mappings from addr to purpose */ +#define PPP_ADDR_SRC_ROI MDP_FULL_BYPASS_WORD2 +#define PPP_ADDR_SRC0 MDP_FULL_BYPASS_WORD3 +#define PPP_ADDR_SRC1 MDP_FULL_BYPASS_WORD4 +#define PPP_ADDR_SRC_YSTRIDE MDP_FULL_BYPASS_WORD7 +#define PPP_ADDR_SRC_CFG MDP_FULL_BYPASS_WORD9 +#define PPP_ADDR_SRC_PACK_PATTERN MDP_FULL_BYPASS_WORD10 +#define PPP_ADDR_OPERATION MDP_FULL_BYPASS_WORD14 +#define PPP_ADDR_PHASEX_INIT MDP_FULL_BYPASS_WORD15 +#define PPP_ADDR_PHASEY_INIT MDP_FULL_BYPASS_WORD16 +#define PPP_ADDR_PHASEX_STEP MDP_FULL_BYPASS_WORD17 +#define PPP_ADDR_PHASEY_STEP MDP_FULL_BYPASS_WORD18 +#define PPP_ADDR_ALPHA_TRANSP MDP_FULL_BYPASS_WORD19 +#define PPP_ADDR_DST_CFG MDP_FULL_BYPASS_WORD20 +#define PPP_ADDR_DST_PACK_PATTERN MDP_FULL_BYPASS_WORD21 +#define PPP_ADDR_DST_ROI MDP_FULL_BYPASS_WORD25 +#define PPP_ADDR_DST0 MDP_FULL_BYPASS_WORD26 +#define PPP_ADDR_DST1 MDP_FULL_BYPASS_WORD27 +#define PPP_ADDR_DST_YSTRIDE MDP_FULL_BYPASS_WORD30 +#define PPP_ADDR_EDGE MDP_FULL_BYPASS_WORD46 +#define PPP_ADDR_BG0 MDP_FULL_BYPASS_WORD48 +#define PPP_ADDR_BG1 MDP_FULL_BYPASS_WORD49 +#define PPP_ADDR_BG_YSTRIDE MDP_FULL_BYPASS_WORD51 +#define PPP_ADDR_BG_CFG MDP_FULL_BYPASS_WORD53 +#define PPP_ADDR_BG_PACK_PATTERN MDP_FULL_BYPASS_WORD54 + +/* MDP_DMA_CONFIG / MDP_FULL_BYPASS_WORD32 */ +#define DMA_DSTC0G_6BITS (1<<1) +#define DMA_DSTC1B_6BITS (1<<3) +#define DMA_DSTC2R_6BITS (1<<5) +#define DMA_DSTC0G_5BITS (1<<0) +#define DMA_DSTC1B_5BITS (1<<2) +#define DMA_DSTC2R_5BITS (1<<4) + +#define DMA_PACK_TIGHT (1<<6) +#define DMA_PACK_LOOSE 0 +#define DMA_PACK_ALIGN_LSB 0 +#define DMA_PACK_ALIGN_MSB (1<<7) +#define DMA_PACK_PATTERN_RGB \ + (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8) + +#define DMA_OUT_SEL_AHB 0 +#define DMA_OUT_SEL_MDDI (1<<14) +#define DMA_AHBM_LCD_SEL_PRIMARY 0 +#define DMA_AHBM_LCD_SEL_SECONDARY (1<<15) +#define DMA_IBUF_C3ALPHA_EN (1<<16) +#define DMA_DITHER_EN (1<<17) + +#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0 +#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (1<<18) +#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (1<<19) + +#define DMA_IBUF_FORMAT_RGB565 (1<<20) +#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0 + +#define DMA_IBUF_NONCONTIGUOUS (1<<21) + +/* MDDI REGISTER ? */ +#define MDDI_VDO_PACKET_DESC 0x5666 +#define MDDI_VDO_PACKET_PRIM 0xC3 +#define MDDI_VDO_PACKET_SECD 0xC0 + +#endif diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c new file mode 100644 index 000000000000..ba2c4673b648 --- /dev/null +++ b/drivers/video/msm/mdp_ppp.c @@ -0,0 +1,750 @@ +/* drivers/video/msm/mdp_ppp.c + * + * Copyright (C) 2007 QUALCOMM Incorporated + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/fb.h> +#include <linux/file.h> +#include <linux/delay.h> +#include <linux/msm_mdp.h> +#include <linux/android_pmem.h> +#include <mach/msm_fb.h> + +#include "mdp_hw.h" +#include "mdp_scale_tables.h" + +#define DLOG(x...) do {} while (0) + +#define MDP_DOWNSCALE_BLUR (MDP_DOWNSCALE_MAX + 1) +static int downscale_y_table = MDP_DOWNSCALE_MAX; +static int downscale_x_table = MDP_DOWNSCALE_MAX; + +struct mdp_regs { + uint32_t src0; + uint32_t src1; + uint32_t dst0; + uint32_t dst1; + uint32_t src_cfg; + uint32_t dst_cfg; + uint32_t src_pack; + uint32_t dst_pack; + uint32_t src_rect; + uint32_t dst_rect; + uint32_t src_ystride; + uint32_t dst_ystride; + uint32_t op; + uint32_t src_bpp; + uint32_t dst_bpp; + uint32_t edge; + uint32_t phasex_init; + uint32_t phasey_init; + uint32_t phasex_step; + uint32_t phasey_step; +}; + +static uint32_t pack_pattern[] = { + PPP_ARRAY0(PACK_PATTERN) +}; + +static uint32_t src_img_cfg[] = { + PPP_ARRAY1(CFG, SRC) +}; + +static uint32_t dst_img_cfg[] = { + PPP_ARRAY1(CFG, DST) +}; + +static uint32_t bytes_per_pixel[] = { + [MDP_RGB_565] = 2, + [MDP_RGB_888] = 3, + [MDP_XRGB_8888] = 4, + [MDP_ARGB_8888] = 4, + [MDP_RGBA_8888] = 4, + [MDP_BGRA_8888] = 4, + [MDP_Y_CBCR_H2V1] = 1, + [MDP_Y_CBCR_H2V2] = 1, + [MDP_Y_CRCB_H2V1] = 1, + [MDP_Y_CRCB_H2V2] = 1, + [MDP_YCRYCB_H2V1] = 2 +}; + +static uint32_t dst_op_chroma[] = { + PPP_ARRAY1(CHROMA_SAMP, DST) +}; + +static uint32_t src_op_chroma[] = { + PPP_ARRAY1(CHROMA_SAMP, SRC) +}; + +static uint32_t bg_op_chroma[] = { + PPP_ARRAY1(CHROMA_SAMP, BG) +}; + +static void rotate_dst_addr_x(struct mdp_blit_req *req, struct mdp_regs *regs) +{ + regs->dst0 += (req->dst_rect.w - + min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp; + regs->dst1 += (req->dst_rect.w - + min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp; +} + +static void rotate_dst_addr_y(struct mdp_blit_req *req, struct mdp_regs *regs) +{ + regs->dst0 += (req->dst_rect.h - + min((uint32_t)16, req->dst_rect.h)) * + regs->dst_ystride; + regs->dst1 += (req->dst_rect.h - + min((uint32_t)16, req->dst_rect.h)) * + regs->dst_ystride; +} + +static void blit_rotate(struct mdp_blit_req *req, + struct mdp_regs *regs) +{ + if (req->flags == MDP_ROT_NOP) + return; + + regs->op |= PPP_OP_ROT_ON; + if ((req->flags & MDP_ROT_90 || req->flags & MDP_FLIP_LR) && + !(req->flags & MDP_ROT_90 && req->flags & MDP_FLIP_LR)) + rotate_dst_addr_x(req, regs); + if (req->flags & MDP_ROT_90) + regs->op |= PPP_OP_ROT_90; + if (req->flags & MDP_FLIP_UD) { + regs->op |= PPP_OP_FLIP_UD; + rotate_dst_addr_y(req, regs); + } + if (req->flags & MDP_FLIP_LR) + regs->op |= PPP_OP_FLIP_LR; +} + +static void blit_convert(struct mdp_blit_req *req, struct mdp_regs *regs) +{ + if (req->src.format == req->dst.format) + return; + if (IS_RGB(req->src.format) && IS_YCRCB(req->dst.format)) { + regs->op |= PPP_OP_CONVERT_RGB2YCBCR | PPP_OP_CONVERT_ON; + } else if (IS_YCRCB(req->src.format) && IS_RGB(req->dst.format)) { + regs->op |= PPP_OP_CONVERT_YCBCR2RGB | PPP_OP_CONVERT_ON; + if (req->dst.format == MDP_RGB_565) + regs->op |= PPP_OP_CONVERT_MATRIX_SECONDARY; + } +} + +#define GET_BIT_RANGE(value, high, low) \ + (((1 << (high - low + 1)) - 1) & (value >> low)) +static uint32_t transp_convert(struct mdp_blit_req *req) +{ + uint32_t transp = 0; + if (req->src.format == MDP_RGB_565) { + /* pad each value to 8 bits by copying the high bits into the + * low end, convert RGB to RBG by switching low 2 components */ + transp |= ((GET_BIT_RANGE(req->transp_mask, 15, 11) << 3) | + (GET_BIT_RANGE(req->transp_mask, 15, 13))) << 16; + + transp |= ((GET_BIT_RANGE(req->transp_mask, 4, 0) << 3) | + (GET_BIT_RANGE(req->transp_mask, 4, 2))) << 8; + + transp |= (GET_BIT_RANGE(req->transp_mask, 10, 5) << 2) | + (GET_BIT_RANGE(req->transp_mask, 10, 9)); + } else { + /* convert RGB to RBG */ + transp |= (GET_BIT_RANGE(req->transp_mask, 15, 8)) | + (GET_BIT_RANGE(req->transp_mask, 23, 16) << 16) | + (GET_BIT_RANGE(req->transp_mask, 7, 0) << 8); + } + return transp; +} +#undef GET_BIT_RANGE + +static void blit_blend(struct mdp_blit_req *req, struct mdp_regs *regs) +{ + /* TRANSP BLEND */ + if (req->transp_mask != MDP_TRANSP_NOP) { + req->transp_mask = transp_convert(req); + if (req->alpha != MDP_ALPHA_NOP) { + /* use blended transparancy mode + * pixel = (src == transp) ? dst : blend + * blend is combo of blend_eq_sel and + * blend_alpha_sel */ + regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON | + PPP_OP_BLEND_ALPHA_BLEND_NORMAL | + PPP_OP_BLEND_CONSTANT_ALPHA | + PPP_BLEND_ALPHA_TRANSP; + } else { + /* simple transparancy mode + * pixel = (src == transp) ? dst : src */ + regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON | + PPP_OP_BLEND_SRCPIXEL_TRANSP; + } + } + + req->alpha &= 0xff; + /* ALPHA BLEND */ + if (HAS_ALPHA(req->src.format)) { + regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON | + PPP_OP_BLEND_SRCPIXEL_ALPHA; + } else if (req->alpha < MDP_ALPHA_NOP) { + /* just blend by alpha */ + regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON | + PPP_OP_BLEND_ALPHA_BLEND_NORMAL | + PPP_OP_BLEND_CONSTANT_ALPHA; + } + + regs->op |= bg_op_chroma[req->dst.format]; +} + +#define ONE_HALF (1LL << 32) +#define ONE (1LL << 33) +#define TWO (2LL << 33) +#define THREE (3LL << 33) +#define FRAC_MASK (ONE - 1) +#define INT_MASK (~FRAC_MASK) + +static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin, + uint32_t *phase_init, uint32_t *phase_step) +{ + /* to improve precicsion calculations are done in U31.33 and converted + * to U3.29 at the end */ + int64_t k1, k2, k3, k4, tmp; + uint64_t n, d, os, os_p, od, od_p, oreq; + unsigned rpa = 0; + int64_t ip64, delta; + + if (dim_out % 3 == 0) + rpa = !(dim_in % (dim_out / 3)); + + n = ((uint64_t)dim_out) << 34; + d = dim_in; + if (!d) + return -1; + do_div(n, d); + k3 = (n + 1) >> 1; + if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31)) { + DLOG("crap bad scale\n"); + return -1; + } + n = ((uint64_t)dim_in) << 34; + d = (uint64_t)dim_out; + if (!d) + return -1; + do_div(n, d); + k1 = (n + 1) >> 1; + k2 = (k1 - ONE) >> 1; + + *phase_init = (int)(k2 >> 4); + k4 = (k3 - ONE) >> 1; + + if (rpa) { + os = ((uint64_t)origin << 33) - ONE_HALF; + tmp = (dim_out * os) + ONE_HALF; + if (!dim_in) + return -1; + do_div(tmp, dim_in); + od = tmp - ONE_HALF; + } else { + os = ((uint64_t)origin << 1) - 1; + od = (((k3 * os) >> 1) + k4); + } + + od_p = od & INT_MASK; + if (od_p != od) + od_p += ONE; + + if (rpa) { + tmp = (dim_in * od_p) + ONE_HALF; + if (!dim_in) + return -1; + do_div(tmp, dim_in); + os_p = tmp - ONE_HALF; + } else { + os_p = ((k1 * (od_p >> 33)) + k2); + } + + oreq = (os_p & INT_MASK) - ONE; + + ip64 = os_p - oreq; + delta = ((int64_t)(origin) << 33) - oreq; + ip64 -= delta; + /* limit to valid range before the left shift */ + delta = (ip64 & (1LL << 63)) ? 4 : -4; + delta <<= 33; + while (abs((int)(ip64 >> 33)) > 4) + ip64 += delta; + *phase_init = (int)(ip64 >> 4); + *phase_step = (uint32_t)(k1 >> 4); + return 0; +} + +static void load_scale_table(const struct mdp_info *mdp, + struct mdp_table_entry *table, int len) +{ + int i; + for (i = 0; i < len; i++) + mdp_writel(mdp, table[i].val, table[i].reg); +} + +enum { +IMG_LEFT, +IMG_RIGHT, +IMG_TOP, +IMG_BOTTOM, +}; + +static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst, + uint32_t *interp1, uint32_t *interp2, + uint32_t *repeat1, uint32_t *repeat2) { + if (src > 3 * dst) { + *interp1 = 0; + *interp2 = src - 1; + *repeat1 = 0; + *repeat2 = 0; + } else if (src == 3 * dst) { + *interp1 = 0; + *interp2 = src; + *repeat1 = 0; + *repeat2 = 1; + } else if (src > dst && src < 3 * dst) { + *interp1 = -1; + *interp2 = src; + *repeat1 = 1; + *repeat2 = 1; + } else if (src == dst) { + *interp1 = -1; + *interp2 = src + 1; + *repeat1 = 1; + *repeat2 = 2; + } else { + *interp1 = -2; + *interp2 = src + 1; + *repeat1 = 2; + *repeat2 = 2; + } + *interp1 += src_coord; + *interp2 += src_coord; +} + +static int get_edge_cond(struct mdp_blit_req *req, struct mdp_regs *regs) +{ + int32_t luma_interp[4]; + int32_t luma_repeat[4]; + int32_t chroma_interp[4]; + int32_t chroma_bound[4]; + int32_t chroma_repeat[4]; + uint32_t dst_w, dst_h; + + memset(&luma_interp, 0, sizeof(int32_t) * 4); + memset(&luma_repeat, 0, sizeof(int32_t) * 4); + memset(&chroma_interp, 0, sizeof(int32_t) * 4); + memset(&chroma_bound, 0, sizeof(int32_t) * 4); + memset(&chroma_repeat, 0, sizeof(int32_t) * 4); + regs->edge = 0; + + if (req->flags & MDP_ROT_90) { + dst_w = req->dst_rect.h; + dst_h = req->dst_rect.w; + } else { + dst_w = req->dst_rect.w; + dst_h = req->dst_rect.h; + } + + if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) { + get_edge_info(req->src_rect.h, req->src_rect.y, dst_h, + &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM], + &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]); + get_edge_info(req->src_rect.w, req->src_rect.x, dst_w, + &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT], + &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]); + } else { + luma_interp[IMG_LEFT] = req->src_rect.x; + luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1; + luma_interp[IMG_TOP] = req->src_rect.y; + luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1; + luma_repeat[IMG_LEFT] = 0; + luma_repeat[IMG_TOP] = 0; + luma_repeat[IMG_RIGHT] = 0; + luma_repeat[IMG_BOTTOM] = 0; + } + + chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT]; + chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT]; + chroma_interp[IMG_TOP] = luma_interp[IMG_TOP]; + chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM]; + + chroma_bound[IMG_LEFT] = req->src_rect.x; + chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1; + chroma_bound[IMG_TOP] = req->src_rect.y; + chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1; + + if (IS_YCRCB(req->src.format)) { + chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1; + chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1; + + chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1; + chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1; + } + + if (req->src.format == MDP_Y_CBCR_H2V2 || + req->src.format == MDP_Y_CRCB_H2V2) { + chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1; + chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1) + >> 1; + chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1; + chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1; + } + + chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] - + chroma_interp[IMG_LEFT]; + chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] - + chroma_bound[IMG_RIGHT]; + chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] - + chroma_interp[IMG_TOP]; + chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] - + chroma_bound[IMG_BOTTOM]; + + if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 || + chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 || + chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 || + chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 || + luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 || + luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 || + luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 || + luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3) + return -1; + + regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA; + regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA; + regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA; + regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA; + regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA; + regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA; + regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA; + regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA; + return 0; +} + +static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req, + struct mdp_regs *regs) +{ + uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y; + uint32_t scale_factor_x, scale_factor_y; + uint32_t downscale; + uint32_t dst_w, dst_h; + + if (req->flags & MDP_ROT_90) { + dst_w = req->dst_rect.h; + dst_h = req->dst_rect.w; + } else { + dst_w = req->dst_rect.w; + dst_h = req->dst_rect.h; + } + if ((req->src_rect.w == dst_w) && (req->src_rect.h == dst_h) && + !(req->flags & MDP_BLUR)) { + regs->phasex_init = 0; + regs->phasey_init = 0; + regs->phasex_step = 0; + regs->phasey_step = 0; + return 0; + } + + if (scale_params(req->src_rect.w, dst_w, 1, &phase_init_x, + &phase_step_x) || + scale_params(req->src_rect.h, dst_h, 1, &phase_init_y, + &phase_step_y)) + return -1; + + scale_factor_x = (dst_w * 10) / req->src_rect.w; + scale_factor_y = (dst_h * 10) / req->src_rect.h; + + if (scale_factor_x > 8) + downscale = MDP_DOWNSCALE_PT8TO1; + else if (scale_factor_x > 6) + downscale = MDP_DOWNSCALE_PT6TOPT8; + else if (scale_factor_x > 4) + downscale = MDP_DOWNSCALE_PT4TOPT6; + else + downscale = MDP_DOWNSCALE_PT2TOPT4; + if (downscale != downscale_x_table) { + load_scale_table(mdp, mdp_downscale_x_table[downscale], 64); + downscale_x_table = downscale; + } + + if (scale_factor_y > 8) + downscale = MDP_DOWNSCALE_PT8TO1; + else if (scale_factor_y > 6) + downscale = MDP_DOWNSCALE_PT6TOPT8; + else if (scale_factor_y > 4) + downscale = MDP_DOWNSCALE_PT4TOPT6; + else + downscale = MDP_DOWNSCALE_PT2TOPT4; + if (downscale != downscale_y_table) { + load_scale_table(mdp, mdp_downscale_y_table[downscale], 64); + downscale_y_table = downscale; + } + + regs->phasex_init = phase_init_x; + regs->phasey_init = phase_init_y; + regs->phasex_step = phase_step_x; + regs->phasey_step = phase_step_y; + regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON); + return 0; + +} + +static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req, + struct mdp_regs *regs) +{ + if (!(req->flags & MDP_BLUR)) + return; + + if (!(downscale_x_table == MDP_DOWNSCALE_BLUR && + downscale_y_table == MDP_DOWNSCALE_BLUR)) { + load_scale_table(mdp, mdp_gaussian_blur_table, 128); + downscale_x_table = MDP_DOWNSCALE_BLUR; + downscale_y_table = MDP_DOWNSCALE_BLUR; + } + + regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON); +} + + +#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp) + +#define Y_TO_CRCB_RATIO(format) \ + ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\ + (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1) + +static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp, + uint32_t *len0, uint32_t *len1) +{ + *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp); + if (IS_PSEUDOPLNR(img->format)) + *len1 = *len0/Y_TO_CRCB_RATIO(img->format); + else + *len1 = 0; +} + +static int valid_src_dst(unsigned long src_start, unsigned long src_len, + unsigned long dst_start, unsigned long dst_len, + struct mdp_blit_req *req, struct mdp_regs *regs) +{ + unsigned long src_min_ok = src_start; + unsigned long src_max_ok = src_start + src_len; + unsigned long dst_min_ok = dst_start; + unsigned long dst_max_ok = dst_start + dst_len; + uint32_t src0_len, src1_len, dst0_len, dst1_len; + get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len, + &src1_len); + get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len, + &dst1_len); + + if (regs->src0 < src_min_ok || regs->src0 > src_max_ok || + regs->src0 + src0_len > src_max_ok) { + DLOG("invalid_src %x %x %lx %lx\n", regs->src0, + src0_len, src_min_ok, src_max_ok); + return 0; + } + if (regs->src_cfg & PPP_SRC_PLANE_PSEUDOPLNR) { + if (regs->src1 < src_min_ok || regs->src1 > src_max_ok || + regs->src1 + src1_len > src_max_ok) { + DLOG("invalid_src1"); + return 0; + } + } + if (regs->dst0 < dst_min_ok || regs->dst0 > dst_max_ok || + regs->dst0 + dst0_len > dst_max_ok) { + DLOG("invalid_dst"); + return 0; + } + if (regs->dst_cfg & PPP_SRC_PLANE_PSEUDOPLNR) { + if (regs->dst1 < dst_min_ok || regs->dst1 > dst_max_ok || + regs->dst1 + dst1_len > dst_max_ok) { + DLOG("invalid_dst1"); + return 0; + } + } + return 1; +} + + +static void flush_imgs(struct mdp_blit_req *req, struct mdp_regs *regs, + struct file *src_file, struct file *dst_file) +{ +#ifdef CONFIG_ANDROID_PMEM + uint32_t src0_len, src1_len, dst0_len, dst1_len; + + /* flush src images to memory before dma to mdp */ + get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len, + &src1_len); + flush_pmem_file(src_file, req->src.offset, src0_len); + if (IS_PSEUDOPLNR(req->src.format)) + flush_pmem_file(src_file, req->src.offset + src0_len, + src1_len); + + /* flush dst images */ + get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len, + &dst1_len); + flush_pmem_file(dst_file, req->dst.offset, dst0_len); + if (IS_PSEUDOPLNR(req->dst.format)) + flush_pmem_file(dst_file, req->dst.offset + dst0_len, + dst1_len); +#endif +} + +static void get_chroma_addr(struct mdp_img *img, struct mdp_rect *rect, + uint32_t base, uint32_t bpp, uint32_t cfg, + uint32_t *addr, uint32_t *ystride) +{ + uint32_t compress_v = Y_TO_CRCB_RATIO(img->format); + uint32_t compress_h = 2; + uint32_t offset; + + if (IS_PSEUDOPLNR(img->format)) { + offset = (rect->x / compress_h) * compress_h; + offset += rect->y == 0 ? 0 : + ((rect->y + 1) / compress_v) * img->width; + *addr = base + (img->width * img->height * bpp); + *addr += offset * bpp; + *ystride |= *ystride << 16; + } else { + *addr = 0; + } +} + +static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req, + struct mdp_regs *regs, struct file *src_file, + struct file *dst_file) +{ + mdp_writel(mdp, 1, 0x060); + mdp_writel(mdp, regs->src_rect, PPP_ADDR_SRC_ROI); + mdp_writel(mdp, regs->src0, PPP_ADDR_SRC0); + mdp_writel(mdp, regs->src1, PPP_ADDR_SRC1); + mdp_writel(mdp, regs->src_ystride, PPP_ADDR_SRC_YSTRIDE); + mdp_writel(mdp, regs->src_cfg, PPP_ADDR_SRC_CFG); + mdp_writel(mdp, regs->src_pack, PPP_ADDR_SRC_PACK_PATTERN); + + mdp_writel(mdp, regs->op, PPP_ADDR_OPERATION); + mdp_writel(mdp, regs->phasex_init, PPP_ADDR_PHASEX_INIT); + mdp_writel(mdp, regs->phasey_init, PPP_ADDR_PHASEY_INIT); + mdp_writel(mdp, regs->phasex_step, PPP_ADDR_PHASEX_STEP); + mdp_writel(mdp, regs->phasey_step, PPP_ADDR_PHASEY_STEP); + + mdp_writel(mdp, (req->alpha << 24) | (req->transp_mask & 0xffffff), + PPP_ADDR_ALPHA_TRANSP); + + mdp_writel(mdp, regs->dst_cfg, PPP_ADDR_DST_CFG); + mdp_writel(mdp, regs->dst_pack, PPP_ADDR_DST_PACK_PATTERN); + mdp_writel(mdp, regs->dst_rect, PPP_ADDR_DST_ROI); + mdp_writel(mdp, regs->dst0, PPP_ADDR_DST0); + mdp_writel(mdp, regs->dst1, PPP_ADDR_DST1); + mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_DST_YSTRIDE); + + mdp_writel(mdp, regs->edge, PPP_ADDR_EDGE); + if (regs->op & PPP_OP_BLEND_ON) { + mdp_writel(mdp, regs->dst0, PPP_ADDR_BG0); + mdp_writel(mdp, regs->dst1, PPP_ADDR_BG1); + mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_BG_YSTRIDE); + mdp_writel(mdp, src_img_cfg[req->dst.format], PPP_ADDR_BG_CFG); + mdp_writel(mdp, pack_pattern[req->dst.format], + PPP_ADDR_BG_PACK_PATTERN); + } + flush_imgs(req, regs, src_file, dst_file); + mdp_writel(mdp, 0x1000, MDP_DISPLAY0_START); + return 0; +} + +int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req, + struct file *src_file, unsigned long src_start, unsigned long src_len, + struct file *dst_file, unsigned long dst_start, unsigned long dst_len) +{ + struct mdp_regs regs = {0}; + + if (unlikely(req->src.format >= MDP_IMGTYPE_LIMIT || + req->dst.format >= MDP_IMGTYPE_LIMIT)) { + printk(KERN_ERR "mpd_ppp: img is of wrong format\n"); + return -EINVAL; + } + + if (unlikely(req->src_rect.x > req->src.width || + req->src_rect.y > req->src.height || + req->dst_rect.x > req->dst.width || + req->dst_rect.y > req->dst.height)) { + printk(KERN_ERR "mpd_ppp: img rect is outside of img!\n"); + return -EINVAL; + } + + /* set the src image configuration */ + regs.src_cfg = src_img_cfg[req->src.format]; + regs.src_cfg |= (req->src_rect.x & 0x1) ? PPP_SRC_BPP_ROI_ODD_X : 0; + regs.src_cfg |= (req->src_rect.y & 0x1) ? PPP_SRC_BPP_ROI_ODD_Y : 0; + regs.src_rect = (req->src_rect.h << 16) | req->src_rect.w; + regs.src_pack = pack_pattern[req->src.format]; + + /* set the dest image configuration */ + regs.dst_cfg = dst_img_cfg[req->dst.format] | PPP_DST_OUT_SEL_AXI; + regs.dst_rect = (req->dst_rect.h << 16) | req->dst_rect.w; + regs.dst_pack = pack_pattern[req->dst.format]; + + /* set src, bpp, start pixel and ystride */ + regs.src_bpp = bytes_per_pixel[req->src.format]; + regs.src0 = src_start + req->src.offset; + regs.src_ystride = req->src.width * regs.src_bpp; + get_chroma_addr(&req->src, &req->src_rect, regs.src0, regs.src_bpp, + regs.src_cfg, ®s.src1, ®s.src_ystride); + regs.src0 += (req->src_rect.x + (req->src_rect.y * req->src.width)) * + regs.src_bpp; + + /* set dst, bpp, start pixel and ystride */ + regs.dst_bpp = bytes_per_pixel[req->dst.format]; + regs.dst0 = dst_start + req->dst.offset; + regs.dst_ystride = req->dst.width * regs.dst_bpp; + get_chroma_addr(&req->dst, &req->dst_rect, regs.dst0, regs.dst_bpp, + regs.dst_cfg, ®s.dst1, ®s.dst_ystride); + regs.dst0 += (req->dst_rect.x + (req->dst_rect.y * req->dst.width)) * + regs.dst_bpp; + + if (!valid_src_dst(src_start, src_len, dst_start, dst_len, req, + ®s)) { + printk(KERN_ERR "mpd_ppp: final src or dst location is " + "invalid, are you trying to make an image too large " + "or to place it outside the screen?\n"); + return -EINVAL; + } + + /* set up operation register */ + regs.op = 0; + blit_rotate(req, ®s); + blit_convert(req, ®s); + if (req->flags & MDP_DITHER) + regs.op |= PPP_OP_DITHER_EN; + blit_blend(req, ®s); + if (blit_scale(mdp, req, ®s)) { + printk(KERN_ERR "mpd_ppp: error computing scale for img.\n"); + return -EINVAL; + } + blit_blur(mdp, req, ®s); + regs.op |= dst_op_chroma[req->dst.format] | + src_op_chroma[req->src.format]; + + /* if the image is YCRYCB, the x and w must be even */ + if (unlikely(req->src.format == MDP_YCRYCB_H2V1)) { + req->src_rect.x = req->src_rect.x & (~0x1); + req->src_rect.w = req->src_rect.w & (~0x1); + req->dst_rect.x = req->dst_rect.x & (~0x1); + req->dst_rect.w = req->dst_rect.w & (~0x1); + } + if (get_edge_cond(req, ®s)) + return -EINVAL; + + send_blit(mdp, req, ®s, src_file, dst_file); + return 0; +} diff --git a/drivers/video/msm/mdp_scale_tables.c b/drivers/video/msm/mdp_scale_tables.c new file mode 100644 index 000000000000..604783b2e17c --- /dev/null +++ b/drivers/video/msm/mdp_scale_tables.c @@ -0,0 +1,766 @@ +/* drivers/video/msm_fb/mdp_scale_tables.c + * + * Copyright (C) 2007 QUALCOMM Incorporated + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "mdp_scale_tables.h" +#include "mdp_hw.h" + +struct mdp_table_entry mdp_upscale_table[] = { + { 0x5fffc, 0x0 }, + { 0x50200, 0x7fc00000 }, + { 0x5fffc, 0xff80000d }, + { 0x50204, 0x7ec003f9 }, + { 0x5fffc, 0xfec0001c }, + { 0x50208, 0x7d4003f3 }, + { 0x5fffc, 0xfe40002b }, + { 0x5020c, 0x7b8003ed }, + { 0x5fffc, 0xfd80003c }, + { 0x50210, 0x794003e8 }, + { 0x5fffc, 0xfcc0004d }, + { 0x50214, 0x76c003e4 }, + { 0x5fffc, 0xfc40005f }, + { 0x50218, 0x73c003e0 }, + { 0x5fffc, 0xfb800071 }, + { 0x5021c, 0x708003de }, + { 0x5fffc, 0xfac00085 }, + { 0x50220, 0x6d0003db }, + { 0x5fffc, 0xfa000098 }, + { 0x50224, 0x698003d9 }, + { 0x5fffc, 0xf98000ac }, + { 0x50228, 0x654003d8 }, + { 0x5fffc, 0xf8c000c1 }, + { 0x5022c, 0x610003d7 }, + { 0x5fffc, 0xf84000d5 }, + { 0x50230, 0x5c8003d7 }, + { 0x5fffc, 0xf7c000e9 }, + { 0x50234, 0x580003d7 }, + { 0x5fffc, 0xf74000fd }, + { 0x50238, 0x534003d8 }, + { 0x5fffc, 0xf6c00112 }, + { 0x5023c, 0x4e8003d8 }, + { 0x5fffc, 0xf6800126 }, + { 0x50240, 0x494003da }, + { 0x5fffc, 0xf600013a }, + { 0x50244, 0x448003db }, + { 0x5fffc, 0xf600014d }, + { 0x50248, 0x3f4003dd }, + { 0x5fffc, 0xf5c00160 }, + { 0x5024c, 0x3a4003df }, + { 0x5fffc, 0xf5c00172 }, + { 0x50250, 0x354003e1 }, + { 0x5fffc, 0xf5c00184 }, + { 0x50254, 0x304003e3 }, + { 0x5fffc, 0xf6000195 }, + { 0x50258, 0x2b0003e6 }, + { 0x5fffc, 0xf64001a6 }, + { 0x5025c, 0x260003e8 }, + { 0x5fffc, 0xf6c001b4 }, + { 0x50260, 0x214003eb }, + { 0x5fffc, 0xf78001c2 }, + { 0x50264, 0x1c4003ee }, + { 0x5fffc, 0xf80001cf }, + { 0x50268, 0x17c003f1 }, + { 0x5fffc, 0xf90001db }, + { 0x5026c, 0x134003f3 }, + { 0x5fffc, 0xfa0001e5 }, + { 0x50270, 0xf0003f6 }, + { 0x5fffc, 0xfb4001ee }, + { 0x50274, 0xac003f9 }, + { 0x5fffc, 0xfcc001f5 }, + { 0x50278, 0x70003fb }, + { 0x5fffc, 0xfe4001fb }, + { 0x5027c, 0x34003fe }, +}; + +static struct mdp_table_entry mdp_downscale_x_table_PT2TOPT4[] = { + { 0x5fffc, 0x740008c }, + { 0x50280, 0x33800088 }, + { 0x5fffc, 0x800008e }, + { 0x50284, 0x33400084 }, + { 0x5fffc, 0x8400092 }, + { 0x50288, 0x33000080 }, + { 0x5fffc, 0x9000094 }, + { 0x5028c, 0x3300007b }, + { 0x5fffc, 0x9c00098 }, + { 0x50290, 0x32400077 }, + { 0x5fffc, 0xa40009b }, + { 0x50294, 0x32000073 }, + { 0x5fffc, 0xb00009d }, + { 0x50298, 0x31c0006f }, + { 0x5fffc, 0xbc000a0 }, + { 0x5029c, 0x3140006b }, + { 0x5fffc, 0xc8000a2 }, + { 0x502a0, 0x31000067 }, + { 0x5fffc, 0xd8000a5 }, + { 0x502a4, 0x30800062 }, + { 0x5fffc, 0xe4000a8 }, + { 0x502a8, 0x2fc0005f }, + { 0x5fffc, 0xec000aa }, + { 0x502ac, 0x2fc0005b }, + { 0x5fffc, 0xf8000ad }, + { 0x502b0, 0x2f400057 }, + { 0x5fffc, 0x108000b0 }, + { 0x502b4, 0x2e400054 }, + { 0x5fffc, 0x114000b2 }, + { 0x502b8, 0x2e000050 }, + { 0x5fffc, 0x124000b4 }, + { 0x502bc, 0x2d80004c }, + { 0x5fffc, 0x130000b6 }, + { 0x502c0, 0x2d000049 }, + { 0x5fffc, 0x140000b8 }, + { 0x502c4, 0x2c800045 }, + { 0x5fffc, 0x150000b9 }, + { 0x502c8, 0x2c000042 }, + { 0x5fffc, 0x15c000bd }, + { 0x502cc, 0x2b40003e }, + { 0x5fffc, 0x16c000bf }, + { 0x502d0, 0x2a80003b }, + { 0x5fffc, 0x17c000bf }, + { 0x502d4, 0x2a000039 }, + { 0x5fffc, 0x188000c2 }, + { 0x502d8, 0x29400036 }, + { 0x5fffc, 0x19c000c4 }, + { 0x502dc, 0x28800032 }, + { 0x5fffc, 0x1ac000c5 }, + { 0x502e0, 0x2800002f }, + { 0x5fffc, 0x1bc000c7 }, + { 0x502e4, 0x2740002c }, + { 0x5fffc, 0x1cc000c8 }, + { 0x502e8, 0x26c00029 }, + { 0x5fffc, 0x1dc000c9 }, + { 0x502ec, 0x26000027 }, + { 0x5fffc, 0x1ec000cc }, + { 0x502f0, 0x25000024 }, + { 0x5fffc, 0x200000cc }, + { 0x502f4, 0x24800021 }, + { 0x5fffc, 0x210000cd }, + { 0x502f8, 0x23800020 }, + { 0x5fffc, 0x220000ce }, + { 0x502fc, 0x2300001d }, +}; + +static struct mdp_table_entry mdp_downscale_x_table_PT4TOPT6[] = { + { 0x5fffc, 0x740008c }, + { 0x50280, 0x33800088 }, + { 0x5fffc, 0x800008e }, + { 0x50284, 0x33400084 }, + { 0x5fffc, 0x8400092 }, + { 0x50288, 0x33000080 }, + { 0x5fffc, 0x9000094 }, + { 0x5028c, 0x3300007b }, + { 0x5fffc, 0x9c00098 }, + { 0x50290, 0x32400077 }, + { 0x5fffc, 0xa40009b }, + { 0x50294, 0x32000073 }, + { 0x5fffc, 0xb00009d }, + { 0x50298, 0x31c0006f }, + { 0x5fffc, 0xbc000a0 }, + { 0x5029c, 0x3140006b }, + { 0x5fffc, 0xc8000a2 }, + { 0x502a0, 0x31000067 }, + { 0x5fffc, 0xd8000a5 }, + { 0x502a4, 0x30800062 }, + { 0x5fffc, 0xe4000a8 }, + { 0x502a8, 0x2fc0005f }, + { 0x5fffc, 0xec000aa }, + { 0x502ac, 0x2fc0005b }, + { 0x5fffc, 0xf8000ad }, + { 0x502b0, 0x2f400057 }, + { 0x5fffc, 0x108000b0 }, + { 0x502b4, 0x2e400054 }, + { 0x5fffc, 0x114000b2 }, + { 0x502b8, 0x2e000050 }, + { 0x5fffc, 0x124000b4 }, + { 0x502bc, 0x2d80004c }, + { 0x5fffc, 0x130000b6 }, + { 0x502c0, 0x2d000049 }, + { 0x5fffc, 0x140000b8 }, + { 0x502c4, 0x2c800045 }, + { 0x5fffc, 0x150000b9 }, + { 0x502c8, 0x2c000042 }, + { 0x5fffc, 0x15c000bd }, + { 0x502cc, 0x2b40003e }, + { 0x5fffc, 0x16c000bf }, + { 0x502d0, 0x2a80003b }, + { 0x5fffc, 0x17c000bf }, + { 0x502d4, 0x2a000039 }, + { 0x5fffc, 0x188000c2 }, + { 0x502d8, 0x29400036 }, + { 0x5fffc, 0x19c000c4 }, + { 0x502dc, 0x28800032 }, + { 0x5fffc, 0x1ac000c5 }, + { 0x502e0, 0x2800002f }, + { 0x5fffc, 0x1bc000c7 }, + { 0x502e4, 0x2740002c }, + { 0x5fffc, 0x1cc000c8 }, + { 0x502e8, 0x26c00029 }, + { 0x5fffc, 0x1dc000c9 }, + { 0x502ec, 0x26000027 }, + { 0x5fffc, 0x1ec000cc }, + { 0x502f0, 0x25000024 }, + { 0x5fffc, 0x200000cc }, + { 0x502f4, 0x24800021 }, + { 0x5fffc, 0x210000cd }, + { 0x502f8, 0x23800020 }, + { 0x5fffc, 0x220000ce }, + { 0x502fc, 0x2300001d }, +}; + +static struct mdp_table_entry mdp_downscale_x_table_PT6TOPT8[] = { + { 0x5fffc, 0xfe000070 }, + { 0x50280, 0x4bc00068 }, + { 0x5fffc, 0xfe000078 }, + { 0x50284, 0x4bc00060 }, + { 0x5fffc, 0xfe000080 }, + { 0x50288, 0x4b800059 }, + { 0x5fffc, 0xfe000089 }, + { 0x5028c, 0x4b000052 }, + { 0x5fffc, 0xfe400091 }, + { 0x50290, 0x4a80004b }, + { 0x5fffc, 0xfe40009a }, + { 0x50294, 0x4a000044 }, + { 0x5fffc, 0xfe8000a3 }, + { 0x50298, 0x4940003d }, + { 0x5fffc, 0xfec000ac }, + { 0x5029c, 0x48400037 }, + { 0x5fffc, 0xff0000b4 }, + { 0x502a0, 0x47800031 }, + { 0x5fffc, 0xff8000bd }, + { 0x502a4, 0x4640002b }, + { 0x5fffc, 0xc5 }, + { 0x502a8, 0x45000026 }, + { 0x5fffc, 0x8000ce }, + { 0x502ac, 0x43800021 }, + { 0x5fffc, 0x10000d6 }, + { 0x502b0, 0x4240001c }, + { 0x5fffc, 0x18000df }, + { 0x502b4, 0x40800018 }, + { 0x5fffc, 0x24000e6 }, + { 0x502b8, 0x3f000014 }, + { 0x5fffc, 0x30000ee }, + { 0x502bc, 0x3d400010 }, + { 0x5fffc, 0x40000f5 }, + { 0x502c0, 0x3b80000c }, + { 0x5fffc, 0x50000fc }, + { 0x502c4, 0x39800009 }, + { 0x5fffc, 0x6000102 }, + { 0x502c8, 0x37c00006 }, + { 0x5fffc, 0x7000109 }, + { 0x502cc, 0x35800004 }, + { 0x5fffc, 0x840010e }, + { 0x502d0, 0x33800002 }, + { 0x5fffc, 0x9800114 }, + { 0x502d4, 0x31400000 }, + { 0x5fffc, 0xac00119 }, + { 0x502d8, 0x2f4003fe }, + { 0x5fffc, 0xc40011e }, + { 0x502dc, 0x2d0003fc }, + { 0x5fffc, 0xdc00121 }, + { 0x502e0, 0x2b0003fb }, + { 0x5fffc, 0xf400125 }, + { 0x502e4, 0x28c003fa }, + { 0x5fffc, 0x11000128 }, + { 0x502e8, 0x268003f9 }, + { 0x5fffc, 0x12c0012a }, + { 0x502ec, 0x244003f9 }, + { 0x5fffc, 0x1480012c }, + { 0x502f0, 0x224003f8 }, + { 0x5fffc, 0x1640012e }, + { 0x502f4, 0x200003f8 }, + { 0x5fffc, 0x1800012f }, + { 0x502f8, 0x1e0003f8 }, + { 0x5fffc, 0x1a00012f }, + { 0x502fc, 0x1c0003f8 }, +}; + +static struct mdp_table_entry mdp_downscale_x_table_PT8TO1[] = { + { 0x5fffc, 0x0 }, + { 0x50280, 0x7fc00000 }, + { 0x5fffc, 0xff80000d }, + { 0x50284, 0x7ec003f9 }, + { 0x5fffc, 0xfec0001c }, + { 0x50288, 0x7d4003f3 }, + { 0x5fffc, 0xfe40002b }, + { 0x5028c, 0x7b8003ed }, + { 0x5fffc, 0xfd80003c }, + { 0x50290, 0x794003e8 }, + { 0x5fffc, 0xfcc0004d }, + { 0x50294, 0x76c003e4 }, + { 0x5fffc, 0xfc40005f }, + { 0x50298, 0x73c003e0 }, + { 0x5fffc, 0xfb800071 }, + { 0x5029c, 0x708003de }, + { 0x5fffc, 0xfac00085 }, + { 0x502a0, 0x6d0003db }, + { 0x5fffc, 0xfa000098 }, + { 0x502a4, 0x698003d9 }, + { 0x5fffc, 0xf98000ac }, + { 0x502a8, 0x654003d8 }, + { 0x5fffc, 0xf8c000c1 }, + { 0x502ac, 0x610003d7 }, + { 0x5fffc, 0xf84000d5 }, + { 0x502b0, 0x5c8003d7 }, + { 0x5fffc, 0xf7c000e9 }, + { 0x502b4, 0x580003d7 }, + { 0x5fffc, 0xf74000fd }, + { 0x502b8, 0x534003d8 }, + { 0x5fffc, 0xf6c00112 }, + { 0x502bc, 0x4e8003d8 }, + { 0x5fffc, 0xf6800126 }, + { 0x502c0, 0x494003da }, + { 0x5fffc, 0xf600013a }, + { 0x502c4, 0x448003db }, + { 0x5fffc, 0xf600014d }, + { 0x502c8, 0x3f4003dd }, + { 0x5fffc, 0xf5c00160 }, + { 0x502cc, 0x3a4003df }, + { 0x5fffc, 0xf5c00172 }, + { 0x502d0, 0x354003e1 }, + { 0x5fffc, 0xf5c00184 }, + { 0x502d4, 0x304003e3 }, + { 0x5fffc, 0xf6000195 }, + { 0x502d8, 0x2b0003e6 }, + { 0x5fffc, 0xf64001a6 }, + { 0x502dc, 0x260003e8 }, + { 0x5fffc, 0xf6c001b4 }, + { 0x502e0, 0x214003eb }, + { 0x5fffc, 0xf78001c2 }, + { 0x502e4, 0x1c4003ee }, + { 0x5fffc, 0xf80001cf }, + { 0x502e8, 0x17c003f1 }, + { 0x5fffc, 0xf90001db }, + { 0x502ec, 0x134003f3 }, + { 0x5fffc, 0xfa0001e5 }, + { 0x502f0, 0xf0003f6 }, + { 0x5fffc, 0xfb4001ee }, + { 0x502f4, 0xac003f9 }, + { 0x5fffc, 0xfcc001f5 }, + { 0x502f8, 0x70003fb }, + { 0x5fffc, 0xfe4001fb }, + { 0x502fc, 0x34003fe }, +}; + +struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX] = { + [MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_x_table_PT2TOPT4, + [MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_x_table_PT4TOPT6, + [MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_x_table_PT6TOPT8, + [MDP_DOWNSCALE_PT8TO1] = mdp_downscale_x_table_PT8TO1, +}; + +static struct mdp_table_entry mdp_downscale_y_table_PT2TOPT4[] = { + { 0x5fffc, 0x740008c }, + { 0x50300, 0x33800088 }, + { 0x5fffc, 0x800008e }, + { 0x50304, 0x33400084 }, + { 0x5fffc, 0x8400092 }, + { 0x50308, 0x33000080 }, + { 0x5fffc, 0x9000094 }, + { 0x5030c, 0x3300007b }, + { 0x5fffc, 0x9c00098 }, + { 0x50310, 0x32400077 }, + { 0x5fffc, 0xa40009b }, + { 0x50314, 0x32000073 }, + { 0x5fffc, 0xb00009d }, + { 0x50318, 0x31c0006f }, + { 0x5fffc, 0xbc000a0 }, + { 0x5031c, 0x3140006b }, + { 0x5fffc, 0xc8000a2 }, + { 0x50320, 0x31000067 }, + { 0x5fffc, 0xd8000a5 }, + { 0x50324, 0x30800062 }, + { 0x5fffc, 0xe4000a8 }, + { 0x50328, 0x2fc0005f }, + { 0x5fffc, 0xec000aa }, + { 0x5032c, 0x2fc0005b }, + { 0x5fffc, 0xf8000ad }, + { 0x50330, 0x2f400057 }, + { 0x5fffc, 0x108000b0 }, + { 0x50334, 0x2e400054 }, + { 0x5fffc, 0x114000b2 }, + { 0x50338, 0x2e000050 }, + { 0x5fffc, 0x124000b4 }, + { 0x5033c, 0x2d80004c }, + { 0x5fffc, 0x130000b6 }, + { 0x50340, 0x2d000049 }, + { 0x5fffc, 0x140000b8 }, + { 0x50344, 0x2c800045 }, + { 0x5fffc, 0x150000b9 }, + { 0x50348, 0x2c000042 }, + { 0x5fffc, 0x15c000bd }, + { 0x5034c, 0x2b40003e }, + { 0x5fffc, 0x16c000bf }, + { 0x50350, 0x2a80003b }, + { 0x5fffc, 0x17c000bf }, + { 0x50354, 0x2a000039 }, + { 0x5fffc, 0x188000c2 }, + { 0x50358, 0x29400036 }, + { 0x5fffc, 0x19c000c4 }, + { 0x5035c, 0x28800032 }, + { 0x5fffc, 0x1ac000c5 }, + { 0x50360, 0x2800002f }, + { 0x5fffc, 0x1bc000c7 }, + { 0x50364, 0x2740002c }, + { 0x5fffc, 0x1cc000c8 }, + { 0x50368, 0x26c00029 }, + { 0x5fffc, 0x1dc000c9 }, + { 0x5036c, 0x26000027 }, + { 0x5fffc, 0x1ec000cc }, + { 0x50370, 0x25000024 }, + { 0x5fffc, 0x200000cc }, + { 0x50374, 0x24800021 }, + { 0x5fffc, 0x210000cd }, + { 0x50378, 0x23800020 }, + { 0x5fffc, 0x220000ce }, + { 0x5037c, 0x2300001d }, +}; + +static struct mdp_table_entry mdp_downscale_y_table_PT4TOPT6[] = { + { 0x5fffc, 0x740008c }, + { 0x50300, 0x33800088 }, + { 0x5fffc, 0x800008e }, + { 0x50304, 0x33400084 }, + { 0x5fffc, 0x8400092 }, + { 0x50308, 0x33000080 }, + { 0x5fffc, 0x9000094 }, + { 0x5030c, 0x3300007b }, + { 0x5fffc, 0x9c00098 }, + { 0x50310, 0x32400077 }, + { 0x5fffc, 0xa40009b }, + { 0x50314, 0x32000073 }, + { 0x5fffc, 0xb00009d }, + { 0x50318, 0x31c0006f }, + { 0x5fffc, 0xbc000a0 }, + { 0x5031c, 0x3140006b }, + { 0x5fffc, 0xc8000a2 }, + { 0x50320, 0x31000067 }, + { 0x5fffc, 0xd8000a5 }, + { 0x50324, 0x30800062 }, + { 0x5fffc, 0xe4000a8 }, + { 0x50328, 0x2fc0005f }, + { 0x5fffc, 0xec000aa }, + { 0x5032c, 0x2fc0005b }, + { 0x5fffc, 0xf8000ad }, + { 0x50330, 0x2f400057 }, + { 0x5fffc, 0x108000b0 }, + { 0x50334, 0x2e400054 }, + { 0x5fffc, 0x114000b2 }, + { 0x50338, 0x2e000050 }, + { 0x5fffc, 0x124000b4 }, + { 0x5033c, 0x2d80004c }, + { 0x5fffc, 0x130000b6 }, + { 0x50340, 0x2d000049 }, + { 0x5fffc, 0x140000b8 }, + { 0x50344, 0x2c800045 }, + { 0x5fffc, 0x150000b9 }, + { 0x50348, 0x2c000042 }, + { 0x5fffc, 0x15c000bd }, + { 0x5034c, 0x2b40003e }, + { 0x5fffc, 0x16c000bf }, + { 0x50350, 0x2a80003b }, + { 0x5fffc, 0x17c000bf }, + { 0x50354, 0x2a000039 }, + { 0x5fffc, 0x188000c2 }, + { 0x50358, 0x29400036 }, + { 0x5fffc, 0x19c000c4 }, + { 0x5035c, 0x28800032 }, + { 0x5fffc, 0x1ac000c5 }, + { 0x50360, 0x2800002f }, + { 0x5fffc, 0x1bc000c7 }, + { 0x50364, 0x2740002c }, + { 0x5fffc, 0x1cc000c8 }, + { 0x50368, 0x26c00029 }, + { 0x5fffc, 0x1dc000c9 }, + { 0x5036c, 0x26000027 }, + { 0x5fffc, 0x1ec000cc }, + { 0x50370, 0x25000024 }, + { 0x5fffc, 0x200000cc }, + { 0x50374, 0x24800021 }, + { 0x5fffc, 0x210000cd }, + { 0x50378, 0x23800020 }, + { 0x5fffc, 0x220000ce }, + { 0x5037c, 0x2300001d }, +}; + +static struct mdp_table_entry mdp_downscale_y_table_PT6TOPT8[] = { + { 0x5fffc, 0xfe000070 }, + { 0x50300, 0x4bc00068 }, + { 0x5fffc, 0xfe000078 }, + { 0x50304, 0x4bc00060 }, + { 0x5fffc, 0xfe000080 }, + { 0x50308, 0x4b800059 }, + { 0x5fffc, 0xfe000089 }, + { 0x5030c, 0x4b000052 }, + { 0x5fffc, 0xfe400091 }, + { 0x50310, 0x4a80004b }, + { 0x5fffc, 0xfe40009a }, + { 0x50314, 0x4a000044 }, + { 0x5fffc, 0xfe8000a3 }, + { 0x50318, 0x4940003d }, + { 0x5fffc, 0xfec000ac }, + { 0x5031c, 0x48400037 }, + { 0x5fffc, 0xff0000b4 }, + { 0x50320, 0x47800031 }, + { 0x5fffc, 0xff8000bd }, + { 0x50324, 0x4640002b }, + { 0x5fffc, 0xc5 }, + { 0x50328, 0x45000026 }, + { 0x5fffc, 0x8000ce }, + { 0x5032c, 0x43800021 }, + { 0x5fffc, 0x10000d6 }, + { 0x50330, 0x4240001c }, + { 0x5fffc, 0x18000df }, + { 0x50334, 0x40800018 }, + { 0x5fffc, 0x24000e6 }, + { 0x50338, 0x3f000014 }, + { 0x5fffc, 0x30000ee }, + { 0x5033c, 0x3d400010 }, + { 0x5fffc, 0x40000f5 }, + { 0x50340, 0x3b80000c }, + { 0x5fffc, 0x50000fc }, + { 0x50344, 0x39800009 }, + { 0x5fffc, 0x6000102 }, + { 0x50348, 0x37c00006 }, + { 0x5fffc, 0x7000109 }, + { 0x5034c, 0x35800004 }, + { 0x5fffc, 0x840010e }, + { 0x50350, 0x33800002 }, + { 0x5fffc, 0x9800114 }, + { 0x50354, 0x31400000 }, + { 0x5fffc, 0xac00119 }, + { 0x50358, 0x2f4003fe }, + { 0x5fffc, 0xc40011e }, + { 0x5035c, 0x2d0003fc }, + { 0x5fffc, 0xdc00121 }, + { 0x50360, 0x2b0003fb }, + { 0x5fffc, 0xf400125 }, + { 0x50364, 0x28c003fa }, + { 0x5fffc, 0x11000128 }, + { 0x50368, 0x268003f9 }, + { 0x5fffc, 0x12c0012a }, + { 0x5036c, 0x244003f9 }, + { 0x5fffc, 0x1480012c }, + { 0x50370, 0x224003f8 }, + { 0x5fffc, 0x1640012e }, + { 0x50374, 0x200003f8 }, + { 0x5fffc, 0x1800012f }, + { 0x50378, 0x1e0003f8 }, + { 0x5fffc, 0x1a00012f }, + { 0x5037c, 0x1c0003f8 }, +}; + +static struct mdp_table_entry mdp_downscale_y_table_PT8TO1[] = { + { 0x5fffc, 0x0 }, + { 0x50300, 0x7fc00000 }, + { 0x5fffc, 0xff80000d }, + { 0x50304, 0x7ec003f9 }, + { 0x5fffc, 0xfec0001c }, + { 0x50308, 0x7d4003f3 }, + { 0x5fffc, 0xfe40002b }, + { 0x5030c, 0x7b8003ed }, + { 0x5fffc, 0xfd80003c }, + { 0x50310, 0x794003e8 }, + { 0x5fffc, 0xfcc0004d }, + { 0x50314, 0x76c003e4 }, + { 0x5fffc, 0xfc40005f }, + { 0x50318, 0x73c003e0 }, + { 0x5fffc, 0xfb800071 }, + { 0x5031c, 0x708003de }, + { 0x5fffc, 0xfac00085 }, + { 0x50320, 0x6d0003db }, + { 0x5fffc, 0xfa000098 }, + { 0x50324, 0x698003d9 }, + { 0x5fffc, 0xf98000ac }, + { 0x50328, 0x654003d8 }, + { 0x5fffc, 0xf8c000c1 }, + { 0x5032c, 0x610003d7 }, + { 0x5fffc, 0xf84000d5 }, + { 0x50330, 0x5c8003d7 }, + { 0x5fffc, 0xf7c000e9 }, + { 0x50334, 0x580003d7 }, + { 0x5fffc, 0xf74000fd }, + { 0x50338, 0x534003d8 }, + { 0x5fffc, 0xf6c00112 }, + { 0x5033c, 0x4e8003d8 }, + { 0x5fffc, 0xf6800126 }, + { 0x50340, 0x494003da }, + { 0x5fffc, 0xf600013a }, + { 0x50344, 0x448003db }, + { 0x5fffc, 0xf600014d }, + { 0x50348, 0x3f4003dd }, + { 0x5fffc, 0xf5c00160 }, + { 0x5034c, 0x3a4003df }, + { 0x5fffc, 0xf5c00172 }, + { 0x50350, 0x354003e1 }, + { 0x5fffc, 0xf5c00184 }, + { 0x50354, 0x304003e3 }, + { 0x5fffc, 0xf6000195 }, + { 0x50358, 0x2b0003e6 }, + { 0x5fffc, 0xf64001a6 }, + { 0x5035c, 0x260003e8 }, + { 0x5fffc, 0xf6c001b4 }, + { 0x50360, 0x214003eb }, + { 0x5fffc, 0xf78001c2 }, + { 0x50364, 0x1c4003ee }, + { 0x5fffc, 0xf80001cf }, + { 0x50368, 0x17c003f1 }, + { 0x5fffc, 0xf90001db }, + { 0x5036c, 0x134003f3 }, + { 0x5fffc, 0xfa0001e5 }, + { 0x50370, 0xf0003f6 }, + { 0x5fffc, 0xfb4001ee }, + { 0x50374, 0xac003f9 }, + { 0x5fffc, 0xfcc001f5 }, + { 0x50378, 0x70003fb }, + { 0x5fffc, 0xfe4001fb }, + { 0x5037c, 0x34003fe }, +}; + +struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX] = { + [MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_y_table_PT2TOPT4, + [MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_y_table_PT4TOPT6, + [MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_y_table_PT6TOPT8, + [MDP_DOWNSCALE_PT8TO1] = mdp_downscale_y_table_PT8TO1, +}; + +struct mdp_table_entry mdp_gaussian_blur_table[] = { + /* max variance */ + { 0x5fffc, 0x20000080 }, + { 0x50280, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50284, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50288, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5028c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50290, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50294, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50298, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5029c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502a0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502a4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502a8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502ac, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502b0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502b4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502b8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502bc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502c0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502c4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502c8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502cc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502d0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502d4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502d8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502dc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502e0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502e4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502e8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502ec, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502f0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502f4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502f8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502fc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50300, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50304, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50308, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5030c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50310, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50314, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50318, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5031c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50320, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50324, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50328, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5032c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50330, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50334, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50338, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5033c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50340, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50344, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50348, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5034c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50350, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50354, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50358, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5035c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50360, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50364, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50368, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5036c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50370, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50374, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50378, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5037c, 0x20000080 }, +}; diff --git a/drivers/video/msm/mdp_scale_tables.h b/drivers/video/msm/mdp_scale_tables.h new file mode 100644 index 000000000000..34077b1af603 --- /dev/null +++ b/drivers/video/msm/mdp_scale_tables.h @@ -0,0 +1,38 @@ +/* drivers/video/msm_fb/mdp_scale_tables.h + * + * Copyright (C) 2007 QUALCOMM Incorporated + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _MDP_SCALE_TABLES_H_ +#define _MDP_SCALE_TABLES_H_ + +#include <linux/types.h> +struct mdp_table_entry { + uint32_t reg; + uint32_t val; +}; + +extern struct mdp_table_entry mdp_upscale_table[64]; + +enum { + MDP_DOWNSCALE_PT2TOPT4, + MDP_DOWNSCALE_PT4TOPT6, + MDP_DOWNSCALE_PT6TOPT8, + MDP_DOWNSCALE_PT8TO1, + MDP_DOWNSCALE_MAX, +}; + +extern struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX]; +extern struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX]; +extern struct mdp_table_entry mdp_gaussian_blur_table[]; + +#endif diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c new file mode 100644 index 000000000000..49101dda45ee --- /dev/null +++ b/drivers/video/msm/msm_fb.c @@ -0,0 +1,636 @@ +/* drivers/video/msm/msm_fb.c + * + * Core MSM framebuffer driver. + * + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/fb.h> +#include <linux/delay.h> + +#include <linux/freezer.h> +#include <linux/wait.h> +#include <linux/msm_mdp.h> +#include <linux/io.h> +#include <linux/uaccess.h> +#include <mach/msm_fb.h> +#include <mach/board.h> +#include <linux/workqueue.h> +#include <linux/clk.h> +#include <linux/debugfs.h> +#include <linux/dma-mapping.h> + +#define PRINT_FPS 0 +#define PRINT_BLIT_TIME 0 + +#define SLEEPING 0x4 +#define UPDATING 0x3 +#define FULL_UPDATE_DONE 0x2 +#define WAKING 0x1 +#define AWAKE 0x0 + +#define NONE 0 +#define SUSPEND_RESUME 0x1 +#define FPS 0x2 +#define BLIT_TIME 0x4 +#define SHOW_UPDATES 0x8 + +#define DLOG(mask, fmt, args...) \ +do { \ + if (msmfb_debug_mask & mask) \ + printk(KERN_INFO "msmfb: "fmt, ##args); \ +} while (0) + +static int msmfb_debug_mask; +module_param_named(msmfb_debug_mask, msmfb_debug_mask, int, + S_IRUGO | S_IWUSR | S_IWGRP); + +struct mdp_device *mdp; + +struct msmfb_info { + struct fb_info *fb; + struct msm_panel_data *panel; + int xres; + int yres; + unsigned output_format; + unsigned yoffset; + unsigned frame_requested; + unsigned frame_done; + int sleeping; + unsigned update_frame; + struct { + int left; + int top; + int eright; /* exclusive */ + int ebottom; /* exclusive */ + } update_info; + char *black; + + spinlock_t update_lock; + struct mutex panel_init_lock; + wait_queue_head_t frame_wq; + struct workqueue_struct *resume_workqueue; + struct work_struct resume_work; + struct msmfb_callback dma_callback; + struct msmfb_callback vsync_callback; + struct hrtimer fake_vsync; + ktime_t vsync_request_time; +}; + +static int msmfb_open(struct fb_info *info, int user) +{ + return 0; +} + +static int msmfb_release(struct fb_info *info, int user) +{ + return 0; +} + +/* Called from dma interrupt handler, must not sleep */ +static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback) +{ + unsigned long irq_flags; + struct msmfb_info *msmfb = container_of(callback, struct msmfb_info, + dma_callback); + + spin_lock_irqsave(&msmfb->update_lock, irq_flags); + msmfb->frame_done = msmfb->frame_requested; + if (msmfb->sleeping == UPDATING && + msmfb->frame_done == msmfb->update_frame) { + DLOG(SUSPEND_RESUME, "full update completed\n"); + queue_work(msmfb->resume_workqueue, &msmfb->resume_work); + } + spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); + wake_up(&msmfb->frame_wq); +} + +static int msmfb_start_dma(struct msmfb_info *msmfb) +{ + uint32_t x, y, w, h; + unsigned addr; + unsigned long irq_flags; + uint32_t yoffset; + s64 time_since_request; + struct msm_panel_data *panel = msmfb->panel; + + spin_lock_irqsave(&msmfb->update_lock, irq_flags); + time_since_request = ktime_to_ns(ktime_sub(ktime_get(), + msmfb->vsync_request_time)); + if (time_since_request > 20 * NSEC_PER_MSEC) { + uint32_t us; + us = do_div(time_since_request, NSEC_PER_MSEC) / NSEC_PER_USEC; + printk(KERN_WARNING "msmfb_start_dma %lld.%03u ms after vsync " + "request\n", time_since_request, us); + } + if (msmfb->frame_done == msmfb->frame_requested) { + spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); + return -1; + } + if (msmfb->sleeping == SLEEPING) { + DLOG(SUSPEND_RESUME, "tried to start dma while asleep\n"); + spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); + return -1; + } + x = msmfb->update_info.left; + y = msmfb->update_info.top; + w = msmfb->update_info.eright - x; + h = msmfb->update_info.ebottom - y; + yoffset = msmfb->yoffset; + msmfb->update_info.left = msmfb->xres + 1; + msmfb->update_info.top = msmfb->yres + 1; + msmfb->update_info.eright = 0; + msmfb->update_info.ebottom = 0; + if (unlikely(w > msmfb->xres || h > msmfb->yres || + w == 0 || h == 0)) { + printk(KERN_INFO "invalid update: %d %d %d " + "%d\n", x, y, w, h); + msmfb->frame_done = msmfb->frame_requested; + goto error; + } + spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); + + addr = ((msmfb->xres * (yoffset + y) + x) * 2); + mdp->dma(mdp, addr + msmfb->fb->fix.smem_start, + msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback, + panel->interface_type); + return 0; +error: + spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); + /* some clients need to clear their vsync interrupt */ + if (panel->clear_vsync) + panel->clear_vsync(panel); + wake_up(&msmfb->frame_wq); + return 0; +} + +/* Called from esync interrupt handler, must not sleep */ +static void msmfb_handle_vsync_interrupt(struct msmfb_callback *callback) +{ + struct msmfb_info *msmfb = container_of(callback, struct msmfb_info, + vsync_callback); + msmfb_start_dma(msmfb); +} + +static enum hrtimer_restart msmfb_fake_vsync(struct hrtimer *timer) +{ + struct msmfb_info *msmfb = container_of(timer, struct msmfb_info, + fake_vsync); + msmfb_start_dma(msmfb); + return HRTIMER_NORESTART; +} + +static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top, + uint32_t eright, uint32_t ebottom, + uint32_t yoffset, int pan_display) +{ + struct msmfb_info *msmfb = info->par; + struct msm_panel_data *panel = msmfb->panel; + unsigned long irq_flags; + int sleeping; + int retry = 1; + + DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n", + left, top, eright, ebottom, yoffset, pan_display); +restart: + spin_lock_irqsave(&msmfb->update_lock, irq_flags); + + /* if we are sleeping, on a pan_display wait 10ms (to throttle back + * drawing otherwise return */ + if (msmfb->sleeping == SLEEPING) { + DLOG(SUSPEND_RESUME, "drawing while asleep\n"); + spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); + if (pan_display) + wait_event_interruptible_timeout(msmfb->frame_wq, + msmfb->sleeping != SLEEPING, HZ/10); + return; + } + + sleeping = msmfb->sleeping; + /* on a full update, if the last frame has not completed, wait for it */ + if (pan_display && (msmfb->frame_requested != msmfb->frame_done || + sleeping == UPDATING)) { + int ret; + spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); + ret = wait_event_interruptible_timeout(msmfb->frame_wq, + msmfb->frame_done == msmfb->frame_requested && + msmfb->sleeping != UPDATING, 5 * HZ); + if (ret <= 0 && (msmfb->frame_requested != msmfb->frame_done || + msmfb->sleeping == UPDATING)) { + if (retry && panel->request_vsync && + (sleeping == AWAKE)) { + panel->request_vsync(panel, + &msmfb->vsync_callback); + retry = 0; + printk(KERN_WARNING "msmfb_pan_display timeout " + "rerequest vsync\n"); + } else { + printk(KERN_WARNING "msmfb_pan_display timeout " + "waiting for frame start, %d %d\n", + msmfb->frame_requested, + msmfb->frame_done); + return; + } + } + goto restart; + } + + + msmfb->frame_requested++; + /* if necessary, update the y offset, if this is the + * first full update on resume, set the sleeping state */ + if (pan_display) { + msmfb->yoffset = yoffset; + if (left == 0 && top == 0 && eright == info->var.xres && + ebottom == info->var.yres) { + if (sleeping == WAKING) { + msmfb->update_frame = msmfb->frame_requested; + DLOG(SUSPEND_RESUME, "full update starting\n"); + msmfb->sleeping = UPDATING; + } + } + } + + /* set the update request */ + if (left < msmfb->update_info.left) + msmfb->update_info.left = left; + if (top < msmfb->update_info.top) + msmfb->update_info.top = top; + if (eright > msmfb->update_info.eright) + msmfb->update_info.eright = eright; + if (ebottom > msmfb->update_info.ebottom) + msmfb->update_info.ebottom = ebottom; + DLOG(SHOW_UPDATES, "update queued %d %d %d %d %d\n", + msmfb->update_info.left, msmfb->update_info.top, + msmfb->update_info.eright, msmfb->update_info.ebottom, + msmfb->yoffset); + spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); + + /* if the panel is all the way on wait for vsync, otherwise sleep + * for 16 ms (long enough for the dma to panel) and then begin dma */ + msmfb->vsync_request_time = ktime_get(); + if (panel->request_vsync && (sleeping == AWAKE)) { + panel->request_vsync(panel, &msmfb->vsync_callback); + } else { + if (!hrtimer_active(&msmfb->fake_vsync)) { + hrtimer_start(&msmfb->fake_vsync, + ktime_set(0, NSEC_PER_SEC/60), + HRTIMER_MODE_REL); + } + } +} + +static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top, + uint32_t eright, uint32_t ebottom) +{ + msmfb_pan_update(info, left, top, eright, ebottom, 0, 0); +} + +static void power_on_panel(struct work_struct *work) +{ + struct msmfb_info *msmfb = + container_of(work, struct msmfb_info, resume_work); + struct msm_panel_data *panel = msmfb->panel; + unsigned long irq_flags; + + mutex_lock(&msmfb->panel_init_lock); + DLOG(SUSPEND_RESUME, "turning on panel\n"); + if (msmfb->sleeping == UPDATING) { + if (panel->unblank(panel)) { + printk(KERN_INFO "msmfb: panel unblank failed," + "not starting drawing\n"); + goto error; + } + spin_lock_irqsave(&msmfb->update_lock, irq_flags); + msmfb->sleeping = AWAKE; + wake_up(&msmfb->frame_wq); + spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); + } +error: + mutex_unlock(&msmfb->panel_init_lock); +} + + +static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + if ((var->xres != info->var.xres) || + (var->yres != info->var.yres) || + (var->xres_virtual != info->var.xres_virtual) || + (var->yres_virtual != info->var.yres_virtual) || + (var->xoffset != info->var.xoffset) || + (var->bits_per_pixel != info->var.bits_per_pixel) || + (var->grayscale != info->var.grayscale)) + return -EINVAL; + return 0; +} + +int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct msmfb_info *msmfb = info->par; + struct msm_panel_data *panel = msmfb->panel; + + /* "UPDT" */ + if ((panel->caps & MSMFB_CAP_PARTIAL_UPDATES) && + (var->reserved[0] == 0x54445055)) { + msmfb_pan_update(info, var->reserved[1] & 0xffff, + var->reserved[1] >> 16, + var->reserved[2] & 0xffff, + var->reserved[2] >> 16, var->yoffset, 1); + } else { + msmfb_pan_update(info, 0, 0, info->var.xres, info->var.yres, + var->yoffset, 1); + } + return 0; +} + +static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) +{ + cfb_fillrect(p, rect); + msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width, + rect->dy + rect->height); +} + +static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) +{ + cfb_copyarea(p, area); + msmfb_update(p, area->dx, area->dy, area->dx + area->width, + area->dy + area->height); +} + +static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image) +{ + cfb_imageblit(p, image); + msmfb_update(p, image->dx, image->dy, image->dx + image->width, + image->dy + image->height); +} + + +static int msmfb_blit(struct fb_info *info, + void __user *p) +{ + struct mdp_blit_req req; + struct mdp_blit_req_list req_list; + int i; + int ret; + + if (copy_from_user(&req_list, p, sizeof(req_list))) + return -EFAULT; + + for (i = 0; i < req_list.count; i++) { + struct mdp_blit_req_list *list = + (struct mdp_blit_req_list *)p; + if (copy_from_user(&req, &list->req[i], sizeof(req))) + return -EFAULT; + ret = mdp->blit(mdp, info, &req); + if (ret) + return ret; + } + return 0; +} + + +DEFINE_MUTEX(mdp_ppp_lock); + +static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int ret; + + switch (cmd) { + case MSMFB_GRP_DISP: + mdp->set_grp_disp(mdp, arg); + break; + case MSMFB_BLIT: + ret = msmfb_blit(p, argp); + if (ret) + return ret; + break; + default: + printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd); + return -EINVAL; + } + return 0; +} + +static struct fb_ops msmfb_ops = { + .owner = THIS_MODULE, + .fb_open = msmfb_open, + .fb_release = msmfb_release, + .fb_check_var = msmfb_check_var, + .fb_pan_display = msmfb_pan_display, + .fb_fillrect = msmfb_fillrect, + .fb_copyarea = msmfb_copyarea, + .fb_imageblit = msmfb_imageblit, + .fb_ioctl = msmfb_ioctl, +}; + +static unsigned PP[16]; + + + +#define BITS_PER_PIXEL 16 + +static void setup_fb_info(struct msmfb_info *msmfb) +{ + struct fb_info *fb_info = msmfb->fb; + int r; + + /* finish setting up the fb_info struct */ + strncpy(fb_info->fix.id, "msmfb", 16); + fb_info->fix.ypanstep = 1; + + fb_info->fbops = &msmfb_ops; + fb_info->flags = FBINFO_DEFAULT; + + fb_info->fix.type = FB_TYPE_PACKED_PIXELS; + fb_info->fix.visual = FB_VISUAL_TRUECOLOR; + fb_info->fix.line_length = msmfb->xres * 2; + + fb_info->var.xres = msmfb->xres; + fb_info->var.yres = msmfb->yres; + fb_info->var.width = msmfb->panel->fb_data->width; + fb_info->var.height = msmfb->panel->fb_data->height; + fb_info->var.xres_virtual = msmfb->xres; + fb_info->var.yres_virtual = msmfb->yres * 2; + fb_info->var.bits_per_pixel = BITS_PER_PIXEL; + fb_info->var.accel_flags = 0; + + fb_info->var.yoffset = 0; + + if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) { + fb_info->var.reserved[0] = 0x54445055; + fb_info->var.reserved[1] = 0; + fb_info->var.reserved[2] = (uint16_t)msmfb->xres | + ((uint32_t)msmfb->yres << 16); + } + + fb_info->var.red.offset = 11; + fb_info->var.red.length = 5; + fb_info->var.red.msb_right = 0; + fb_info->var.green.offset = 5; + fb_info->var.green.length = 6; + fb_info->var.green.msb_right = 0; + fb_info->var.blue.offset = 0; + fb_info->var.blue.length = 5; + fb_info->var.blue.msb_right = 0; + + r = fb_alloc_cmap(&fb_info->cmap, 16, 0); + fb_info->pseudo_palette = PP; + + PP[0] = 0; + for (r = 1; r < 16; r++) + PP[r] = 0xffffffff; +} + +static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev) +{ + struct fb_info *fb = msmfb->fb; + struct resource *resource; + unsigned long size = msmfb->xres * msmfb->yres * + (BITS_PER_PIXEL >> 3) * 2; + unsigned char *fbram; + + /* board file might have attached a resource describing an fb */ + resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!resource) + return -EINVAL; + + /* check the resource is large enough to fit the fb */ + if (resource->end - resource->start < size) { + printk(KERN_ERR "allocated resource is too small for " + "fb\n"); + return -ENOMEM; + } + fb->fix.smem_start = resource->start; + fb->fix.smem_len = resource->end - resource->start; + fbram = ioremap(resource->start, + resource->end - resource->start); + if (fbram == 0) { + printk(KERN_ERR "msmfb: cannot allocate fbram!\n"); + return -ENOMEM; + } + fb->screen_base = fbram; + return 0; +} + +static int msmfb_probe(struct platform_device *pdev) +{ + struct fb_info *fb; + struct msmfb_info *msmfb; + struct msm_panel_data *panel = pdev->dev.platform_data; + int ret; + + if (!panel) { + pr_err("msmfb_probe: no platform data\n"); + return -EINVAL; + } + if (!panel->fb_data) { + pr_err("msmfb_probe: no fb_data\n"); + return -EINVAL; + } + + fb = framebuffer_alloc(sizeof(struct msmfb_info), &pdev->dev); + if (!fb) + return -ENOMEM; + msmfb = fb->par; + msmfb->fb = fb; + msmfb->panel = panel; + msmfb->xres = panel->fb_data->xres; + msmfb->yres = panel->fb_data->yres; + + ret = setup_fbmem(msmfb, pdev); + if (ret) + goto error_setup_fbmem; + + setup_fb_info(msmfb); + + spin_lock_init(&msmfb->update_lock); + mutex_init(&msmfb->panel_init_lock); + init_waitqueue_head(&msmfb->frame_wq); + msmfb->resume_workqueue = create_workqueue("panel_on"); + if (msmfb->resume_workqueue == NULL) { + printk(KERN_ERR "failed to create panel_on workqueue\n"); + ret = -ENOMEM; + goto error_create_workqueue; + } + INIT_WORK(&msmfb->resume_work, power_on_panel); + msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres, + GFP_KERNEL); + + printk(KERN_INFO "msmfb_probe() installing %d x %d panel\n", + msmfb->xres, msmfb->yres); + + msmfb->dma_callback.func = msmfb_handle_dma_interrupt; + msmfb->vsync_callback.func = msmfb_handle_vsync_interrupt; + hrtimer_init(&msmfb->fake_vsync, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + + + msmfb->fake_vsync.function = msmfb_fake_vsync; + + ret = register_framebuffer(fb); + if (ret) + goto error_register_framebuffer; + + msmfb->sleeping = WAKING; + + return 0; + +error_register_framebuffer: + destroy_workqueue(msmfb->resume_workqueue); +error_create_workqueue: + iounmap(fb->screen_base); +error_setup_fbmem: + framebuffer_release(msmfb->fb); + return ret; +} + +static struct platform_driver msm_panel_driver = { + /* need to write remove */ + .probe = msmfb_probe, + .driver = {.name = "msm_panel"}, +}; + + +static int msmfb_add_mdp_device(struct device *dev, + struct class_interface *class_intf) +{ + /* might need locking if mulitple mdp devices */ + if (mdp) + return 0; + mdp = container_of(dev, struct mdp_device, dev); + return platform_driver_register(&msm_panel_driver); +} + +static void msmfb_remove_mdp_device(struct device *dev, + struct class_interface *class_intf) +{ + /* might need locking if mulitple mdp devices */ + if (dev != &mdp->dev) + return; + platform_driver_unregister(&msm_panel_driver); + mdp = NULL; +} + +static struct class_interface msm_fb_interface = { + .add_dev = &msmfb_add_mdp_device, + .remove_dev = &msmfb_remove_mdp_device, +}; + +static int __init msmfb_init(void) +{ + return register_mdp_client(&msm_fb_interface); +} + +module_init(msmfb_init); diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 44408850e2eb..551e3e9c4cbe 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig @@ -7,6 +7,69 @@ config FB_OMAP help Frame buffer driver for OMAP based boards. +config FB_OMAP_LCD_VGA + bool "Use LCD in VGA mode" + depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP + +choice + depends on FB_OMAP && MACH_OVERO + prompt "Screen resolution" + default FB_OMAP_079M3R + help + Selected desired screen resolution + +config FB_OMAP_031M3R + boolean "640 x 480 @ 60 Hz Reduced blanking" + +config FB_OMAP_048M3R + boolean "800 x 600 @ 60 Hz Reduced blanking" + +config FB_OMAP_079M3R + boolean "1024 x 768 @ 60 Hz Reduced blanking" + +config FB_OMAP_092M9R + boolean "1280 x 720 @ 60 Hz Reduced blanking" + +endchoice + +config FB_OMAP_LCDC_EXTERNAL + bool "External LCD controller support" + depends on FB_OMAP + help + Say Y here, if you want to have support for boards with an + external LCD controller connected to the SoSSI/RFBI interface. + +config FB_OMAP_LCDC_HWA742 + bool "Epson HWA742 LCD controller support" + depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL + help + Say Y here if you want to have support for the external + Epson HWA742 LCD controller. + +config FB_OMAP_LCDC_BLIZZARD + bool "Epson Blizzard LCD controller support" + depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL + help + Say Y here if you want to have support for the external + Epson Blizzard LCD controller. + +config FB_OMAP_MANUAL_UPDATE + bool "Default to manual update mode" + depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL + help + Say Y here, if your user-space applications are capable of + notifying the frame buffer driver when a change has occured in + the frame buffer content and thus a reload of the image data to + the external frame buffer is required. If unsure, say N. + +config FB_OMAP_LCD_MIPID + bool "MIPI DBI-C/DCS compatible LCD support" + depends on FB_OMAP && SPI_MASTER + help + Say Y here if you want to have support for LCDs compatible with + the Mobile Industry Processor Interface DBI-C/DCS + specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3) + config FB_OMAP_BOOTLOADER_INIT bool "Check bootloader initialization" depends on FB_OMAP @@ -36,23 +99,4 @@ config FB_OMAP_DMA_TUNE answer yes. Answer no if you have a dedicated video memory, or don't use any of the accelerated features. -config FB_OMAP_LCDC_EXTERNAL - bool "External LCD controller support" - depends on FB_OMAP - help - Say Y here, if you want to have support for boards with an - external LCD controller connected to the SoSSI/RFBI interface. - -config FB_OMAP_LCDC_HWA742 - bool "Epson HWA742 LCD controller support" - depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL - help - Say Y here if you want to have support for the external - Epson HWA742 LCD controller. -config FB_OMAP_LCDC_BLIZZARD - bool "Epson Blizzard LCD controller support" - depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL - help - Say Y here if you want to have support for the external - Epson Blizzard LCD controller. diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index ed13889c1162..b63b198d1f03 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile @@ -8,6 +8,7 @@ objs-yy := omapfb_main.o objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o objs-y$(CONFIG_ARCH_OMAP2) += dispc.o +objs-y$(CONFIG_ARCH_OMAP3) += dispc.o objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o @@ -15,6 +16,7 @@ objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o +objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o @@ -24,5 +26,15 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o +objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o +objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o +objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o +objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o +objs-y$(CONFIG_MACH_OMAP2EVM) += lcd_omap2evm.o +objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o +objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o +objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o +objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o + omapfb-objs := $(objs-yy) diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c index 9dfcf39d3367..d5e59556f9e2 100644 --- a/drivers/video/omap/blizzard.c +++ b/drivers/video/omap/blizzard.c @@ -44,6 +44,7 @@ #define BLIZZARD_CLK_SRC 0x0e #define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 #define BLIZZARD_MEM_BANK0_STATUS 0x14 +#define BLIZZARD_PANEL_CONFIGURATION 0x28 #define BLIZZARD_HDISP 0x2a #define BLIZZARD_HNDP 0x2c #define BLIZZARD_VDISP0 0x2e @@ -162,6 +163,10 @@ struct blizzard_struct { int vid_scaled; int last_color_mode; int zoom_on; + int zoom_area_gx1; + int zoom_area_gx2; + int zoom_area_gy1; + int zoom_area_gy2; int screen_width; int screen_height; unsigned te_connected:1; @@ -513,6 +518,13 @@ static int do_full_screen_update(struct blizzard_request *req) return REQ_PENDING; } +static int check_1d_intersect(int a1, int a2, int b1, int b2) +{ + if (a2 <= b1 || b2 <= a1) + return 0; + return 1; +} + /* Setup all planes with an overlapping area with the update window. */ static int do_partial_update(struct blizzard_request *req, int plane, int x, int y, int w, int h, @@ -525,6 +537,7 @@ static int do_partial_update(struct blizzard_request *req, int plane, int color_mode; int flags; int zoom_off; + int have_zoom_for_this_update = 0; /* Global coordinates, relative to pixel 0,0 of the LCD */ gx1 = x + blizzard.plane[plane].pos_x; @@ -544,10 +557,6 @@ static int do_partial_update(struct blizzard_request *req, int plane, gx2_out = gx1_out + w_out; gy2_out = gy1_out + h_out; } - zoom_off = blizzard.zoom_on && gx1 == 0 && gy1 == 0 && - w == blizzard.screen_width && h == blizzard.screen_height; - blizzard.zoom_on = (!zoom_off && blizzard.zoom_on) || - (w < w_out || h < h_out); for (i = 0; i < OMAPFB_PLANE_NUM; i++) { struct plane_info *p = &blizzard.plane[i]; @@ -653,8 +662,49 @@ static int do_partial_update(struct blizzard_request *req, int plane, else disable_tearsync(); + if ((gx2_out - gx1_out) != (gx2 - gx1) || + (gy2_out - gy1_out) != (gy2 - gy1)) + have_zoom_for_this_update = 1; + + /* 'background' type of screen update (as opposed to 'destructive') + can be used to disable scaling if scaling is active */ + zoom_off = blizzard.zoom_on && !have_zoom_for_this_update && + (gx1_out == 0) && (gx2_out == blizzard.screen_width) && + (gy1_out == 0) && (gy2_out == blizzard.screen_height) && + (gx1 == 0) && (gy1 == 0); + + if (blizzard.zoom_on && !have_zoom_for_this_update && !zoom_off && + check_1d_intersect(blizzard.zoom_area_gx1, blizzard.zoom_area_gx2, + gx1_out, gx2_out) && + check_1d_intersect(blizzard.zoom_area_gy1, blizzard.zoom_area_gy2, + gy1_out, gy2_out)) { + /* Previous screen update was using scaling, current update + * is not using it. Additionally, current screen update is + * going to overlap with the scaled area. Scaling needs to be + * disabled in order to avoid 'magnifying glass' effect. + * Dummy setup of background window can be used for this. + */ + set_window_regs(0, 0, blizzard.screen_width, + blizzard.screen_height, + 0, 0, blizzard.screen_width, + blizzard.screen_height, + BLIZZARD_COLOR_RGB565, 1, flags); + blizzard.zoom_on = 0; + } + + /* remember scaling settings if we have scaled update */ + if (have_zoom_for_this_update) { + blizzard.zoom_on = 1; + blizzard.zoom_area_gx1 = gx1_out; + blizzard.zoom_area_gx2 = gx2_out; + blizzard.zoom_area_gy1 = gy1_out; + blizzard.zoom_area_gy2 = gy2_out; + } + set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out, color_mode, zoom_off, flags); + if (zoom_off) + blizzard.zoom_on = 0; blizzard.extif->set_bits_per_cycle(16); /* set_window_regs has left the register index at the right @@ -908,6 +958,35 @@ static int blizzard_set_scale(int plane, int orig_w, int orig_h, return 0; } +static int blizzard_set_rotate(int angle) +{ + u32 l; + + l = blizzard_read_reg(BLIZZARD_PANEL_CONFIGURATION); + l &= ~0x03; + + switch (angle) { + case 0: + l = l | 0x00; + break; + case 90: + l = l | 0x03; + break; + case 180: + l = l | 0x02; + break; + case 270: + l = l | 0x01; + break; + default: + return -EINVAL; + } + + blizzard_write_reg(BLIZZARD_PANEL_CONFIGURATION, l); + + return 0; +} + static int blizzard_enable_plane(int plane, int enable) { if (enable) @@ -1285,7 +1364,8 @@ static void blizzard_get_caps(int plane, struct omapfb_caps *caps) caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE | OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE | OMAPFB_CAPS_WINDOW_SCALE | - OMAPFB_CAPS_WINDOW_OVERLAY; + OMAPFB_CAPS_WINDOW_OVERLAY | + OMAPFB_CAPS_WINDOW_ROTATE; if (blizzard.te_connected) caps->ctrl |= OMAPFB_CAPS_TEARSYNC; caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) | @@ -1560,6 +1640,7 @@ struct lcd_ctrl blizzard_ctrl = { .setup_plane = blizzard_setup_plane, .set_scale = blizzard_set_scale, .enable_plane = blizzard_enable_plane, + .set_rotate = blizzard_set_rotate, .update_window = blizzard_update_window_async, .sync = blizzard_sync, .suspend = blizzard_suspend, diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index 148cbcc39602..f16e42154229 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c @@ -155,6 +155,8 @@ struct resmap { unsigned long *map; }; +#define MAX_IRQ_HANDLERS 4 + static struct { void __iomem *base; @@ -167,9 +169,11 @@ static struct { int ext_mode; - unsigned long enabled_irqs; - void (*irq_callback)(void *); - void *irq_callback_data; + struct { + u32 irq_mask; + void (*callback)(void *); + void *data; + } irq_handlers[MAX_IRQ_HANDLERS]; struct completion frame_done; int fir_hinc[OMAPFB_PLANE_NUM]; @@ -212,9 +216,9 @@ static void enable_rfbi_mode(int enable) dispc_write_reg(DISPC_CONTROL, l); /* Set bypass mode in RFBI module */ - l = __raw_readl(IO_ADDRESS(RFBI_CONTROL)); + l = __raw_readl(OMAP2_IO_ADDRESS(RFBI_CONTROL)); l |= enable ? 0 : (1 << 1); - __raw_writel(l, IO_ADDRESS(RFBI_CONTROL)); + __raw_writel(l, OMAP2_IO_ADDRESS(RFBI_CONTROL)); } static void set_lcd_data_lines(int data_lines) @@ -286,7 +290,7 @@ static void setup_plane_fifo(int plane, int ext_mode) BUG_ON(plane > 2); l = dispc_read_reg(fsz_reg[plane]); - l &= FLD_MASK(0, 9); + l &= FLD_MASK(0, 11); if (ext_mode) { low = l * 3 / 4; high = l; @@ -294,7 +298,7 @@ static void setup_plane_fifo(int plane, int ext_mode) low = l / 4; high = l * 3 / 4; } - MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9), + MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 12) | FLD_MASK(0, 12), (high << 16) | low); } @@ -809,57 +813,74 @@ static void set_lcd_timings(void) panel->pixel_clock = fck / lck_div / pck_div / 1000; } -int omap_dispc_request_irq(void (*callback)(void *data), void *data) +static void recalc_irq_mask(void) { - int r = 0; + int i; + unsigned long irq_mask = DISPC_IRQ_MASK_ERROR; - BUG_ON(callback == NULL); + for (i = 0; i < MAX_IRQ_HANDLERS; i++) { + if (!dispc.irq_handlers[i].callback) + continue; - if (dispc.irq_callback) - r = -EBUSY; - else { - dispc.irq_callback = callback; - dispc.irq_callback_data = data; + irq_mask |= dispc.irq_handlers[i].irq_mask; } - return r; -} -EXPORT_SYMBOL(omap_dispc_request_irq); - -void omap_dispc_enable_irqs(int irq_mask) -{ enable_lcd_clocks(1); - dispc.enabled_irqs = irq_mask; - irq_mask |= DISPC_IRQ_MASK_ERROR; MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); enable_lcd_clocks(0); } -EXPORT_SYMBOL(omap_dispc_enable_irqs); -void omap_dispc_disable_irqs(int irq_mask) +int omap_dispc_request_irq(unsigned long irq_mask, void (*callback)(void *data), + void *data) { - enable_lcd_clocks(1); - dispc.enabled_irqs &= ~irq_mask; - irq_mask &= ~DISPC_IRQ_MASK_ERROR; - MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); - enable_lcd_clocks(0); + int i; + + BUG_ON(callback == NULL); + + for (i = 0; i < MAX_IRQ_HANDLERS; i++) { + if (dispc.irq_handlers[i].callback) + continue; + + dispc.irq_handlers[i].irq_mask = irq_mask; + dispc.irq_handlers[i].callback = callback; + dispc.irq_handlers[i].data = data; + recalc_irq_mask(); + + return 0; + } + + return -EBUSY; } -EXPORT_SYMBOL(omap_dispc_disable_irqs); +EXPORT_SYMBOL(omap_dispc_request_irq); -void omap_dispc_free_irq(void) +void omap_dispc_free_irq(unsigned long irq_mask, void (*callback)(void *data), + void *data) { - enable_lcd_clocks(1); - omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL); - dispc.irq_callback = NULL; - dispc.irq_callback_data = NULL; - enable_lcd_clocks(0); + int i; + + for (i = 0; i < MAX_IRQ_HANDLERS; i++) { + if (dispc.irq_handlers[i].callback == callback && + dispc.irq_handlers[i].data == data) { + dispc.irq_handlers[i].irq_mask = 0; + dispc.irq_handlers[i].callback = NULL; + dispc.irq_handlers[i].data = NULL; + recalc_irq_mask(); + return; + } + } + + BUG(); } EXPORT_SYMBOL(omap_dispc_free_irq); static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) { - u32 stat = dispc_read_reg(DISPC_IRQSTATUS); + u32 stat; + int i = 0; + + enable_lcd_clocks(1); + stat = dispc_read_reg(DISPC_IRQSTATUS); if (stat & DISPC_IRQ_FRAMEMASK) complete(&dispc.frame_done); @@ -870,11 +891,17 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) } } - if ((stat & dispc.enabled_irqs) && dispc.irq_callback) - dispc.irq_callback(dispc.irq_callback_data); + for (i = 0; i < MAX_IRQ_HANDLERS; i++) { + if (unlikely(dispc.irq_handlers[i].callback && + (stat & dispc.irq_handlers[i].irq_mask))) + dispc.irq_handlers[i].callback( + dispc.irq_handlers[i].data); + } dispc_write_reg(DISPC_IRQSTATUS, stat); + enable_lcd_clocks(0); + return IRQ_HANDLED; } @@ -913,18 +940,13 @@ static void put_dss_clocks(void) static void enable_lcd_clocks(int enable) { - if (enable) + if (enable) { + clk_enable(dispc.dss_ick); clk_enable(dispc.dss1_fck); - else + } else { clk_disable(dispc.dss1_fck); -} - -static void enable_interface_clocks(int enable) -{ - if (enable) - clk_enable(dispc.dss_ick); - else clk_disable(dispc.dss_ick); + } } static void enable_digit_clocks(int enable) @@ -1013,7 +1035,7 @@ static void mmap_user_close(struct vm_area_struct *vma) atomic_dec(&dispc.map_count[plane]); } -static struct vm_operations_struct mmap_user_ops = { +static const struct vm_operations_struct mmap_user_ops = { .open = mmap_user_open, .close = mmap_user_close, }; @@ -1365,7 +1387,6 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, if ((r = get_dss_clocks()) < 0) goto fail0; - enable_interface_clocks(1); enable_lcd_clocks(1); #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT @@ -1396,10 +1417,10 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, enable_digit_clocks(0); } - /* Enable smart idle and autoidle */ - l = dispc_read_reg(DISPC_CONTROL); + /* Enable smart standby/idle, autoidle and wakeup */ + l = dispc_read_reg(DISPC_SYSCONFIG); l &= ~((3 << 12) | (3 << 3)); - l |= (2 << 12) | (2 << 3) | (1 << 0); + l |= (2 << 12) | (2 << 3) | (1 << 2) | (1 << 0); dispc_write_reg(DISPC_SYSCONFIG, l); omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG); @@ -1409,10 +1430,9 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, dispc_write_reg(DISPC_CONFIG, l); l = dispc_read_reg(DISPC_IRQSTATUS); - dispc_write_reg(l, DISPC_IRQSTATUS); + dispc_write_reg(DISPC_IRQSTATUS, l); - /* Enable those that we handle always */ - omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK); + recalc_irq_mask(); if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler, 0, MODULE_NAME, fbdev)) < 0) { @@ -1421,7 +1441,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, } /* L3 firewall setting: enable access to OCM RAM */ - __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0)); + __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0)); if ((r = alloc_palette_ram()) < 0) goto fail2; @@ -1469,7 +1489,6 @@ fail2: free_irq(INT_24XX_DSS_IRQ, fbdev); fail1: enable_lcd_clocks(0); - enable_interface_clocks(0); put_dss_clocks(); fail0: iounmap(dispc.base); @@ -1487,7 +1506,6 @@ static void omap_dispc_cleanup(void) cleanup_fbmem(); free_palette_ram(); free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); - enable_interface_clocks(0); put_dss_clocks(); iounmap(dispc.base); } diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h index ef720a78f6d5..c15ea77f0604 100644 --- a/drivers/video/omap/dispc.h +++ b/drivers/video/omap/dispc.h @@ -37,9 +37,10 @@ extern void omap_dispc_set_lcd_size(int width, int height); extern void omap_dispc_enable_lcd_out(int enable); extern void omap_dispc_enable_digit_out(int enable); -extern int omap_dispc_request_irq(void (*callback)(void *data), void *data); -extern void omap_dispc_free_irq(void); +extern int omap_dispc_request_irq(unsigned long irq_mask, + void (*callback)(void *data), void *data); +extern void omap_dispc_free_irq(unsigned long irq_mask, + void (*callback)(void *data), void *data); extern const struct lcd_ctrl omap2_int_ctrl; - #endif diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index 5d4f34887a22..ca51583ec98a 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c @@ -131,7 +131,7 @@ struct { struct omapfb_device *fbdev; struct lcd_ctrl_extif *extif; - struct lcd_ctrl *int_ctrl; + const struct lcd_ctrl *int_ctrl; struct clk *sys_ck; } hwa742; diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c new file mode 100644 index 000000000000..393712b6f369 --- /dev/null +++ b/drivers/video/omap/lcd_2430sdp.c @@ -0,0 +1,202 @@ +/* + * LCD panel support for the TI 2430SDP board + * + * Copyright (C) 2007 MontaVista + * Author: Hunyue Yau <hyau@mvista.com> + * + * Derived from drivers/video/omap/lcd-apollon.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/i2c/twl4030.h> + +#include <mach/mux.h> +#include <mach/omapfb.h> +#include <asm/mach-types.h> + +#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 +#define SDP2430_LCD_PANEL_ENABLE_GPIO 154 +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24 +#define SDP3430_LCD_PANEL_ENABLE_GPIO 28 + +static unsigned backlight_gpio; +static unsigned enable_gpio; + +#define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */ +#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER +#define ENABLE_VAUX2_DEDICATED 0x09 +#define ENABLE_VAUX2_DEV_GRP 0x20 +#define ENABLE_VAUX3_DEDICATED 0x03 +#define ENABLE_VAUX3_DEV_GRP 0x20 + +#define ENABLE_VPLL2_DEDICATED 0x05 +#define ENABLE_VPLL2_DEV_GRP 0xE0 +#define TWL4030_VPLL2_DEV_GRP 0x33 +#define TWL4030_VPLL2_DEDICATED 0x36 + +#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v) + + +static int sdp2430_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + if (machine_is_omap_3430sdp()) { + enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; + backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; + } else { + enable_gpio = SDP2430_LCD_PANEL_ENABLE_GPIO; + backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO; + } + + gpio_request(enable_gpio, "LCD enable"); /* LCD panel */ + gpio_request(backlight_gpio, "LCD bl"); /* LCD backlight */ + gpio_direction_output(enable_gpio, 0); + gpio_direction_output(backlight_gpio, 0); + + return 0; +} + +static void sdp2430_panel_cleanup(struct lcd_panel *panel) +{ + gpio_free(backlight_gpio); + gpio_free(enable_gpio); +} + +static int sdp2430_panel_enable(struct lcd_panel *panel) +{ + u8 ded_val, ded_reg; + u8 grp_val, grp_reg; + + if (machine_is_omap_3430sdp()) { + ded_reg = TWL4030_VAUX3_DEDICATED; + ded_val = ENABLE_VAUX3_DEDICATED; + grp_reg = TWL4030_VAUX3_DEV_GRP; + grp_val = ENABLE_VAUX3_DEV_GRP; + + if (omap_rev() > OMAP3430_REV_ES1_0) { + t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED, + TWL4030_VPLL2_DEDICATED); + t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP, + TWL4030_VPLL2_DEV_GRP); + } + } else { + ded_reg = TWL4030_VAUX2_DEDICATED; + ded_val = ENABLE_VAUX2_DEDICATED; + grp_reg = TWL4030_VAUX2_DEV_GRP; + grp_val = ENABLE_VAUX2_DEV_GRP; + } + + gpio_set_value(enable_gpio, 1); + gpio_set_value(backlight_gpio, 1); + + if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg)) + return -EIO; + if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg)) + return -EIO; + + return 0; +} + +static void sdp2430_panel_disable(struct lcd_panel *panel) +{ + gpio_set_value(enable_gpio, 0); + gpio_set_value(backlight_gpio, 0); + if (omap_rev() > OMAP3430_REV_ES1_0) { + t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED); + t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP); + msleep(4); + } +} + +static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +struct lcd_panel sdp2430_panel = { + .name = "sdp2430", + .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | + OMAP_LCDC_INV_HSYNC, + + .bpp = 16, + .data_lines = 16, + .x_res = 240, + .y_res = 320, + .hsw = 3, /* hsync_len (4) - 1 */ + .hfp = 3, /* right_margin (4) - 1 */ + .hbp = 39, /* left_margin (40) - 1 */ + .vsw = 1, /* vsync_len (2) - 1 */ + .vfp = 2, /* lower_margin */ + .vbp = 7, /* upper_margin (8) - 1 */ + + .pixel_clock = LCD_PIXCLOCK_MAX, + + .init = sdp2430_panel_init, + .cleanup = sdp2430_panel_cleanup, + .enable = sdp2430_panel_enable, + .disable = sdp2430_panel_disable, + .get_caps = sdp2430_panel_get_caps, +}; + +static int sdp2430_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&sdp2430_panel); + return 0; +} + +static int sdp2430_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int sdp2430_panel_suspend(struct platform_device *pdev, + pm_message_t mesg) +{ + return 0; +} + +static int sdp2430_panel_resume(struct platform_device *pdev) +{ + return 0; +} + +struct platform_driver sdp2430_panel_driver = { + .probe = sdp2430_panel_probe, + .remove = sdp2430_panel_remove, + .suspend = sdp2430_panel_suspend, + .resume = sdp2430_panel_resume, + .driver = { + .name = "sdp2430_lcd", + .owner = THIS_MODULE, + }, +}; + +static int __init sdp2430_panel_drv_init(void) +{ + return platform_driver_register(&sdp2430_panel_driver); +} + +static void __exit sdp2430_panel_drv_exit(void) +{ + platform_driver_unregister(&sdp2430_panel_driver); +} + +module_init(sdp2430_panel_drv_init); +module_exit(sdp2430_panel_drv_exit); diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c new file mode 100644 index 000000000000..1f7439955e02 --- /dev/null +++ b/drivers/video/omap/lcd_ams_delta.c @@ -0,0 +1,137 @@ +/* + * Based on drivers/video/omap/lcd_inn1510.c + * + * LCD panel support for the Amstrad E3 (Delta) videophone. + * + * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/delay.h> + +#include <mach/board-ams-delta.h> +#include <mach/hardware.h> +#include <mach/omapfb.h> + +#define AMS_DELTA_DEFAULT_CONTRAST 112 + +static int ams_delta_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + return 0; +} + +static void ams_delta_panel_cleanup(struct lcd_panel *panel) +{ +} + +static int ams_delta_panel_enable(struct lcd_panel *panel) +{ + ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP, + AMS_DELTA_LATCH2_LCD_NDISP); + ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN, + AMS_DELTA_LATCH2_LCD_VBLEN); + + omap_writeb(1, OMAP_PWL_CLK_ENABLE); + omap_writeb(AMS_DELTA_DEFAULT_CONTRAST, OMAP_PWL_ENABLE); + + return 0; +} + +static void ams_delta_panel_disable(struct lcd_panel *panel) +{ + ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN, 0); + ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP, 0); +} + +static unsigned long ams_delta_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +static struct lcd_panel ams_delta_panel = { + .name = "ams-delta", + .config = 0, + + .bpp = 12, + .data_lines = 16, + .x_res = 480, + .y_res = 320, + .pixel_clock = 4687, + .hsw = 3, + .hfp = 1, + .hbp = 1, + .vsw = 1, + .vfp = 0, + .vbp = 0, + .pcd = 0, + .acb = 37, + + .init = ams_delta_panel_init, + .cleanup = ams_delta_panel_cleanup, + .enable = ams_delta_panel_enable, + .disable = ams_delta_panel_disable, + .get_caps = ams_delta_panel_get_caps, +}; + +static int ams_delta_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&ams_delta_panel); + return 0; +} + +static int ams_delta_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int ams_delta_panel_suspend(struct platform_device *pdev, + pm_message_t mesg) +{ + return 0; +} + +static int ams_delta_panel_resume(struct platform_device *pdev) +{ + return 0; +} + +struct platform_driver ams_delta_panel_driver = { + .probe = ams_delta_panel_probe, + .remove = ams_delta_panel_remove, + .suspend = ams_delta_panel_suspend, + .resume = ams_delta_panel_resume, + .driver = { + .name = "lcd_ams_delta", + .owner = THIS_MODULE, + }, +}; + +static int ams_delta_panel_drv_init(void) +{ + return platform_driver_register(&ams_delta_panel_driver); +} + +static void ams_delta_panel_drv_cleanup(void) +{ + platform_driver_unregister(&ams_delta_panel_driver); +} + +module_init(ams_delta_panel_drv_init); +module_exit(ams_delta_panel_drv_cleanup); diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c new file mode 100644 index 000000000000..626ae3a532ff --- /dev/null +++ b/drivers/video/omap/lcd_apollon.c @@ -0,0 +1,138 @@ +/* + * LCD panel support for the Samsung OMAP2 Apollon board + * + * Copyright (C) 2005,2006 Samsung Electronics + * Author: Kyungmin Park <kyungmin.park@samsung.com> + * + * Derived from drivers/video/omap/lcd-h4.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <mach/gpio.h> +#include <mach/mux.h> +#include <mach/omapfb.h> + +/* #define USE_35INCH_LCD 1 */ + +static int apollon_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + /* configure LCD PWR_EN */ + omap_cfg_reg(M21_242X_GPIO11); + return 0; +} + +static void apollon_panel_cleanup(struct lcd_panel *panel) +{ +} + +static int apollon_panel_enable(struct lcd_panel *panel) +{ + return 0; +} + +static void apollon_panel_disable(struct lcd_panel *panel) +{ +} + +static unsigned long apollon_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +struct lcd_panel apollon_panel = { + .name = "apollon", + .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | + OMAP_LCDC_INV_HSYNC, + + .bpp = 16, + .data_lines = 18, +#ifdef USE_35INCH_LCD + .x_res = 240, + .y_res = 320, + .hsw = 2, + .hfp = 3, + .hbp = 9, + .vsw = 4, + .vfp = 3, + .vbp = 5, +#else + .x_res = 480, + .y_res = 272, + .hsw = 41, + .hfp = 2, + .hbp = 2, + .vsw = 10, + .vfp = 2, + .vbp = 2, +#endif + .pixel_clock = 6250, + + .init = apollon_panel_init, + .cleanup = apollon_panel_cleanup, + .enable = apollon_panel_enable, + .disable = apollon_panel_disable, + .get_caps = apollon_panel_get_caps, +}; + +static int apollon_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&apollon_panel); + return 0; +} + +static int apollon_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int apollon_panel_suspend(struct platform_device *pdev, + pm_message_t mesg) +{ + return 0; +} + +static int apollon_panel_resume(struct platform_device *pdev) +{ + return 0; +} + +struct platform_driver apollon_panel_driver = { + .probe = apollon_panel_probe, + .remove = apollon_panel_remove, + .suspend = apollon_panel_suspend, + .resume = apollon_panel_resume, + .driver = { + .name = "apollon_lcd", + .owner = THIS_MODULE, + }, +}; + +static int __init apollon_panel_drv_init(void) +{ + return platform_driver_register(&apollon_panel_driver); +} + +static void __exit apollon_panel_drv_exit(void) +{ + platform_driver_unregister(&apollon_panel_driver); +} + +module_init(apollon_panel_drv_init); +module_exit(apollon_panel_drv_exit); diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c index 2486237ebba5..417ae5efa8bb 100644 --- a/drivers/video/omap/lcd_h3.c +++ b/drivers/video/omap/lcd_h3.c @@ -124,12 +124,12 @@ struct platform_driver h3_panel_driver = { }, }; -static int h3_panel_drv_init(void) +static int __init h3_panel_drv_init(void) { return platform_driver_register(&h3_panel_driver); } -static void h3_panel_drv_cleanup(void) +static void __exit h3_panel_drv_cleanup(void) { platform_driver_unregister(&h3_panel_driver); } diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c index 6ff56430341b..0c398bda7601 100644 --- a/drivers/video/omap/lcd_h4.c +++ b/drivers/video/omap/lcd_h4.c @@ -102,12 +102,12 @@ static struct platform_driver h4_panel_driver = { }, }; -static int h4_panel_drv_init(void) +static int __init h4_panel_drv_init(void) { return platform_driver_register(&h4_panel_driver); } -static void h4_panel_drv_cleanup(void) +static void __exit h4_panel_drv_cleanup(void) { platform_driver_unregister(&h4_panel_driver); } diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c index 6953ed4b5820..cdbd8bb607be 100644 --- a/drivers/video/omap/lcd_inn1510.c +++ b/drivers/video/omap/lcd_inn1510.c @@ -109,12 +109,12 @@ struct platform_driver innovator1510_panel_driver = { }, }; -static int innovator1510_panel_drv_init(void) +static int __init innovator1510_panel_drv_init(void) { return platform_driver_register(&innovator1510_panel_driver); } -static void innovator1510_panel_drv_cleanup(void) +static void __exit innovator1510_panel_drv_cleanup(void) { platform_driver_unregister(&innovator1510_panel_driver); } diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c index 4c4f7ee6d733..268f7f808a4e 100644 --- a/drivers/video/omap/lcd_inn1610.c +++ b/drivers/video/omap/lcd_inn1610.c @@ -133,12 +133,12 @@ struct platform_driver innovator1610_panel_driver = { }, }; -static int innovator1610_panel_drv_init(void) +static int __init innovator1610_panel_drv_init(void) { return platform_driver_register(&innovator1610_panel_driver); } -static void innovator1610_panel_drv_cleanup(void) +static void __exit innovator1610_panel_drv_cleanup(void) { platform_driver_unregister(&innovator1610_panel_driver); } diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c new file mode 100644 index 000000000000..dbfe8974fb94 --- /dev/null +++ b/drivers/video/omap/lcd_ldp.c @@ -0,0 +1,200 @@ +/* + * LCD panel support for the TI LDP board + * + * Copyright (C) 2007 WindRiver + * Author: Stanley Miao <stanley.miao@windriver.com> + * + * Derived from drivers/video/omap/lcd-2430sdp.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/i2c/twl4030.h> + +#include <mach/gpio.h> +#include <mach/mux.h> +#include <mach/omapfb.h> +#include <asm/mach-types.h> + +#define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES) +#define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES) + +#define LCD_PANEL_RESET_GPIO 55 +#define LCD_PANEL_QVGA_GPIO 56 + +#ifdef CONFIG_FB_OMAP_LCD_VGA +#define LCD_XRES 480 +#define LCD_YRES 640 +#define LCD_PIXCLOCK_MAX 41700 +#else +#define LCD_XRES 240 +#define LCD_YRES 320 +#define LCD_PIXCLOCK_MAX 185186 +#endif + +#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER +#define ENABLE_VAUX2_DEDICATED 0x09 +#define ENABLE_VAUX2_DEV_GRP 0x20 +#define ENABLE_VAUX3_DEDICATED 0x03 +#define ENABLE_VAUX3_DEV_GRP 0x20 + +#define ENABLE_VPLL2_DEDICATED 0x05 +#define ENABLE_VPLL2_DEV_GRP 0xE0 +#define TWL4030_VPLL2_DEV_GRP 0x33 +#define TWL4030_VPLL2_DEDICATED 0x36 + +#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v) + + +static int ldp_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + gpio_request(LCD_PANEL_RESET_GPIO, "lcd reset"); + gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga"); + gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd panel"); + gpio_request(LCD_PANEL_BACKLIGHT_GPIO, "lcd backlight"); + + gpio_direction_output(LCD_PANEL_QVGA_GPIO, 0); + gpio_direction_output(LCD_PANEL_RESET_GPIO, 0); + gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); + gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0); + +#ifdef CONFIG_FB_OMAP_LCD_VGA + gpio_set_value(LCD_PANEL_QVGA_GPIO, 0); +#else + gpio_set_value(LCD_PANEL_QVGA_GPIO, 1); +#endif + gpio_set_value(LCD_PANEL_RESET_GPIO, 1); + + return 0; +} + +static void ldp_panel_cleanup(struct lcd_panel *panel) +{ + gpio_free(LCD_PANEL_BACKLIGHT_GPIO); + gpio_free(LCD_PANEL_ENABLE_GPIO); + gpio_free(LCD_PANEL_QVGA_GPIO); + gpio_free(LCD_PANEL_RESET_GPIO); +} + +static int ldp_panel_enable(struct lcd_panel *panel) +{ + if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED, + TWL4030_VPLL2_DEDICATED)) + return -EIO; + if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP, + TWL4030_VPLL2_DEV_GRP)) + return -EIO; + + gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1); + gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 1); + + if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEDICATED, + TWL4030_VAUX3_DEDICATED)) + return -EIO; + if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEV_GRP, + TWL4030_VAUX3_DEV_GRP)) + return -EIO; + + return 0; +} + +static void ldp_panel_disable(struct lcd_panel *panel) +{ + gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); + gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0); + + t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED); + t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP); + msleep(4); +} + +static unsigned long ldp_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +struct lcd_panel ldp_panel = { + .name = "ldp", + .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | + OMAP_LCDC_INV_HSYNC, + + .bpp = 16, + .data_lines = 18, + .x_res = LCD_XRES, + .y_res = LCD_YRES, + .hsw = 3, /* hsync_len (4) - 1 */ + .hfp = 3, /* right_margin (4) - 1 */ + .hbp = 39, /* left_margin (40) - 1 */ + .vsw = 1, /* vsync_len (2) - 1 */ + .vfp = 2, /* lower_margin */ + .vbp = 7, /* upper_margin (8) - 1 */ + + .pixel_clock = LCD_PIXCLOCK_MAX, + + .init = ldp_panel_init, + .cleanup = ldp_panel_cleanup, + .enable = ldp_panel_enable, + .disable = ldp_panel_disable, + .get_caps = ldp_panel_get_caps, +}; + +static int ldp_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&ldp_panel); + return 0; +} + +static int ldp_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int ldp_panel_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + return 0; +} + +static int ldp_panel_resume(struct platform_device *pdev) +{ + return 0; +} + +struct platform_driver ldp_panel_driver = { + .probe = ldp_panel_probe, + .remove = ldp_panel_remove, + .suspend = ldp_panel_suspend, + .resume = ldp_panel_resume, + .driver = { + .name = "ldp_lcd", + .owner = THIS_MODULE, + }, +}; + +static int __init ldp_panel_drv_init(void) +{ + return platform_driver_register(&ldp_panel_driver); +} + +static void __exit ldp_panel_drv_exit(void) +{ + platform_driver_unregister(&ldp_panel_driver); +} + +module_init(ldp_panel_drv_init); +module_exit(ldp_panel_drv_exit); diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c new file mode 100644 index 000000000000..918ee8934196 --- /dev/null +++ b/drivers/video/omap/lcd_mipid.c @@ -0,0 +1,625 @@ +/* + * LCD driver for MIPI DBI-C / DCS compatible LCDs + * + * Copyright (C) 2006 Nokia Corporation + * Author: Imre Deak <imre.deak@nokia.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/workqueue.h> +#include <linux/spi/spi.h> + +#include <mach/omapfb.h> +#include <mach/lcd_mipid.h> + +#define MIPID_MODULE_NAME "lcd_mipid" + +#define MIPID_CMD_READ_DISP_ID 0x04 +#define MIPID_CMD_READ_RED 0x06 +#define MIPID_CMD_READ_GREEN 0x07 +#define MIPID_CMD_READ_BLUE 0x08 +#define MIPID_CMD_READ_DISP_STATUS 0x09 +#define MIPID_CMD_RDDSDR 0x0F +#define MIPID_CMD_SLEEP_IN 0x10 +#define MIPID_CMD_SLEEP_OUT 0x11 +#define MIPID_CMD_DISP_OFF 0x28 +#define MIPID_CMD_DISP_ON 0x29 + +#define MIPID_ESD_CHECK_PERIOD msecs_to_jiffies(5000) + +#define to_mipid_device(p) container_of(p, struct mipid_device, \ + panel) +struct mipid_device { + int enabled; + int revision; + unsigned int saved_bklight_level; + unsigned long hw_guard_end; /* next value of jiffies + when we can issue the + next sleep in/out command */ + unsigned long hw_guard_wait; /* max guard time in jiffies */ + + struct omapfb_device *fbdev; + struct spi_device *spi; + struct mutex mutex; + struct lcd_panel panel; + + struct workqueue_struct *esd_wq; + struct delayed_work esd_work; + void (*esd_check)(struct mipid_device *m); +}; + +static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf, + int wlen, u8 *rbuf, int rlen) +{ + struct spi_message m; + struct spi_transfer *x, xfer[4]; + u16 w; + int r; + + BUG_ON(md->spi == NULL); + + spi_message_init(&m); + + memset(xfer, 0, sizeof(xfer)); + x = &xfer[0]; + + cmd &= 0xff; + x->tx_buf = &cmd; + x->bits_per_word = 9; + x->len = 2; + spi_message_add_tail(x, &m); + + if (wlen) { + x++; + x->tx_buf = wbuf; + x->len = wlen; + x->bits_per_word = 9; + spi_message_add_tail(x, &m); + } + + if (rlen) { + x++; + x->rx_buf = &w; + x->len = 1; + spi_message_add_tail(x, &m); + + if (rlen > 1) { + /* Arrange for the extra clock before the first + * data bit. + */ + x->bits_per_word = 9; + x->len = 2; + + x++; + x->rx_buf = &rbuf[1]; + x->len = rlen - 1; + spi_message_add_tail(x, &m); + } + } + + r = spi_sync(md->spi, &m); + if (r < 0) + dev_dbg(&md->spi->dev, "spi_sync %d\n", r); + + if (rlen) + rbuf[0] = w & 0xff; +} + +static inline void mipid_cmd(struct mipid_device *md, int cmd) +{ + mipid_transfer(md, cmd, NULL, 0, NULL, 0); +} + +static inline void mipid_write(struct mipid_device *md, + int reg, const u8 *buf, int len) +{ + mipid_transfer(md, reg, buf, len, NULL, 0); +} + +static inline void mipid_read(struct mipid_device *md, + int reg, u8 *buf, int len) +{ + mipid_transfer(md, reg, NULL, 0, buf, len); +} + +static void set_data_lines(struct mipid_device *md, int data_lines) +{ + u16 par; + + switch (data_lines) { + case 16: + par = 0x150; + break; + case 18: + par = 0x160; + break; + case 24: + par = 0x170; + break; + } + mipid_write(md, 0x3a, (u8 *)&par, 2); +} + +static void send_init_string(struct mipid_device *md) +{ + u16 initpar[] = { 0x0102, 0x0100, 0x0100 }; + + mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar)); + set_data_lines(md, md->panel.data_lines); +} + +static void hw_guard_start(struct mipid_device *md, int guard_msec) +{ + md->hw_guard_wait = msecs_to_jiffies(guard_msec); + md->hw_guard_end = jiffies + md->hw_guard_wait; +} + +static void hw_guard_wait(struct mipid_device *md) +{ + unsigned long wait = md->hw_guard_end - jiffies; + + if ((long)wait > 0 && wait <= md->hw_guard_wait) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(wait); + } +} + +static void set_sleep_mode(struct mipid_device *md, int on) +{ + int cmd, sleep_time = 50; + + if (on) + cmd = MIPID_CMD_SLEEP_IN; + else + cmd = MIPID_CMD_SLEEP_OUT; + hw_guard_wait(md); + mipid_cmd(md, cmd); + hw_guard_start(md, 120); + /* + * When we enable the panel, it seems we _have_ to sleep + * 120 ms before sending the init string. When disabling the + * panel we'll sleep for the duration of 2 frames, so that the + * controller can still provide the PCLK,HS,VS signals. + */ + if (!on) + sleep_time = 120; + msleep(sleep_time); +} + +static void set_display_state(struct mipid_device *md, int enabled) +{ + int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF; + + mipid_cmd(md, cmd); +} + +static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level) +{ + struct mipid_device *md = to_mipid_device(panel); + struct mipid_platform_data *pd = md->spi->dev.platform_data; + + if (pd->get_bklight_max == NULL || pd->set_bklight_level == NULL) + return -ENODEV; + if (level > pd->get_bklight_max(pd)) + return -EINVAL; + if (!md->enabled) { + md->saved_bklight_level = level; + return 0; + } + pd->set_bklight_level(pd, level); + + return 0; +} + +static unsigned int mipid_get_bklight_level(struct lcd_panel *panel) +{ + struct mipid_device *md = to_mipid_device(panel); + struct mipid_platform_data *pd = md->spi->dev.platform_data; + + if (pd->get_bklight_level == NULL) + return -ENODEV; + return pd->get_bklight_level(pd); +} + +static unsigned int mipid_get_bklight_max(struct lcd_panel *panel) +{ + struct mipid_device *md = to_mipid_device(panel); + struct mipid_platform_data *pd = md->spi->dev.platform_data; + + if (pd->get_bklight_max == NULL) + return -ENODEV; + + return pd->get_bklight_max(pd); +} + +static unsigned long mipid_get_caps(struct lcd_panel *panel) +{ + return OMAPFB_CAPS_SET_BACKLIGHT; +} + +static u16 read_first_pixel(struct mipid_device *md) +{ + u16 pixel; + u8 red, green, blue; + + mutex_lock(&md->mutex); + mipid_read(md, MIPID_CMD_READ_RED, &red, 1); + mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1); + mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1); + mutex_unlock(&md->mutex); + + switch (md->panel.data_lines) { + case 16: + pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1); + break; + case 24: + /* 24 bit -> 16 bit */ + pixel = ((red >> 3) << 11) | ((green >> 2) << 5) | + (blue >> 3); + break; + default: + pixel = 0; + BUG(); + } + + return pixel; +} + +static int mipid_run_test(struct lcd_panel *panel, int test_num) +{ + struct mipid_device *md = to_mipid_device(panel); + static const u16 test_values[4] = { + 0x0000, 0xffff, 0xaaaa, 0x5555, + }; + int i; + + if (test_num != MIPID_TEST_RGB_LINES) + return MIPID_TEST_INVALID; + + for (i = 0; i < ARRAY_SIZE(test_values); i++) { + int delay; + unsigned long tmo; + + omapfb_write_first_pixel(md->fbdev, test_values[i]); + tmo = jiffies + msecs_to_jiffies(100); + delay = 25; + while (1) { + u16 pixel; + + msleep(delay); + pixel = read_first_pixel(md); + if (pixel == test_values[i]) + break; + if (time_after(jiffies, tmo)) { + dev_err(&md->spi->dev, + "MIPI LCD RGB I/F test failed: " + "expecting %04x, got %04x\n", + test_values[i], pixel); + return MIPID_TEST_FAILED; + } + delay = 10; + } + } + + return 0; +} + +static void ls041y3_esd_recover(struct mipid_device *md) +{ + dev_err(&md->spi->dev, "performing LCD ESD recovery\n"); + set_sleep_mode(md, 1); + set_sleep_mode(md, 0); +} + +static void ls041y3_esd_check_mode1(struct mipid_device *md) +{ + u8 state1, state2; + + mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1); + set_sleep_mode(md, 0); + mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1); + dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n", + state1, state2); + /* Each sleep out command will trigger a self diagnostic and flip + * Bit6 if the test passes. + */ + if (!((state1 ^ state2) & (1 << 6))) + ls041y3_esd_recover(md); +} + +static void ls041y3_esd_check_mode2(struct mipid_device *md) +{ + int i; + u8 rbuf[2]; + static const struct { + int cmd; + int wlen; + u16 wbuf[3]; + } *rd, rd_ctrl[7] = { + { 0xb0, 4, { 0x0101, 0x01fe, } }, + { 0xb1, 4, { 0x01de, 0x0121, } }, + { 0xc2, 4, { 0x0100, 0x0100, } }, + { 0xbd, 2, { 0x0100, } }, + { 0xc2, 4, { 0x01fc, 0x0103, } }, + { 0xb4, 0, }, + { 0x00, 0, }, + }; + + rd = rd_ctrl; + for (i = 0; i < 3; i++, rd++) + mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen); + + udelay(10); + mipid_read(md, rd->cmd, rbuf, 2); + rd++; + + for (i = 0; i < 3; i++, rd++) { + udelay(10); + mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen); + } + + dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]); + if (rbuf[1] == 0x00) + ls041y3_esd_recover(md); +} + +static void ls041y3_esd_check(struct mipid_device *md) +{ + ls041y3_esd_check_mode1(md); + if (md->revision >= 0x88) + ls041y3_esd_check_mode2(md); +} + +static void mipid_esd_start_check(struct mipid_device *md) +{ + if (md->esd_check != NULL) + queue_delayed_work(md->esd_wq, &md->esd_work, + MIPID_ESD_CHECK_PERIOD); +} + +static void mipid_esd_stop_check(struct mipid_device *md) +{ + if (md->esd_check != NULL) + cancel_rearming_delayed_workqueue(md->esd_wq, &md->esd_work); +} + +static void mipid_esd_work(struct work_struct *work) +{ + struct mipid_device *md = container_of(work, struct mipid_device, + esd_work.work); + + mutex_lock(&md->mutex); + md->esd_check(md); + mutex_unlock(&md->mutex); + mipid_esd_start_check(md); +} + +static int mipid_enable(struct lcd_panel *panel) +{ + struct mipid_device *md = to_mipid_device(panel); + + mutex_lock(&md->mutex); + + if (md->enabled) { + mutex_unlock(&md->mutex); + return 0; + } + set_sleep_mode(md, 0); + md->enabled = 1; + send_init_string(md); + set_display_state(md, 1); + mipid_set_bklight_level(panel, md->saved_bklight_level); + mipid_esd_start_check(md); + + mutex_unlock(&md->mutex); + return 0; +} + +static void mipid_disable(struct lcd_panel *panel) +{ + struct mipid_device *md = to_mipid_device(panel); + + /* + * A final ESD work might be called before returning, + * so do this without holding the lock. + */ + mipid_esd_stop_check(md); + mutex_lock(&md->mutex); + + if (!md->enabled) { + mutex_unlock(&md->mutex); + return; + } + md->saved_bklight_level = mipid_get_bklight_level(panel); + mipid_set_bklight_level(panel, 0); + set_display_state(md, 0); + set_sleep_mode(md, 1); + md->enabled = 0; + + mutex_unlock(&md->mutex); +} + +static int panel_enabled(struct mipid_device *md) +{ + u32 disp_status; + int enabled; + + mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4); + disp_status = __be32_to_cpu(disp_status); + enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10)); + dev_dbg(&md->spi->dev, + "LCD panel %senabled by bootloader (status 0x%04x)\n", + enabled ? "" : "not ", disp_status); + return enabled; +} + +static int mipid_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + struct mipid_device *md = to_mipid_device(panel); + + md->fbdev = fbdev; + md->esd_wq = create_singlethread_workqueue("mipid_esd"); + if (md->esd_wq == NULL) { + dev_err(&md->spi->dev, "can't create ESD workqueue\n"); + return -ENOMEM; + } + INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work); + mutex_init(&md->mutex); + + md->enabled = panel_enabled(md); + + if (md->enabled) + mipid_esd_start_check(md); + else + md->saved_bklight_level = mipid_get_bklight_level(panel); + + return 0; +} + +static void mipid_cleanup(struct lcd_panel *panel) +{ + struct mipid_device *md = to_mipid_device(panel); + + if (md->enabled) + mipid_esd_stop_check(md); + destroy_workqueue(md->esd_wq); +} + +static struct lcd_panel mipid_panel = { + .config = OMAP_LCDC_PANEL_TFT, + + .bpp = 16, + .x_res = 800, + .y_res = 480, + .pixel_clock = 21940, + .hsw = 50, + .hfp = 20, + .hbp = 15, + .vsw = 2, + .vfp = 1, + .vbp = 3, + + .init = mipid_init, + .cleanup = mipid_cleanup, + .enable = mipid_enable, + .disable = mipid_disable, + .get_caps = mipid_get_caps, + .set_bklight_level = mipid_set_bklight_level, + .get_bklight_level = mipid_get_bklight_level, + .get_bklight_max = mipid_get_bklight_max, + .run_test = mipid_run_test, +}; + +static int mipid_detect(struct mipid_device *md) +{ + struct mipid_platform_data *pdata; + u8 display_id[3]; + + pdata = md->spi->dev.platform_data; + if (pdata == NULL) { + dev_err(&md->spi->dev, "missing platform data\n"); + return -ENOENT; + } + + mipid_read(md, MIPID_CMD_READ_DISP_ID, display_id, 3); + dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n", + display_id[0], display_id[1], display_id[2]); + + switch (display_id[0]) { + case 0x45: + md->panel.name = "lph8923"; + break; + case 0x83: + md->panel.name = "ls041y3"; + md->esd_check = ls041y3_esd_check; + break; + default: + md->panel.name = "unknown"; + dev_err(&md->spi->dev, "invalid display ID\n"); + return -ENODEV; + } + + md->revision = display_id[1]; + md->panel.data_lines = pdata->data_lines; + pr_info("omapfb: %s rev %02x LCD detected, %d data lines\n", + md->panel.name, md->revision, md->panel.data_lines); + + return 0; +} + +static int mipid_spi_probe(struct spi_device *spi) +{ + struct mipid_device *md; + int r; + + md = kzalloc(sizeof(*md), GFP_KERNEL); + if (md == NULL) { + dev_err(&spi->dev, "out of memory\n"); + return -ENOMEM; + } + + spi->mode = SPI_MODE_0; + md->spi = spi; + dev_set_drvdata(&spi->dev, md); + md->panel = mipid_panel; + + r = mipid_detect(md); + if (r < 0) + return r; + + omapfb_register_panel(&md->panel); + + return 0; +} + +static int mipid_spi_remove(struct spi_device *spi) +{ + struct mipid_device *md = dev_get_drvdata(&spi->dev); + + mipid_disable(&md->panel); + kfree(md); + + return 0; +} + +static struct spi_driver mipid_spi_driver = { + .driver = { + .name = MIPID_MODULE_NAME, + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = mipid_spi_probe, + .remove = __devexit_p(mipid_spi_remove), +}; + +static int mipid_drv_init(void) +{ + spi_register_driver(&mipid_spi_driver); + + return 0; +} +module_init(mipid_drv_init); + +static void mipid_drv_cleanup(void) +{ + spi_unregister_driver(&mipid_spi_driver); +} +module_exit(mipid_drv_cleanup); + +MODULE_DESCRIPTION("MIPI display driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap/lcd_omap2evm.c b/drivers/video/omap/lcd_omap2evm.c new file mode 100644 index 000000000000..7a2bbe2ecec3 --- /dev/null +++ b/drivers/video/omap/lcd_omap2evm.c @@ -0,0 +1,191 @@ +/* + * LCD panel support for the MISTRAL OMAP2EVM board + * + * Author: Arun C <arunedarath@mistralsolutions.com> + * + * Derived from drivers/video/omap/lcd_omap3evm.c + * Derived from drivers/video/omap/lcd-apollon.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/i2c/twl4030.h> + +#include <mach/mux.h> +#include <mach/omapfb.h> +#include <asm/mach-types.h> + +#define LCD_PANEL_ENABLE_GPIO 154 +#define LCD_PANEL_LR 128 +#define LCD_PANEL_UD 129 +#define LCD_PANEL_INI 152 +#define LCD_PANEL_QVGA 148 +#define LCD_PANEL_RESB 153 + +#define TWL_LED_LEDEN 0x00 +#define TWL_PWMA_PWMAON 0x00 +#define TWL_PWMA_PWMAOFF 0x01 + +static unsigned int bklight_level; + +static int omap2evm_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable"); + gpio_request(LCD_PANEL_LR, "LCD lr"); + gpio_request(LCD_PANEL_UD, "LCD ud"); + gpio_request(LCD_PANEL_INI, "LCD ini"); + gpio_request(LCD_PANEL_QVGA, "LCD qvga"); + gpio_request(LCD_PANEL_RESB, "LCD resb"); + + gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1); + gpio_direction_output(LCD_PANEL_RESB, 1); + gpio_direction_output(LCD_PANEL_INI, 1); + gpio_direction_output(LCD_PANEL_QVGA, 0); + gpio_direction_output(LCD_PANEL_LR, 1); + gpio_direction_output(LCD_PANEL_UD, 1); + + twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN); + twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON); + twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF); + bklight_level = 100; + + return 0; +} + +static void omap2evm_panel_cleanup(struct lcd_panel *panel) +{ + gpio_free(LCD_PANEL_RESB); + gpio_free(LCD_PANEL_QVGA); + gpio_free(LCD_PANEL_INI); + gpio_free(LCD_PANEL_UD); + gpio_free(LCD_PANEL_LR); + gpio_free(LCD_PANEL_ENABLE_GPIO); +} + +static int omap2evm_panel_enable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); + return 0; +} + +static void omap2evm_panel_disable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); +} + +static unsigned long omap2evm_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +static int omap2evm_bklight_setlevel(struct lcd_panel *panel, + unsigned int level) +{ + u8 c; + if ((level >= 0) && (level <= 100)) { + c = (125 * (100 - level)) / 100 + 2; + twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF); + bklight_level = level; + } + return 0; +} + +static unsigned int omap2evm_bklight_getlevel(struct lcd_panel *panel) +{ + return bklight_level; +} + +static unsigned int omap2evm_bklight_getmaxlevel(struct lcd_panel *panel) +{ + return 100; +} + +struct lcd_panel omap2evm_panel = { + .name = "omap2evm", + .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | + OMAP_LCDC_INV_HSYNC, + + .bpp = 16, + .data_lines = 18, + .x_res = 480, + .y_res = 640, + .hsw = 3, + .hfp = 0, + .hbp = 28, + .vsw = 2, + .vfp = 1, + .vbp = 0, + + .pixel_clock = 20000, + + .init = omap2evm_panel_init, + .cleanup = omap2evm_panel_cleanup, + .enable = omap2evm_panel_enable, + .disable = omap2evm_panel_disable, + .get_caps = omap2evm_panel_get_caps, + .set_bklight_level = omap2evm_bklight_setlevel, + .get_bklight_level = omap2evm_bklight_getlevel, + .get_bklight_max = omap2evm_bklight_getmaxlevel, +}; + +static int omap2evm_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&omap2evm_panel); + return 0; +} + +static int omap2evm_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int omap2evm_panel_suspend(struct platform_device *pdev, + pm_message_t mesg) +{ + return 0; +} + +static int omap2evm_panel_resume(struct platform_device *pdev) +{ + return 0; +} + +struct platform_driver omap2evm_panel_driver = { + .probe = omap2evm_panel_probe, + .remove = omap2evm_panel_remove, + .suspend = omap2evm_panel_suspend, + .resume = omap2evm_panel_resume, + .driver = { + .name = "omap2evm_lcd", + .owner = THIS_MODULE, + }, +}; + +static int __init omap2evm_panel_drv_init(void) +{ + return platform_driver_register(&omap2evm_panel_driver); +} + +static void __exit omap2evm_panel_drv_exit(void) +{ + platform_driver_unregister(&omap2evm_panel_driver); +} + +module_init(omap2evm_panel_drv_init); +module_exit(omap2evm_panel_drv_exit); diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c new file mode 100644 index 000000000000..4011910123bf --- /dev/null +++ b/drivers/video/omap/lcd_omap3beagle.c @@ -0,0 +1,130 @@ +/* + * LCD panel support for the TI OMAP3 Beagle board + * + * Author: Koen Kooi <koen@openembedded.org> + * + * Derived from drivers/video/omap/lcd-omap3evm.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/i2c/twl4030.h> + +#include <mach/mux.h> +#include <mach/omapfb.h> +#include <asm/mach-types.h> + +#define LCD_PANEL_ENABLE_GPIO 170 + +static int omap3beagle_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable"); + return 0; +} + +static void omap3beagle_panel_cleanup(struct lcd_panel *panel) +{ + gpio_free(LCD_PANEL_ENABLE_GPIO); +} + +static int omap3beagle_panel_enable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); + return 0; +} + +static void omap3beagle_panel_disable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); +} + +static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +struct lcd_panel omap3beagle_panel = { + .name = "omap3beagle", + .config = OMAP_LCDC_PANEL_TFT, + + .bpp = 16, + .data_lines = 24, + .x_res = 1024, + .y_res = 768, + .hsw = 3, /* hsync_len (4) - 1 */ + .hfp = 3, /* right_margin (4) - 1 */ + .hbp = 39, /* left_margin (40) - 1 */ + .vsw = 1, /* vsync_len (2) - 1 */ + .vfp = 2, /* lower_margin */ + .vbp = 7, /* upper_margin (8) - 1 */ + + .pixel_clock = 64000, + + .init = omap3beagle_panel_init, + .cleanup = omap3beagle_panel_cleanup, + .enable = omap3beagle_panel_enable, + .disable = omap3beagle_panel_disable, + .get_caps = omap3beagle_panel_get_caps, +}; + +static int omap3beagle_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&omap3beagle_panel); + return 0; +} + +static int omap3beagle_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int omap3beagle_panel_suspend(struct platform_device *pdev, + pm_message_t mesg) +{ + return 0; +} + +static int omap3beagle_panel_resume(struct platform_device *pdev) +{ + return 0; +} + +struct platform_driver omap3beagle_panel_driver = { + .probe = omap3beagle_panel_probe, + .remove = omap3beagle_panel_remove, + .suspend = omap3beagle_panel_suspend, + .resume = omap3beagle_panel_resume, + .driver = { + .name = "omap3beagle_lcd", + .owner = THIS_MODULE, + }, +}; + +static int __init omap3beagle_panel_drv_init(void) +{ + return platform_driver_register(&omap3beagle_panel_driver); +} + +static void __exit omap3beagle_panel_drv_exit(void) +{ + platform_driver_unregister(&omap3beagle_panel_driver); +} + +module_init(omap3beagle_panel_drv_init); +module_exit(omap3beagle_panel_drv_exit); diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c new file mode 100644 index 000000000000..b6a4c2c57a2f --- /dev/null +++ b/drivers/video/omap/lcd_omap3evm.c @@ -0,0 +1,192 @@ +/* + * LCD panel support for the TI OMAP3 EVM board + * + * Author: Steve Sakoman <steve@sakoman.com> + * + * Derived from drivers/video/omap/lcd-apollon.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/i2c/twl4030.h> + +#include <mach/mux.h> +#include <mach/omapfb.h> +#include <asm/mach-types.h> + +#define LCD_PANEL_ENABLE_GPIO 153 +#define LCD_PANEL_LR 2 +#define LCD_PANEL_UD 3 +#define LCD_PANEL_INI 152 +#define LCD_PANEL_QVGA 154 +#define LCD_PANEL_RESB 155 + +#define ENABLE_VDAC_DEDICATED 0x03 +#define ENABLE_VDAC_DEV_GRP 0x20 +#define ENABLE_VPLL2_DEDICATED 0x05 +#define ENABLE_VPLL2_DEV_GRP 0xE0 + +#define TWL_LED_LEDEN 0x00 +#define TWL_PWMA_PWMAON 0x00 +#define TWL_PWMA_PWMAOFF 0x01 + +static unsigned int bklight_level; + +static int omap3evm_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + gpio_request(LCD_PANEL_LR, "LCD lr"); + gpio_request(LCD_PANEL_UD, "LCD ud"); + gpio_request(LCD_PANEL_INI, "LCD ini"); + gpio_request(LCD_PANEL_RESB, "LCD resb"); + gpio_request(LCD_PANEL_QVGA, "LCD qvga"); + + gpio_direction_output(LCD_PANEL_RESB, 1); + gpio_direction_output(LCD_PANEL_INI, 1); + gpio_direction_output(LCD_PANEL_QVGA, 0); + gpio_direction_output(LCD_PANEL_LR, 1); + gpio_direction_output(LCD_PANEL_UD, 1); + + twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN); + twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON); + twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF); + bklight_level = 100; + + return 0; +} + +static void omap3evm_panel_cleanup(struct lcd_panel *panel) +{ + gpio_free(LCD_PANEL_QVGA); + gpio_free(LCD_PANEL_RESB); + gpio_free(LCD_PANEL_INI); + gpio_free(LCD_PANEL_UD); + gpio_free(LCD_PANEL_LR); +} + +static int omap3evm_panel_enable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); + return 0; +} + +static void omap3evm_panel_disable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); +} + +static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +static int omap3evm_bklight_setlevel(struct lcd_panel *panel, + unsigned int level) +{ + u8 c; + if ((level >= 0) && (level <= 100)) { + c = (125 * (100 - level)) / 100 + 2; + twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF); + bklight_level = level; + } + return 0; +} + +static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel) +{ + return bklight_level; +} + +static unsigned int omap3evm_bklight_getmaxlevel(struct lcd_panel *panel) +{ + return 100; +} + +struct lcd_panel omap3evm_panel = { + .name = "omap3evm", + .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | + OMAP_LCDC_INV_HSYNC, + + .bpp = 16, + .data_lines = 18, + .x_res = 480, + .y_res = 640, + .hsw = 3, /* hsync_len (4) - 1 */ + .hfp = 3, /* right_margin (4) - 1 */ + .hbp = 39, /* left_margin (40) - 1 */ + .vsw = 1, /* vsync_len (2) - 1 */ + .vfp = 2, /* lower_margin */ + .vbp = 7, /* upper_margin (8) - 1 */ + + .pixel_clock = 26000, + + .init = omap3evm_panel_init, + .cleanup = omap3evm_panel_cleanup, + .enable = omap3evm_panel_enable, + .disable = omap3evm_panel_disable, + .get_caps = omap3evm_panel_get_caps, + .set_bklight_level = omap3evm_bklight_setlevel, + .get_bklight_level = omap3evm_bklight_getlevel, + .get_bklight_max = omap3evm_bklight_getmaxlevel, +}; + +static int omap3evm_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&omap3evm_panel); + return 0; +} + +static int omap3evm_panel_remove(struct platform_device *pdev) +{ + return 0; +} + +static int omap3evm_panel_suspend(struct platform_device *pdev, + pm_message_t mesg) +{ + return 0; +} + +static int omap3evm_panel_resume(struct platform_device *pdev) +{ + return 0; +} + +struct platform_driver omap3evm_panel_driver = { + .probe = omap3evm_panel_probe, + .remove = omap3evm_panel_remove, + .suspend = omap3evm_panel_suspend, + .resume = omap3evm_panel_resume, + .driver = { + .name = "omap3evm_lcd", + .owner = THIS_MODULE, + }, +}; + +static int __init omap3evm_panel_drv_init(void) +{ + return platform_driver_register(&omap3evm_panel_driver); +} + +static void __exit omap3evm_panel_drv_exit(void) +{ + platform_driver_unregister(&omap3evm_panel_driver); +} + +module_init(omap3evm_panel_drv_init); +module_exit(omap3evm_panel_drv_exit); diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c index 379c96d36da5..b3fa88bc6269 100644 --- a/drivers/video/omap/lcd_osk.c +++ b/drivers/video/omap/lcd_osk.c @@ -127,12 +127,12 @@ struct platform_driver osk_panel_driver = { }, }; -static int osk_panel_drv_init(void) +static int __init osk_panel_drv_init(void) { return platform_driver_register(&osk_panel_driver); } -static void osk_panel_drv_cleanup(void) +static void __exit osk_panel_drv_cleanup(void) { platform_driver_unregister(&osk_panel_driver); } diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c new file mode 100644 index 000000000000..2bc5c9268e5e --- /dev/null +++ b/drivers/video/omap/lcd_overo.c @@ -0,0 +1,179 @@ +/* + * LCD panel support for the Gumstix Overo + * + * Author: Steve Sakoman <steve@sakoman.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/i2c/twl4030.h> + +#include <mach/gpio.h> +#include <mach/mux.h> +#include <mach/omapfb.h> +#include <asm/mach-types.h> + +#define LCD_ENABLE 144 + +static int overo_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +{ + if ((gpio_request(LCD_ENABLE, "LCD_ENABLE") == 0) && + (gpio_direction_output(LCD_ENABLE, 1) == 0)) + gpio_export(LCD_ENABLE, 0); + else + printk(KERN_ERR "could not obtain gpio for LCD_ENABLE\n"); + + return 0; +} + +static void overo_panel_cleanup(struct lcd_panel *panel) +{ + gpio_free(LCD_ENABLE); +} + +static int overo_panel_enable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_ENABLE, 1); + return 0; +} + +static void overo_panel_disable(struct lcd_panel *panel) +{ + gpio_set_value(LCD_ENABLE, 0); +} + +static unsigned long overo_panel_get_caps(struct lcd_panel *panel) +{ + return 0; +} + +struct lcd_panel overo_panel = { + .name = "overo", + .config = OMAP_LCDC_PANEL_TFT, + .bpp = 16, + .data_lines = 24, + +#if defined CONFIG_FB_OMAP_031M3R + + /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ + .x_res = 640, + .y_res = 480, + .hfp = 48, + .hsw = 32, + .hbp = 80, + .vfp = 3, + .vsw = 4, + .vbp = 7, + .pixel_clock = 23500, + +#elif defined CONFIG_FB_OMAP_048M3R + + /* 800 x 600 @ 60 Hz Reduced blanking VESA CVT 0.48M3-R */ + .x_res = 800, + .y_res = 600, + .hfp = 48, + .hsw = 32, + .hbp = 80, + .vfp = 3, + .vsw = 4, + .vbp = 11, + .pixel_clock = 35500, + +#elif defined CONFIG_FB_OMAP_079M3R + + /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */ + .x_res = 1024, + .y_res = 768, + .hfp = 48, + .hsw = 32, + .hbp = 80, + .vfp = 3, + .vsw = 4, + .vbp = 15, + .pixel_clock = 56000, + +#elif defined CONFIG_FB_OMAP_092M9R + + /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */ + .x_res = 1280, + .y_res = 720, + .hfp = 48, + .hsw = 32, + .hbp = 80, + .vfp = 3, + .vsw = 5, + .vbp = 13, + .pixel_clock = 64000, + +#else + + /* use 640 x 480 if no config option */ + /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ + .x_res = 640, + .y_res = 480, + .hfp = 48, + .hsw = 32, + .hbp = 80, + .vfp = 3, + .vsw = 4, + .vbp = 7, + .pixel_clock = 23500, + +#endif + + .init = overo_panel_init, + .cleanup = overo_panel_cleanup, + .enable = overo_panel_enable, + .disable = overo_panel_disable, + .get_caps = overo_panel_get_caps, +}; + +static int overo_panel_probe(struct platform_device *pdev) +{ + omapfb_register_panel(&overo_panel); + return 0; +} + +static int overo_panel_remove(struct platform_device *pdev) +{ + /* omapfb does not have unregister_panel */ + return 0; +} + +static struct platform_driver overo_panel_driver = { + .probe = overo_panel_probe, + .remove = overo_panel_remove, + .driver = { + .name = "overo_lcd", + .owner = THIS_MODULE, + }, +}; + +static int __init overo_panel_drv_init(void) +{ + return platform_driver_register(&overo_panel_driver); +} + +static void __exit overo_panel_drv_exit(void) +{ + platform_driver_unregister(&overo_panel_driver); +} + +module_init(overo_panel_drv_init); +module_exit(overo_panel_drv_exit); diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c index 218317366e6e..4bf3c79f3cc7 100644 --- a/drivers/video/omap/lcd_palmte.c +++ b/drivers/video/omap/lcd_palmte.c @@ -108,12 +108,12 @@ struct platform_driver palmte_panel_driver = { }, }; -static int palmte_panel_drv_init(void) +static int __init palmte_panel_drv_init(void) { return platform_driver_register(&palmte_panel_driver); } -static void palmte_panel_drv_cleanup(void) +static void __exit palmte_panel_drv_cleanup(void) { platform_driver_unregister(&palmte_panel_driver); } diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c index 57b0f6cf6a5a..48ea1f9f2cbf 100644 --- a/drivers/video/omap/lcd_palmtt.c +++ b/drivers/video/omap/lcd_palmtt.c @@ -113,12 +113,12 @@ struct platform_driver palmtt_panel_driver = { }, }; -static int palmtt_panel_drv_init(void) +static int __init palmtt_panel_drv_init(void) { return platform_driver_register(&palmtt_panel_driver); } -static void palmtt_panel_drv_cleanup(void) +static void __exit palmtt_panel_drv_cleanup(void) { platform_driver_unregister(&palmtt_panel_driver); } diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c index d33d78b11723..0697d29b4d3b 100644 --- a/drivers/video/omap/lcd_palmz71.c +++ b/drivers/video/omap/lcd_palmz71.c @@ -109,12 +109,12 @@ struct platform_driver palmz71_panel_driver = { }, }; -static int palmz71_panel_drv_init(void) +static int __init palmz71_panel_drv_init(void) { return platform_driver_register(&palmz71_panel_driver); } -static void palmz71_panel_drv_cleanup(void) +static void __exit palmz71_panel_drv_cleanup(void) { platform_driver_unregister(&palmz71_panel_driver); } diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 8862233d57b6..125e605b8c68 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -67,6 +67,7 @@ static struct caps_table_struct ctrl_caps[] = { { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" }, { OMAPFB_CAPS_WINDOW_SCALE, "scale window" }, { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" }, + { OMAPFB_CAPS_WINDOW_ROTATE, "rotate window" }, { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" }, }; @@ -215,6 +216,15 @@ static int ctrl_change_mode(struct fb_info *fbi) offset, var->xres_virtual, plane->info.pos_x, plane->info.pos_y, var->xres, var->yres, plane->color_mode); + if (r < 0) + return r; + + if (fbdev->ctrl->set_rotate != NULL) { + r = fbdev->ctrl->set_rotate(var->rotate); + if (r < 0) + return r; + } + if (fbdev->ctrl->set_scale != NULL) r = fbdev->ctrl->set_scale(plane->idx, var->xres, var->yres, @@ -554,7 +564,6 @@ static int set_fb_var(struct fb_info *fbi, var->xoffset = var->xres_virtual - var->xres; if (var->yres + var->yoffset > var->yres_virtual) var->yoffset = var->yres_virtual - var->yres; - line_size = var->xres * bpp / 8; if (plane->color_mode == OMAPFB_COLOR_RGB444) { var->red.offset = 8; var->red.length = 4; @@ -600,7 +609,7 @@ static void omapfb_rotate(struct fb_info *fbi, int rotate) struct omapfb_device *fbdev = plane->fbdev; omapfb_rqueue_lock(fbdev); - if (cpu_is_omap15xx() && rotate != fbi->var.rotate) { + if (rotate != fbi->var.rotate) { struct fb_var_screeninfo *new_var = &fbdev->new_var; memcpy(new_var, &fbi->var, sizeof(*new_var)); @@ -707,28 +716,42 @@ int omapfb_update_window_async(struct fb_info *fbi, void (*callback)(void *), void *callback_data) { + int xres, yres; struct omapfb_plane_struct *plane = fbi->par; struct omapfb_device *fbdev = plane->fbdev; - struct fb_var_screeninfo *var; + struct fb_var_screeninfo *var = &fbi->var; + + switch (var->rotate) { + case 0: + case 180: + xres = fbdev->panel->x_res; + yres = fbdev->panel->y_res; + break; + case 90: + case 270: + xres = fbdev->panel->y_res; + yres = fbdev->panel->x_res; + break; + default: + return -EINVAL; + } - var = &fbi->var; - if (win->x >= var->xres || win->y >= var->yres || - win->out_x > var->xres || win->out_y >= var->yres) + if (win->x >= xres || win->y >= yres || + win->out_x > xres || win->out_y > yres) return -EINVAL; if (!fbdev->ctrl->update_window || fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE) return -ENODEV; - if (win->x + win->width >= var->xres) - win->width = var->xres - win->x; - if (win->y + win->height >= var->yres) - win->height = var->yres - win->y; - /* The out sizes should be cropped to the LCD size */ - if (win->out_x + win->out_width > fbdev->panel->x_res) - win->out_width = fbdev->panel->x_res - win->out_x; - if (win->out_y + win->out_height > fbdev->panel->y_res) - win->out_height = fbdev->panel->y_res - win->out_y; + if (win->x + win->width > xres) + win->width = xres - win->x; + if (win->y + win->height > yres) + win->height = yres - win->y; + if (win->out_x + win->out_width > xres) + win->out_width = xres - win->out_x; + if (win->out_y + win->out_height > yres) + win->out_height = yres - win->out_y; if (!win->width || !win->height || !win->out_width || !win->out_height) return 0; @@ -1699,8 +1722,8 @@ static int omapfb_do_probe(struct platform_device *pdev, pr_info("omapfb: configured for panel %s\n", fbdev->panel->name); - def_vxres = def_vxres ? : fbdev->panel->x_res; - def_vyres = def_vyres ? : fbdev->panel->y_res; + def_vxres = def_vxres ? def_vxres : fbdev->panel->x_res; + def_vyres = def_vyres ? def_vyres : fbdev->panel->y_res; init_state++; @@ -1822,8 +1845,8 @@ static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg) { struct omapfb_device *fbdev = platform_get_drvdata(pdev); - omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]); - + if (fbdev != NULL) + omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]); return 0; } @@ -1832,7 +1855,8 @@ static int omapfb_resume(struct platform_device *pdev) { struct omapfb_device *fbdev = platform_get_drvdata(pdev); - omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]); + if (fbdev != NULL) + omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]); return 0; } diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c index 9332d6ca6456..ee01e84e19c1 100644 --- a/drivers/video/omap/rfbi.c +++ b/drivers/video/omap/rfbi.c @@ -57,6 +57,7 @@ #define DISPC_BASE 0x48050400 #define DISPC_CONTROL 0x0040 +#define DISPC_IRQ_FRAMEMASK 0x0001 static struct { void __iomem *base; @@ -553,7 +554,9 @@ static int rfbi_init(struct omapfb_device *fbdev) l = (0x01 << 2); rfbi_write_reg(RFBI_CONTROL, l); - if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) { + r = omap_dispc_request_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, + NULL); + if (r < 0) { dev_err(fbdev->dev, "can't get DISPC irq\n"); rfbi_enable_clocks(0); return r; @@ -570,7 +573,7 @@ static int rfbi_init(struct omapfb_device *fbdev) static void rfbi_cleanup(void) { - omap_dispc_free_irq(); + omap_dispc_free_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, NULL); rfbi_put_clocks(); iounmap(rfbi.base); } diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index bacfabd9ce16..0a366d86f08e 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -223,10 +223,14 @@ static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static inline int platinum_vram_reqd(int video_mode, int color_mode) { - return vmode_attrs[video_mode-1].vres * - (vmode_attrs[video_mode-1].hres * (1<<color_mode) + - ((video_mode == VMODE_832_624_75) && - (color_mode > CMODE_8)) ? 0x10 : 0x20) + 0x1000; + int baseval = vmode_attrs[video_mode-1].hres * (1<<color_mode); + + if ((video_mode == VMODE_832_624_75) && (color_mode > CMODE_8)) + baseval += 0x10; + else + baseval += 0x20; + + return vmode_attrs[video_mode-1].vres * baseval + 0x1000; } #define STORE_D2(a, d) { \ diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index c0af638fe702..9c0144ee7ae5 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c @@ -32,7 +32,7 @@ #include <linux/init.h> #include <asm/abs_addr.h> -#include <asm/iommu.h> +#include <asm/cell-regs.h> #include <asm/lv1call.h> #include <asm/ps3av.h> #include <asm/ps3fb.h> diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 6506117c134b..1820c4a24434 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -1638,24 +1638,26 @@ pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data) * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int pxafb_suspend(struct platform_device *dev, pm_message_t state) +static int pxafb_suspend(struct device *dev) { - struct pxafb_info *fbi = platform_get_drvdata(dev); + struct pxafb_info *fbi = dev_get_drvdata(dev); set_ctrlr_state(fbi, C_DISABLE_PM); return 0; } -static int pxafb_resume(struct platform_device *dev) +static int pxafb_resume(struct device *dev) { - struct pxafb_info *fbi = platform_get_drvdata(dev); + struct pxafb_info *fbi = dev_get_drvdata(dev); set_ctrlr_state(fbi, C_ENABLE_PM); return 0; } -#else -#define pxafb_suspend NULL -#define pxafb_resume NULL + +static struct dev_pm_ops pxafb_pm_ops = { + .suspend = pxafb_suspend, + .resume = pxafb_resume, +}; #endif static int __devinit pxafb_init_video_memory(struct pxafb_info *fbi) @@ -2081,6 +2083,9 @@ static int __devinit pxafb_probe(struct platform_device *dev) goto failed; } + if (cpu_is_pxa3xx() && inf->acceleration_enabled) + fbi->fb.fix.accel = FB_ACCEL_PXA3XX; + fbi->backlight_power = inf->pxafb_backlight_power; fbi->lcd_power = inf->pxafb_lcd_power; @@ -2091,14 +2096,14 @@ static int __devinit pxafb_probe(struct platform_device *dev) goto failed_fbi; } - r = request_mem_region(r->start, r->end - r->start + 1, dev->name); + r = request_mem_region(r->start, resource_size(r), dev->name); if (r == NULL) { dev_err(&dev->dev, "failed to request I/O memory\n"); ret = -EBUSY; goto failed_fbi; } - fbi->mmio_base = ioremap(r->start, r->end - r->start + 1); + fbi->mmio_base = ioremap(r->start, resource_size(r)); if (fbi->mmio_base == NULL) { dev_err(&dev->dev, "failed to map I/O memory\n"); ret = -EBUSY; @@ -2197,7 +2202,7 @@ failed_free_dma: failed_free_io: iounmap(fbi->mmio_base); failed_free_res: - release_mem_region(r->start, r->end - r->start + 1); + release_mem_region(r->start, resource_size(r)); failed_fbi: clk_put(fbi->clk); platform_set_drvdata(dev, NULL); @@ -2237,7 +2242,7 @@ static int __devexit pxafb_remove(struct platform_device *dev) iounmap(fbi->mmio_base); r = platform_get_resource(dev, IORESOURCE_MEM, 0); - release_mem_region(r->start, r->end - r->start + 1); + release_mem_region(r->start, resource_size(r)); clk_put(fbi->clk); kfree(fbi); @@ -2248,11 +2253,12 @@ static int __devexit pxafb_remove(struct platform_device *dev) static struct platform_driver pxafb_driver = { .probe = pxafb_probe, .remove = __devexit_p(pxafb_remove), - .suspend = pxafb_suspend, - .resume = pxafb_resume, .driver = { .owner = THIS_MODULE, .name = "pxa2xx-fb", +#ifdef CONFIG_PM + .pm = &pxafb_pm_ops, +#endif }, }; diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 5a72083dc67c..adf9632c6b1f 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -1036,7 +1036,7 @@ static int s3c_fb_resume(struct platform_device *pdev) static struct platform_driver s3c_fb_driver = { .probe = s3c_fb_probe, - .remove = s3c_fb_remove, + .remove = __devexit_p(s3c_fb_remove), .suspend = s3c_fb_suspend, .resume = s3c_fb_resume, .driver = { diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 7da0027e2409..aac661225c78 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -369,7 +369,9 @@ static void s3c2410fb_activate_var(struct fb_info *info) void __iomem *regs = fbi->io; int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT; struct fb_var_screeninfo *var = &info->var; - int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock) / 2; + int clkdiv; + + clkdiv = DIV_ROUND_UP(s3c2410fb_calc_pixclk(fbi, var->pixclock), 2); dprintk("%s: var->xres = %d\n", __func__, var->xres); dprintk("%s: var->yres = %d\n", __func__, var->yres); @@ -1119,7 +1121,7 @@ int __init s3c2410fb_init(void) int ret = platform_driver_register(&s3c2410fb_driver); if (ret == 0) - ret = platform_driver_register(&s3c2412fb_driver);; + ret = platform_driver_register(&s3c2412fb_driver); return ret; } diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 10ddad8e17d6..cdaa873a6054 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -66,7 +66,7 @@ * - FrameBuffer memory is now allocated at run-time when the * driver is initialized. * - * 2000/04/10: Nicolas Pitre <nico@cam.org> + * 2000/04/10: Nicolas Pitre <nico@fluxnic.net> * - Big cleanup for dynamic selection of machine type at run time. * * 2000/07/19: Jamey Hicks <jamey@crl.dec.com> diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 07f22b625632..3ad5157f9899 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -14,6 +14,7 @@ #include <linux/mm.h> #include <linux/fb.h> #include <linux/clk.h> +#include <linux/pm_runtime.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/interrupt.h> @@ -22,35 +23,8 @@ #include <asm/atomic.h> #define PALETTE_NR 16 - -struct sh_mobile_lcdc_priv; -struct sh_mobile_lcdc_chan { - struct sh_mobile_lcdc_priv *lcdc; - unsigned long *reg_offs; - unsigned long ldmt1r_value; - unsigned long enabled; /* ME and SE in LDCNT2R */ - struct sh_mobile_lcdc_chan_cfg cfg; - u32 pseudo_palette[PALETTE_NR]; - struct fb_info *info; - dma_addr_t dma_handle; - struct fb_deferred_io defio; - struct scatterlist *sglist; - unsigned long frame_end; - wait_queue_head_t frame_end_wait; -}; - -struct sh_mobile_lcdc_priv { - void __iomem *base; - int irq; -#ifdef CONFIG_HAVE_CLK - atomic_t clk_usecnt; - struct clk *dot_clk; - struct clk *clk; -#endif - unsigned long lddckr; - struct sh_mobile_lcdc_chan ch[2]; - int started; -}; +#define SIDE_B_OFFSET 0x1000 +#define MIRROR_OFFSET 0x2000 /* shared registers */ #define _LDDCKR 0x410 @@ -59,17 +33,30 @@ struct sh_mobile_lcdc_priv { #define _LDSR 0x46c #define _LDCNT1R 0x470 #define _LDCNT2R 0x474 +#define _LDRCNTR 0x478 #define _LDDDSR 0x47c #define _LDDWD0R 0x800 #define _LDDRDR 0x840 #define _LDDWAR 0x900 #define _LDDRAR 0x904 +/* shared registers and their order for context save/restore */ +static int lcdc_shared_regs[] = { + _LDDCKR, + _LDDCKSTPR, + _LDINTR, + _LDDDSR, + _LDCNT1R, + _LDCNT2R, +}; +#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) + /* per-channel registers */ enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, - LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR }; + LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR, + NR_CH_REGS }; -static unsigned long lcdc_offs_mainlcd[] = { +static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { [LDDCKPAT1R] = 0x400, [LDDCKPAT2R] = 0x404, [LDMT1R] = 0x418, @@ -87,7 +74,7 @@ static unsigned long lcdc_offs_mainlcd[] = { [LDPMR] = 0x460, }; -static unsigned long lcdc_offs_sublcd[] = { +static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { [LDDCKPAT1R] = 0x408, [LDDCKPAT2R] = 0x40c, [LDMT1R] = 0x600, @@ -110,12 +97,80 @@ static unsigned long lcdc_offs_sublcd[] = { #define DISPLAY_BEU 0x00000008 #define LCDC_ENABLE 0x00000001 #define LDINTR_FE 0x00000400 +#define LDINTR_VSE 0x00000200 +#define LDINTR_VEE 0x00000100 #define LDINTR_FS 0x00000004 +#define LDINTR_VSS 0x00000002 +#define LDINTR_VES 0x00000001 +#define LDRCNTR_SRS 0x00020000 +#define LDRCNTR_SRC 0x00010000 +#define LDRCNTR_MRS 0x00000002 +#define LDRCNTR_MRC 0x00000001 + +struct sh_mobile_lcdc_priv; +struct sh_mobile_lcdc_chan { + struct sh_mobile_lcdc_priv *lcdc; + unsigned long *reg_offs; + unsigned long ldmt1r_value; + unsigned long enabled; /* ME and SE in LDCNT2R */ + struct sh_mobile_lcdc_chan_cfg cfg; + u32 pseudo_palette[PALETTE_NR]; + unsigned long saved_ch_regs[NR_CH_REGS]; + struct fb_info *info; + dma_addr_t dma_handle; + struct fb_deferred_io defio; + struct scatterlist *sglist; + unsigned long frame_end; + unsigned long pan_offset; + unsigned long new_pan_offset; + wait_queue_head_t frame_end_wait; +}; + +struct sh_mobile_lcdc_priv { + void __iomem *base; + int irq; + atomic_t hw_usecnt; + struct device *dev; + struct clk *dot_clk; + unsigned long lddckr; + struct sh_mobile_lcdc_chan ch[2]; + unsigned long saved_shared_regs[NR_SHARED_REGS]; + int started; +}; + +static bool banked(int reg_nr) +{ + switch (reg_nr) { + case LDMT1R: + case LDMT2R: + case LDMT3R: + case LDDFR: + case LDSM1R: + case LDSA1R: + case LDMLSR: + case LDHCNR: + case LDHSYNR: + case LDVLNR: + case LDVSYNR: + return true; + } + return false; +} static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan, int reg_nr, unsigned long data) { iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]); + if (banked(reg_nr)) + iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] + + SIDE_B_OFFSET); +} + +static void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan *chan, + int reg_nr, unsigned long data) +{ + iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] + + MIRROR_OFFSET); } static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan, @@ -156,6 +211,7 @@ static void lcdc_sys_write_index(void *handle, unsigned long data) lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000); lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); + lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); } static void lcdc_sys_write_data(void *handle, unsigned long data) @@ -165,6 +221,7 @@ static void lcdc_sys_write_data(void *handle, unsigned long data) lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000); lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); + lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); } static unsigned long lcdc_sys_read_data(void *handle) @@ -175,8 +232,9 @@ static unsigned long lcdc_sys_read_data(void *handle) lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); udelay(1); + lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); - return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff; + return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff; } struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { @@ -185,11 +243,10 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { lcdc_sys_read_data, }; -#ifdef CONFIG_HAVE_CLK static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) { - if (atomic_inc_and_test(&priv->clk_usecnt)) { - clk_enable(priv->clk); + if (atomic_inc_and_test(&priv->hw_usecnt)) { + pm_runtime_get_sync(priv->dev); if (priv->dot_clk) clk_enable(priv->dot_clk); } @@ -197,16 +254,12 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) { - if (atomic_sub_return(1, &priv->clk_usecnt) == -1) { + if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { if (priv->dot_clk) clk_disable(priv->dot_clk); - clk_disable(priv->clk); + pm_runtime_put(priv->dev); } } -#else -static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {} -static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {} -#endif static int sh_mobile_lcdc_sginit(struct fb_info *info, struct list_head *pagelist) @@ -255,30 +308,52 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) struct sh_mobile_lcdc_priv *priv = data; struct sh_mobile_lcdc_chan *ch; unsigned long tmp; + unsigned long ldintr; int is_sub; int k; /* acknowledge interrupt */ - tmp = lcdc_read(priv, _LDINTR); - tmp &= 0xffffff00; /* mask in high 24 bits */ - tmp |= 0x000000ff ^ LDINTR_FS; /* status in low 8 */ + ldintr = tmp = lcdc_read(priv, _LDINTR); + /* + * disable further VSYNC End IRQs, preserve all other enabled IRQs, + * write 0 to bits 0-6 to ack all triggered IRQs. + */ + tmp &= 0xffffff00 & ~LDINTR_VEE; lcdc_write(priv, _LDINTR, tmp); /* figure out if this interrupt is for main or sub lcd */ is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0; - /* wake up channel and disable clocks*/ + /* wake up channel and disable clocks */ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { ch = &priv->ch[k]; if (!ch->enabled) continue; - if (is_sub == lcdc_chan_is_sublcd(ch)) { - ch->frame_end = 1; - wake_up(&ch->frame_end_wait); + /* Frame Start */ + if (ldintr & LDINTR_FS) { + if (is_sub == lcdc_chan_is_sublcd(ch)) { + ch->frame_end = 1; + wake_up(&ch->frame_end_wait); - sh_mobile_lcdc_clk_off(priv); + sh_mobile_lcdc_clk_off(priv); + } + } + + /* VSYNC End */ + if (ldintr & LDINTR_VES) { + unsigned long ldrcntr = lcdc_read(priv, _LDRCNTR); + /* Set the source address for the next refresh */ + lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle + + ch->new_pan_offset); + if (lcdc_chan_is_sublcd(ch)) + lcdc_write(ch->lcdc, _LDRCNTR, + ldrcntr ^ LDRCNTR_SRS); + else + lcdc_write(ch->lcdc, _LDRCNTR, + ldrcntr ^ LDRCNTR_MRS); + ch->pan_offset = ch->new_pan_offset; } } @@ -520,7 +595,6 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) board_cfg = &ch->cfg.board_cfg; if (board_cfg->display_off) board_cfg->display_off(board_cfg->board_data); - } /* stop the lcdc */ @@ -579,9 +653,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, int clock_source, struct sh_mobile_lcdc_priv *priv) { -#ifdef CONFIG_HAVE_CLK - char clk_name[8]; -#endif char *str; int icksel; @@ -595,25 +666,21 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, priv->lddckr = icksel << 16; -#ifdef CONFIG_HAVE_CLK - atomic_set(&priv->clk_usecnt, -1); - snprintf(clk_name, sizeof(clk_name), "lcdc%d", pdev->id); - priv->clk = clk_get(&pdev->dev, clk_name); - if (IS_ERR(priv->clk)) { - dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); - return PTR_ERR(priv->clk); - } - if (str) { priv->dot_clk = clk_get(&pdev->dev, str); if (IS_ERR(priv->dot_clk)) { dev_err(&pdev->dev, "cannot get dot clock %s\n", str); - clk_put(priv->clk); return PTR_ERR(priv->dot_clk); } } -#endif - + atomic_set(&priv->hw_usecnt, -1); + + /* Runtime PM support involves two step for this driver: + * 1) Enable Runtime PM + * 2) Force Runtime PM Resume since hardware is accessed from probe() + */ + pm_runtime_enable(priv->dev); + pm_runtime_resume(priv->dev); return 0; } @@ -646,6 +713,9 @@ static struct fb_fix_screeninfo sh_mobile_lcdc_fix = { .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_TRUECOLOR, .accel = FB_ACCEL_NONE, + .xpanstep = 0, + .ypanstep = 1, + .ywrapstep = 0, }; static void sh_mobile_lcdc_fillrect(struct fb_info *info, @@ -669,13 +739,38 @@ static void sh_mobile_lcdc_imageblit(struct fb_info *info, sh_mobile_lcdc_deferred_io_touch(info); } +static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct sh_mobile_lcdc_chan *ch = info->par; + + if (info->var.xoffset == var->xoffset && + info->var.yoffset == var->yoffset) + return 0; /* No change, do nothing */ + + ch->new_pan_offset = (var->yoffset * info->fix.line_length) + + (var->xoffset * (info->var.bits_per_pixel / 8)); + + if (ch->new_pan_offset != ch->pan_offset) { + unsigned long ldintr; + ldintr = lcdc_read(ch->lcdc, _LDINTR); + ldintr |= LDINTR_VEE; + lcdc_write(ch->lcdc, _LDINTR, ldintr); + sh_mobile_lcdc_deferred_io_touch(info); + } + + return 0; +} + static struct fb_ops sh_mobile_lcdc_ops = { + .owner = THIS_MODULE, .fb_setcolreg = sh_mobile_lcdc_setcolreg, .fb_read = fb_sys_read, .fb_write = fb_sys_write, .fb_fillrect = sh_mobile_lcdc_fillrect, .fb_copyarea = sh_mobile_lcdc_copyarea, .fb_imageblit = sh_mobile_lcdc_imageblit, + .fb_pan_display = sh_mobile_fb_pan_display, }; static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) @@ -731,9 +826,59 @@ static int sh_mobile_lcdc_resume(struct device *dev) return sh_mobile_lcdc_start(platform_get_drvdata(pdev)); } +static int sh_mobile_lcdc_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); + struct sh_mobile_lcdc_chan *ch; + int k, n; + + /* save per-channel registers */ + for (k = 0; k < ARRAY_SIZE(p->ch); k++) { + ch = &p->ch[k]; + if (!ch->enabled) + continue; + for (n = 0; n < NR_CH_REGS; n++) + ch->saved_ch_regs[n] = lcdc_read_chan(ch, n); + } + + /* save shared registers */ + for (n = 0; n < NR_SHARED_REGS; n++) + p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]); + + /* turn off LCDC hardware */ + lcdc_write(p, _LDCNT1R, 0); + return 0; +} + +static int sh_mobile_lcdc_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); + struct sh_mobile_lcdc_chan *ch; + int k, n; + + /* restore per-channel registers */ + for (k = 0; k < ARRAY_SIZE(p->ch); k++) { + ch = &p->ch[k]; + if (!ch->enabled) + continue; + for (n = 0; n < NR_CH_REGS; n++) + lcdc_write_chan(ch, n, ch->saved_ch_regs[n]); + } + + /* restore shared registers */ + for (n = 0; n < NR_SHARED_REGS; n++) + lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]); + + return 0; +} + static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { .suspend = sh_mobile_lcdc_suspend, .resume = sh_mobile_lcdc_resume, + .runtime_suspend = sh_mobile_lcdc_runtime_suspend, + .runtime_resume = sh_mobile_lcdc_runtime_resume, }; static int sh_mobile_lcdc_remove(struct platform_device *pdev); @@ -778,6 +923,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) } priv->irq = i; + priv->dev = &pdev->dev; platform_set_drvdata(pdev, priv); pdata = pdev->dev.platform_data; @@ -792,6 +938,8 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) goto err1; } init_waitqueue_head(&priv->ch[i].frame_end_wait); + priv->ch[j].pan_offset = 0; + priv->ch[j].new_pan_offset = 0; switch (pdata->ch[i].chan) { case LCDC_CHAN_MAINLCD: @@ -834,7 +982,9 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) info = priv->ch[i].info; info->fbops = &sh_mobile_lcdc_ops; info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; - info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres; + info->var.yres = cfg->lcd_cfg.yres; + /* Default Y virtual resolution is 2x panel size */ + info->var.yres_virtual = info->var.yres * 2; info->var.width = cfg->lcd_size_cfg.width; info->var.height = cfg->lcd_size_cfg.height; info->var.activate = FB_ACTIVATE_NOW; @@ -844,7 +994,8 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) info->fix = sh_mobile_lcdc_fix; info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8); - info->fix.smem_len = info->fix.line_length * cfg->lcd_cfg.yres; + info->fix.smem_len = info->fix.line_length * + info->var.yres_virtual; buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, &priv->ch[i].dma_handle, GFP_KERNEL); @@ -947,11 +1098,10 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) framebuffer_release(info); } -#ifdef CONFIG_HAVE_CLK if (priv->dot_clk) clk_put(priv->dot_clk); - clk_put(priv->clk); -#endif + + pm_runtime_disable(priv->dev); if (priv->base) iounmap(priv->base); diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 4a067f0d0ceb..a4e05e4d7501 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -698,8 +698,8 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int rate, sisfb_vrate[i].refresh); ivideo->rate_idx = sisfb_vrate[i].idx; ivideo->refresh_rate = sisfb_vrate[i].refresh; - } else if(((rate - sisfb_vrate[i-1].refresh) <= 2) - && (sisfb_vrate[i].idx != 1)) { + } else if((sisfb_vrate[i].idx != 1) && + ((rate - sisfb_vrate[i-1].refresh) <= 2)) { DPRINTK("sisfb: Adjusting rate from %d down to %d\n", rate, sisfb_vrate[i-1].refresh); ivideo->rate_idx = sisfb_vrate[i-1].idx; diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h index 705c85360526..bef4aae388d0 100644 --- a/drivers/video/sis/vstruct.h +++ b/drivers/video/sis/vstruct.h @@ -342,7 +342,7 @@ struct SiS_Private unsigned short SiS_RY4COE; unsigned short SiS_LCDHDES; unsigned short SiS_LCDVDES; - unsigned short SiS_DDC_Port; + SISIOADDRESS SiS_DDC_Port; unsigned short SiS_DDC_Index; unsigned short SiS_DDC_Data; unsigned short SiS_DDC_NData; diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index a1eb0862255b..6913fe168c25 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c @@ -974,7 +974,7 @@ static int tmiofb_resume(struct platform_device *dev) { struct fb_info *info = platform_get_drvdata(dev); struct mfd_cell *cell = dev->dev.platform_data; - int retval; + int retval = 0; acquire_console_sem(); diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index ca5b4643a401..e98baf6916b8 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -67,9 +67,8 @@ static DEFINE_MUTEX(uvfb_lock); * find the kernel part of the task struct, copy the registers and * the buffer contents and then complete the task. */ -static void uvesafb_cn_callback(void *data) +static void uvesafb_cn_callback(struct cn_msg *msg) { - struct cn_msg *msg = data; struct uvesafb_task *utask; struct uvesafb_ktask *task; diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 45c54bfe99bb..9d4f3a49ba4a 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -20,229 +20,430 @@ */ #include "global.h" -void viafb_init_accel(void) +static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, + u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, + u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, + u32 fg_color, u32 bg_color, u8 fill_rop) { - viaparinfo->fbmem_free -= CURSOR_SIZE; - viaparinfo->cursor_start = viaparinfo->fbmem_free; - viaparinfo->fbmem_used += CURSOR_SIZE; + u32 ge_cmd = 0, tmp, i; - /* Reverse 8*1024 memory space for cursor image */ - viaparinfo->fbmem_free -= (CURSOR_SIZE + VQ_SIZE); - viaparinfo->VQ_start = viaparinfo->fbmem_free; - viaparinfo->VQ_end = viaparinfo->VQ_start + VQ_SIZE - 1; - viaparinfo->fbmem_used += (CURSOR_SIZE + VQ_SIZE); } - -void viafb_init_2d_engine(void) -{ - u32 dwVQStartAddr, dwVQEndAddr; - u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH; - - /* init 2D engine regs to reset 2D engine */ - writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE); - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); - writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS); - writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION); - writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR); - writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR); - writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR); - writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL); - writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR); - writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET); - writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL); - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); - writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE); - writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH); - writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1); - - /* Init AGP and VQ regs */ - switch (viaparinfo->chip_info->gfx_chip_name) { - case UNICHROME_K8M890: - case UNICHROME_P4M900: - writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET); - writel(0x680A0000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); - writel(0x02000000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); - break; + if (!op || op > 3) { + printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op); + return -EINVAL; + } - default: - writel(0x00100000, viaparinfo->io_virt + VIA_REG_TRANSET); - writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x00333004, viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x60000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x61000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x62000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x63000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x64000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x7D000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); - - writel(0xFE020000, viaparinfo->io_virt + VIA_REG_TRANSET); - writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); - break; + if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) { + if (src_x < dst_x) { + ge_cmd |= 0x00008000; + src_x += width - 1; + dst_x += width - 1; + } + if (src_y < dst_y) { + ge_cmd |= 0x00004000; + src_y += height - 1; + dst_y += height - 1; + } } - if (viaparinfo->VQ_start != 0) { - /* Enable VQ */ - dwVQStartAddr = viaparinfo->VQ_start; - dwVQEndAddr = viaparinfo->VQ_end; - - dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF); - dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF); - dwVQStartEndH = 0x52000000 | - ((dwVQStartAddr & 0xFF000000) >> 24) | - ((dwVQEndAddr & 0xFF000000) >> 16); - dwVQLen = 0x53000000 | (VQ_SIZE >> 3); - switch (viaparinfo->chip_info->gfx_chip_name) { - case UNICHROME_K8M890: - case UNICHROME_P4M900: - dwVQStartL |= 0x20000000; - dwVQEndL |= 0x20000000; - dwVQStartEndH |= 0x20000000; - dwVQLen |= 0x20000000; + + if (op == VIA_BITBLT_FILL) { + switch (fill_rop) { + case 0x00: /* blackness */ + case 0x5A: /* pattern inversion */ + case 0xF0: /* pattern copy */ + case 0xFF: /* whiteness */ break; default: - break; + printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: " + "%u\n", fill_rop); + return -EINVAL; } + } - switch (viaparinfo->chip_info->gfx_chip_name) { - case UNICHROME_K8M890: - case UNICHROME_P4M900: - writel(0x00100000, - viaparinfo->io_virt + VIA_REG_CR_TRANSET); - writel(dwVQStartEndH, - viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); - writel(dwVQStartL, - viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); - writel(dwVQEndL, - viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); - writel(dwVQLen, - viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); - writel(0x74301001, - viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); - writel(0x00000000, - viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); - break; - default: - writel(0x00FE0000, - viaparinfo->io_virt + VIA_REG_TRANSET); - writel(0x080003FE, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x0A00027C, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x0B000260, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x0C000274, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x0D000264, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x0E000000, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x0F000020, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x1000027E, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x110002FE, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x200F0060, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - - writel(0x00000006, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x40008C0F, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x44000000, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x45080C04, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x46800408, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - - writel(dwVQStartEndH, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(dwVQStartL, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(dwVQEndL, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(dwVQLen, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - break; + switch (dst_bpp) { + case 8: + tmp = 0x00000000; + break; + case 16: + tmp = 0x00000100; + break; + case 32: + tmp = 0x00000300; + break; + default: + printk(KERN_WARNING "hw_bitblt_1: Unsupported bpp %d\n", + dst_bpp); + return -EINVAL; + } + writel(tmp, engine + 0x04); + + if (op != VIA_BITBLT_FILL) { + if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000) + || src_y & 0xFFFFF000) { + printk(KERN_WARNING "hw_bitblt_1: Unsupported source " + "x/y %d %d\n", src_x, src_y); + return -EINVAL; } - } else { - /* Disable VQ */ - switch (viaparinfo->chip_info->gfx_chip_name) { - case UNICHROME_K8M890: - case UNICHROME_P4M900: - writel(0x00100000, - viaparinfo->io_virt + VIA_REG_CR_TRANSET); - writel(0x74301000, - viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); - break; - default: - writel(0x00FE0000, - viaparinfo->io_virt + VIA_REG_TRANSET); - writel(0x00000004, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x40008C0F, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x44000000, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x45080C04, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - writel(0x46800408, - viaparinfo->io_virt + VIA_REG_TRANSPACE); - break; + tmp = src_x | (src_y << 16); + writel(tmp, engine + 0x08); + } + + if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) { + printk(KERN_WARNING "hw_bitblt_1: Unsupported destination x/y " + "%d %d\n", dst_x, dst_y); + return -EINVAL; + } + tmp = dst_x | (dst_y << 16); + writel(tmp, engine + 0x0C); + + if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) { + printk(KERN_WARNING "hw_bitblt_1: Unsupported width/height " + "%d %d\n", width, height); + return -EINVAL; + } + tmp = (width - 1) | ((height - 1) << 16); + writel(tmp, engine + 0x10); + + if (op != VIA_BITBLT_COLOR) + writel(fg_color, engine + 0x18); + + if (op == VIA_BITBLT_MONO) + writel(bg_color, engine + 0x1C); + + if (op != VIA_BITBLT_FILL) { + tmp = src_mem ? 0 : src_addr; + if (dst_addr & 0xE0000007) { + printk(KERN_WARNING "hw_bitblt_1: Unsupported source " + "address %X\n", tmp); + return -EINVAL; } + tmp >>= 3; + writel(tmp, engine + 0x30); + } + + if (dst_addr & 0xE0000007) { + printk(KERN_WARNING "hw_bitblt_1: Unsupported destination " + "address %X\n", dst_addr); + return -EINVAL; } + tmp = dst_addr >> 3; + writel(tmp, engine + 0x34); - viafb_set_2d_color_depth(viaparinfo->bpp); + if (op == VIA_BITBLT_FILL) + tmp = 0; + else + tmp = src_pitch; + if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) { + printk(KERN_WARNING "hw_bitblt_1: Unsupported pitch %X %X\n", + tmp, dst_pitch); + return -EINVAL; + } + tmp = (tmp >> 3) | (dst_pitch << (16 - 3)); + writel(tmp, engine + 0x38); + + if (op == VIA_BITBLT_FILL) + ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001; + else { + ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */ + if (src_mem) + ge_cmd |= 0x00000040; + if (op == VIA_BITBLT_MONO) + ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000; + else + ge_cmd |= 0x00000001; + } + writel(ge_cmd, engine); - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); - writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE); + if (op == VIA_BITBLT_FILL || !src_mem) + return 0; - writel(VIA_PITCH_ENABLE | - (((viaparinfo->hres * - viaparinfo->bpp >> 3) >> 3) | (((viaparinfo->hres * - viaparinfo-> - bpp >> 3) >> 3) << 16)), - viaparinfo->io_virt + VIA_REG_PITCH); + tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) + + 3) >> 2; + + for (i = 0; i < tmp; i++) + writel(src_mem[i], engine + VIA_MMIO_BLTBASE); + + return 0; } -void viafb_set_2d_color_depth(int bpp) +static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, + u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, + u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, + u32 fg_color, u32 bg_color, u8 fill_rop) { - u32 dwGEMode; + u32 ge_cmd = 0, tmp, i; + + if (!op || op > 3) { + printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op); + return -EINVAL; + } - dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF; + if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) { + if (src_x < dst_x) { + ge_cmd |= 0x00008000; + src_x += width - 1; + dst_x += width - 1; + } + if (src_y < dst_y) { + ge_cmd |= 0x00004000; + src_y += height - 1; + dst_y += height - 1; + } + } - switch (bpp) { + if (op == VIA_BITBLT_FILL) { + switch (fill_rop) { + case 0x00: /* blackness */ + case 0x5A: /* pattern inversion */ + case 0xF0: /* pattern copy */ + case 0xFF: /* whiteness */ + break; + default: + printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: " + "%u\n", fill_rop); + return -EINVAL; + } + } + + switch (dst_bpp) { + case 8: + tmp = 0x00000000; + break; case 16: - dwGEMode |= VIA_GEM_16bpp; + tmp = 0x00000100; break; case 32: - dwGEMode |= VIA_GEM_32bpp; + tmp = 0x00000300; break; default: - dwGEMode |= VIA_GEM_8bpp; - break; + printk(KERN_WARNING "hw_bitblt_2: Unsupported bpp %d\n", + dst_bpp); + return -EINVAL; + } + writel(tmp, engine + 0x04); + + if (op == VIA_BITBLT_FILL) + tmp = 0; + else + tmp = src_pitch; + if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) { + printk(KERN_WARNING "hw_bitblt_2: Unsupported pitch %X %X\n", + tmp, dst_pitch); + return -EINVAL; + } + tmp = (tmp >> 3) | (dst_pitch << (16 - 3)); + writel(tmp, engine + 0x08); + + if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) { + printk(KERN_WARNING "hw_bitblt_2: Unsupported width/height " + "%d %d\n", width, height); + return -EINVAL; + } + tmp = (width - 1) | ((height - 1) << 16); + writel(tmp, engine + 0x0C); + + if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) { + printk(KERN_WARNING "hw_bitblt_2: Unsupported destination x/y " + "%d %d\n", dst_x, dst_y); + return -EINVAL; + } + tmp = dst_x | (dst_y << 16); + writel(tmp, engine + 0x10); + + if (dst_addr & 0xE0000007) { + printk(KERN_WARNING "hw_bitblt_2: Unsupported destination " + "address %X\n", dst_addr); + return -EINVAL; + } + tmp = dst_addr >> 3; + writel(tmp, engine + 0x14); + + if (op != VIA_BITBLT_FILL) { + if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000) + || src_y & 0xFFFFF000) { + printk(KERN_WARNING "hw_bitblt_2: Unsupported source " + "x/y %d %d\n", src_x, src_y); + return -EINVAL; + } + tmp = src_x | (src_y << 16); + writel(tmp, engine + 0x18); + + tmp = src_mem ? 0 : src_addr; + if (dst_addr & 0xE0000007) { + printk(KERN_WARNING "hw_bitblt_2: Unsupported source " + "address %X\n", tmp); + return -EINVAL; + } + tmp >>= 3; + writel(tmp, engine + 0x1C); } - /* Set BPP and Pitch */ - writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE); + if (op != VIA_BITBLT_COLOR) + writel(fg_color, engine + 0x4C); + + if (op == VIA_BITBLT_MONO) + writel(bg_color, engine + 0x50); + + if (op == VIA_BITBLT_FILL) + ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001; + else { + ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */ + if (src_mem) + ge_cmd |= 0x00000040; + if (op == VIA_BITBLT_MONO) + ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000; + else + ge_cmd |= 0x00000001; + } + writel(ge_cmd, engine); + + if (op == VIA_BITBLT_FILL || !src_mem) + return 0; + + tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) + + 3) >> 2; + + for (i = 0; i < tmp; i++) + writel(src_mem[i], engine + VIA_MMIO_BLTBASE); + + return 0; } -void viafb_hw_cursor_init(void) +int viafb_init_engine(struct fb_info *info) { + struct viafb_par *viapar = info->par; + void __iomem *engine; + u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high, + vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name; + + engine = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); + viapar->shared->engine_mmio = engine; + if (!engine) { + printk(KERN_WARNING "viafb_init_accel: ioremap failed, " + "hardware acceleration disabled\n"); + return -ENOMEM; + } + + switch (chip_name) { + case UNICHROME_CLE266: + case UNICHROME_K400: + case UNICHROME_K800: + case UNICHROME_PM800: + case UNICHROME_CN700: + case UNICHROME_CX700: + case UNICHROME_CN750: + case UNICHROME_K8M890: + case UNICHROME_P4M890: + case UNICHROME_P4M900: + viapar->shared->hw_bitblt = hw_bitblt_1; + break; + case UNICHROME_VX800: + case UNICHROME_VX855: + viapar->shared->hw_bitblt = hw_bitblt_2; + break; + default: + viapar->shared->hw_bitblt = NULL; + } + + viapar->fbmem_free -= CURSOR_SIZE; + viapar->shared->cursor_vram_addr = viapar->fbmem_free; + viapar->fbmem_used += CURSOR_SIZE; + + viapar->fbmem_free -= VQ_SIZE; + viapar->shared->vq_vram_addr = viapar->fbmem_free; + viapar->fbmem_used += VQ_SIZE; + + /* Init AGP and VQ regs */ + switch (chip_name) { + case UNICHROME_K8M890: + case UNICHROME_P4M900: + writel(0x00100000, engine + VIA_REG_CR_TRANSET); + writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE); + writel(0x02000000, engine + VIA_REG_CR_TRANSPACE); + break; + + default: + writel(0x00100000, engine + VIA_REG_TRANSET); + writel(0x00000000, engine + VIA_REG_TRANSPACE); + writel(0x00333004, engine + VIA_REG_TRANSPACE); + writel(0x60000000, engine + VIA_REG_TRANSPACE); + writel(0x61000000, engine + VIA_REG_TRANSPACE); + writel(0x62000000, engine + VIA_REG_TRANSPACE); + writel(0x63000000, engine + VIA_REG_TRANSPACE); + writel(0x64000000, engine + VIA_REG_TRANSPACE); + writel(0x7D000000, engine + VIA_REG_TRANSPACE); + + writel(0xFE020000, engine + VIA_REG_TRANSET); + writel(0x00000000, engine + VIA_REG_TRANSPACE); + break; + } + + /* Enable VQ */ + vq_start_addr = viapar->shared->vq_vram_addr; + vq_end_addr = viapar->shared->vq_vram_addr + VQ_SIZE - 1; + + vq_start_low = 0x50000000 | (vq_start_addr & 0xFFFFFF); + vq_end_low = 0x51000000 | (vq_end_addr & 0xFFFFFF); + vq_high = 0x52000000 | ((vq_start_addr & 0xFF000000) >> 24) | + ((vq_end_addr & 0xFF000000) >> 16); + vq_len = 0x53000000 | (VQ_SIZE >> 3); + + switch (chip_name) { + case UNICHROME_K8M890: + case UNICHROME_P4M900: + vq_start_low |= 0x20000000; + vq_end_low |= 0x20000000; + vq_high |= 0x20000000; + vq_len |= 0x20000000; + + writel(0x00100000, engine + VIA_REG_CR_TRANSET); + writel(vq_high, engine + VIA_REG_CR_TRANSPACE); + writel(vq_start_low, engine + VIA_REG_CR_TRANSPACE); + writel(vq_end_low, engine + VIA_REG_CR_TRANSPACE); + writel(vq_len, engine + VIA_REG_CR_TRANSPACE); + writel(0x74301001, engine + VIA_REG_CR_TRANSPACE); + writel(0x00000000, engine + VIA_REG_CR_TRANSPACE); + break; + default: + writel(0x00FE0000, engine + VIA_REG_TRANSET); + writel(0x080003FE, engine + VIA_REG_TRANSPACE); + writel(0x0A00027C, engine + VIA_REG_TRANSPACE); + writel(0x0B000260, engine + VIA_REG_TRANSPACE); + writel(0x0C000274, engine + VIA_REG_TRANSPACE); + writel(0x0D000264, engine + VIA_REG_TRANSPACE); + writel(0x0E000000, engine + VIA_REG_TRANSPACE); + writel(0x0F000020, engine + VIA_REG_TRANSPACE); + writel(0x1000027E, engine + VIA_REG_TRANSPACE); + writel(0x110002FE, engine + VIA_REG_TRANSPACE); + writel(0x200F0060, engine + VIA_REG_TRANSPACE); + + writel(0x00000006, engine + VIA_REG_TRANSPACE); + writel(0x40008C0F, engine + VIA_REG_TRANSPACE); + writel(0x44000000, engine + VIA_REG_TRANSPACE); + writel(0x45080C04, engine + VIA_REG_TRANSPACE); + writel(0x46800408, engine + VIA_REG_TRANSPACE); + + writel(vq_high, engine + VIA_REG_TRANSPACE); + writel(vq_start_low, engine + VIA_REG_TRANSPACE); + writel(vq_end_low, engine + VIA_REG_TRANSPACE); + writel(vq_len, engine + VIA_REG_TRANSPACE); + break; + } + /* Set Cursor Image Base Address */ - writel(viaparinfo->cursor_start, - viaparinfo->io_virt + VIA_REG_CURSOR_MODE); - writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_POS); - writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_ORG); - writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_BG); - writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_FG); + writel(viapar->shared->cursor_vram_addr, engine + VIA_REG_CURSOR_MODE); + writel(0x0, engine + VIA_REG_CURSOR_POS); + writel(0x0, engine + VIA_REG_CURSOR_ORG); + writel(0x0, engine + VIA_REG_CURSOR_BG); + writel(0x0, engine + VIA_REG_CURSOR_FG); + return 0; } void viafb_show_hw_cursor(struct fb_info *info, int Status) { - u32 temp; - u32 iga_path = ((struct viafb_par *)(info->par))->iga_path; + struct viafb_par *viapar = info->par; + u32 temp, iga_path = viapar->iga_path; - temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE); + temp = readl(viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE); switch (Status) { case HW_Cursor_ON: temp |= 0x1; @@ -259,25 +460,27 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status) default: temp &= 0x7FFFFFFF; } - writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE); + writel(temp, viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE); } -int viafb_wait_engine_idle(void) +void viafb_wait_engine_idle(struct fb_info *info) { + struct viafb_par *viapar = info->par; int loop = 0; - while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & + while (!(readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { loop++; cpu_relax(); } - while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & + while ((readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && (loop < MAXLOOP)) { loop++; cpu_relax(); } - return loop >= MAXLOOP; + if (loop >= MAXLOOP) + printk(KERN_ERR "viafb_wait_engine_idle: not syncing\n"); } diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h index 29bf854e8ccf..615c84ad0f01 100644 --- a/drivers/video/via/accel.h +++ b/drivers/video/via/accel.h @@ -159,11 +159,12 @@ #define MAXLOOP 0xFFFFFF -void viafb_init_accel(void); -void viafb_init_2d_engine(void); -void set_2d_color_depth(int); -void viafb_hw_cursor_init(void); -void viafb_show_hw_cursor(struct fb_info *info, int Status); int -viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp); +#define VIA_BITBLT_COLOR 1 +#define VIA_BITBLT_MONO 2 +#define VIA_BITBLT_FILL 3 + +int viafb_init_engine(struct fb_info *info); +void viafb_show_hw_cursor(struct fb_info *info, int Status); +void viafb_wait_engine_idle(struct fb_info *info); #endif /* __ACCEL_H__ */ diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index dde95edc387a..474f428aea92 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h @@ -68,6 +68,9 @@ #define UNICHROME_VX800 11 #define UNICHROME_VX800_DID 0x1122 +#define UNICHROME_VX855 12 +#define UNICHROME_VX855_DID 0x5122 + /**************************************************/ /* Definition TMDS Trasmitter Information */ /**************************************************/ @@ -122,7 +125,6 @@ struct lvds_chip_information { struct chip_information { int gfx_chip_name; int gfx_chip_revision; - int chip_on_slot; struct tmds_chip_information tmds_chip_info; struct lvds_chip_information lvds_chip_info; struct lvds_chip_information lvds_chip_info2; diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index d6965447ca69..c5c32b6b6e6c 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c @@ -160,7 +160,7 @@ int viafb_tmds_trasmitter_identify(void) static void tmds_register_write(int index, u8 data) { - viaparinfo->i2c_stuff.i2c_port = + viaparinfo->shared->i2c_stuff.i2c_port = viaparinfo->chip_info->tmds_chip_info.i2c_port; viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info. @@ -172,7 +172,7 @@ static int tmds_register_read(int index) { u8 data; - viaparinfo->i2c_stuff.i2c_port = + viaparinfo->shared->i2c_stuff.i2c_port = viaparinfo->chip_info->tmds_chip_info.i2c_port; viafb_i2c_readbyte((u8) viaparinfo->chip_info-> tmds_chip_info.tmds_chip_slave_addr, @@ -182,7 +182,7 @@ static int tmds_register_read(int index) static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) { - viaparinfo->i2c_stuff.i2c_port = + viaparinfo->shared->i2c_stuff.i2c_port = viaparinfo->chip_info->tmds_chip_info.i2c_port; viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info. tmds_chip_slave_addr, (u8) index, buff, buff_len); diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c index 468be2425af3..b675cdbb03ad 100644 --- a/drivers/video/via/global.c +++ b/drivers/video/via/global.c @@ -32,7 +32,6 @@ int viafb_lcd_dsp_method = LCD_EXPANDSION; int viafb_lcd_mode = LCD_OPENLDI; int viafb_bpp = 32; int viafb_bpp1 = 32; -int viafb_accel = 1; int viafb_CRT_ON = 1; int viafb_DVI_ON; int viafb_LCD_ON ; @@ -46,13 +45,11 @@ int viafb_hotplug_refresh = 60; unsigned int viafb_second_offset; int viafb_second_size; int viafb_primary_dev = None_Device; -void __iomem *viafb_FB_MM; unsigned int viafb_second_xres = 640; unsigned int viafb_second_yres = 480; unsigned int viafb_second_virtual_xres; unsigned int viafb_second_virtual_yres; int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1; -struct fb_cursor viacursor; struct fb_info *viafbinfo; struct fb_info *viafbinfo1; struct viafb_par *viaparinfo; diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index 7543d5f7e309..d69d0ca99c2f 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h @@ -77,8 +77,6 @@ extern int viafb_hotplug_Yres; extern int viafb_hotplug_bpp; extern int viafb_hotplug_refresh; extern int viafb_primary_dev; -extern void __iomem *viafb_FB_MM; -extern struct fb_cursor viacursor; extern unsigned int viafb_second_xres; extern unsigned int viafb_second_yres; diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index c8960003f47d..3e083ff67ae2 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -21,125 +21,143 @@ #include "global.h" -static const struct pci_device_id_info pciidlist[] = { - {PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, UNICHROME_CLE266}, - {PCI_VIA_VENDOR_ID, UNICHROME_PM800_DID, UNICHROME_PM800}, - {PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, UNICHROME_K400}, - {PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, UNICHROME_K800}, - {PCI_VIA_VENDOR_ID, UNICHROME_CN700_DID, UNICHROME_CN700}, - {PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, UNICHROME_P4M890}, - {PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, UNICHROME_K8M890}, - {PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, UNICHROME_CX700}, - {PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, UNICHROME_P4M900}, - {PCI_VIA_VENDOR_ID, UNICHROME_CN750_DID, UNICHROME_CN750}, - {PCI_VIA_VENDOR_ID, UNICHROME_VX800_DID, UNICHROME_VX800}, - {0, 0, 0} -}; - -struct offset offset_reg = { - /* IGA1 Offset Register */ - {IGA1_OFFSET_REG_NUM, {{CR13, 0, 7}, {CR35, 5, 7} } }, - /* IGA2 Offset Register */ - {IGA2_OFFSET_REG_NUM, {{CR66, 0, 7}, {CR67, 0, 1} } } -}; - static struct pll_map pll_value[] = { - {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, CX700_25_175M}, - {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, CX700_29_581M}, - {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, CX700_26_880M}, - {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, CX700_31_490M}, - {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, CX700_31_500M}, - {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, CX700_31_728M}, - {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, CX700_32_668M}, - {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, CX700_36_000M}, - {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, CX700_40_000M}, - {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, CX700_41_291M}, - {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, CX700_43_163M}, - {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, CX700_45_250M}, - {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, CX700_46_000M}, - {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, CX700_46_996M}, - {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, CX700_48_000M}, - {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, CX700_48_875M}, - {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, CX700_49_500M}, - {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, CX700_52_406M}, - {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, CX700_52_977M}, - {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, CX700_56_250M}, - {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, CX700_60_466M}, - {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, CX700_61_500M}, - {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, CX700_65_000M}, - {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, CX700_65_178M}, - {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, CX700_66_750M}, - {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, CX700_68_179M}, - {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, CX700_69_924M}, - {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, CX700_70_159M}, - {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, CX700_72_000M}, - {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, CX700_78_750M}, - {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, CX700_80_136M}, - {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, CX700_83_375M}, - {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, CX700_83_950M}, - {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, CX700_84_750M}, - {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, CX700_85_860M}, - {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, CX700_88_750M}, - {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, CX700_94_500M}, - {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, CX700_97_750M}, + {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, + CX700_25_175M, VX855_25_175M}, + {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, + CX700_29_581M, VX855_29_581M}, + {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, + CX700_26_880M, VX855_26_880M}, + {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, + CX700_31_490M, VX855_31_490M}, + {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, + CX700_31_500M, VX855_31_500M}, + {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, + CX700_31_728M, VX855_31_728M}, + {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, + CX700_32_668M, VX855_32_668M}, + {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, + CX700_36_000M, VX855_36_000M}, + {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, + CX700_40_000M, VX855_40_000M}, + {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, + CX700_41_291M, VX855_41_291M}, + {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, + CX700_43_163M, VX855_43_163M}, + {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, + CX700_45_250M, VX855_45_250M}, + {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, + CX700_46_000M, VX855_46_000M}, + {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, + CX700_46_996M, VX855_46_996M}, + {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, + CX700_48_000M, VX855_48_000M}, + {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, + CX700_48_875M, VX855_48_875M}, + {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, + CX700_49_500M, VX855_49_500M}, + {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, + CX700_52_406M, VX855_52_406M}, + {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, + CX700_52_977M, VX855_52_977M}, + {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, + CX700_56_250M, VX855_56_250M}, + {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, + CX700_60_466M, VX855_60_466M}, + {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, + CX700_61_500M, VX855_61_500M}, + {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, + CX700_65_000M, VX855_65_000M}, + {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, + CX700_65_178M, VX855_65_178M}, + {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, + CX700_66_750M, VX855_66_750M}, + {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, + CX700_68_179M, VX855_68_179M}, + {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, + CX700_69_924M, VX855_69_924M}, + {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, + CX700_70_159M, VX855_70_159M}, + {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, + CX700_72_000M, VX855_72_000M}, + {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, + CX700_78_750M, VX855_78_750M}, + {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, + CX700_80_136M, VX855_80_136M}, + {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, + CX700_83_375M, VX855_83_375M}, + {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, + CX700_83_950M, VX855_83_950M}, + {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, + CX700_84_750M, VX855_84_750M}, + {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, + CX700_85_860M, VX855_85_860M}, + {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, + CX700_88_750M, VX855_88_750M}, + {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, + CX700_94_500M, VX855_94_500M}, + {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, + CX700_97_750M, VX855_97_750M}, {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M, - CX700_101_000M}, + CX700_101_000M, VX855_101_000M}, {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M, - CX700_106_500M}, + CX700_106_500M, VX855_106_500M}, {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M, - CX700_108_000M}, + CX700_108_000M, VX855_108_000M}, {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M, - CX700_113_309M}, + CX700_113_309M, VX855_113_309M}, {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M, - CX700_118_840M}, + CX700_118_840M, VX855_118_840M}, {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M, - CX700_119_000M}, + CX700_119_000M, VX855_119_000M}, {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M, - CX700_121_750M}, + CX700_121_750M, 0}, {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M, - CX700_125_104M}, + CX700_125_104M, 0}, {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M, - CX700_133_308M}, + CX700_133_308M, 0}, {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M, - CX700_135_000M}, + CX700_135_000M, VX855_135_000M}, {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M, - CX700_136_700M}, + CX700_136_700M, VX855_136_700M}, {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M, - CX700_138_400M}, + CX700_138_400M, VX855_138_400M}, {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M, - CX700_146_760M}, + CX700_146_760M, VX855_146_760M}, {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M, - CX700_153_920M}, + CX700_153_920M, VX855_153_920M}, {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M, - CX700_156_000M}, + CX700_156_000M, VX855_156_000M}, {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M, - CX700_157_500M}, + CX700_157_500M, VX855_157_500M}, {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M, - CX700_162_000M}, + CX700_162_000M, VX855_162_000M}, {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M, - CX700_187_000M}, + CX700_187_000M, VX855_187_000M}, {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M, - CX700_193_295M}, + CX700_193_295M, VX855_193_295M}, {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M, - CX700_202_500M}, + CX700_202_500M, VX855_202_500M}, {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M, - CX700_204_000M}, + CX700_204_000M, VX855_204_000M}, {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M, - CX700_218_500M}, + CX700_218_500M, VX855_218_500M}, {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M, - CX700_234_000M}, + CX700_234_000M, VX855_234_000M}, {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M, - CX700_267_250M}, + CX700_267_250M, VX855_267_250M}, {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M, - CX700_297_500M}, - {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, CX700_74_481M}, + CX700_297_500M, VX855_297_500M}, + {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, + CX700_74_481M, VX855_74_481M}, {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M, - CX700_172_798M}, + CX700_172_798M, VX855_172_798M}, {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M, - CX700_122_614M}, - {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, CX700_74_270M}, + CX700_122_614M, VX855_122_614M}, + {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, + CX700_74_270M, 0}, {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M, - CX700_148_500M} + CX700_148_500M, VX855_148_500M} }; static struct fifo_depth_select display_fifo_depth_reg = { @@ -508,7 +526,8 @@ static void set_dvi_output_path(int set_iga, int output_interface); static void set_lcd_output_path(int set_iga, int output_interface); static int search_mode_setting(int ModeInfoIndex); static void load_fix_bit_crtc_reg(void); -static void init_gfx_chip_info(void); +static void init_gfx_chip_info(struct pci_dev *pdev, + const struct pci_device_id *pdi); static void init_tmds_chip_info(void); static void init_lvds_chip_info(void); static void device_screen_off(void); @@ -518,7 +537,6 @@ static void device_off(void); static void device_on(void); static void enable_second_display_channel(void); static void disable_second_display_channel(void); -static int get_fb_size_from_pci(void); void viafb_write_reg(u8 index, u16 io_port, u8 data) { @@ -629,70 +647,43 @@ void viafb_set_iga_path(void) } } -void viafb_set_start_addr(void) +void viafb_set_primary_address(u32 addr) { - unsigned long offset = 0, tmp = 0, size = 0; - unsigned long length; - - DEBUG_MSG(KERN_INFO "viafb_set_start_addr!\n"); - viafb_unlock_crt(); - /* update starting address of IGA1 */ - viafb_write_reg(CR0C, VIACR, 0x00); /*initial starting address */ - viafb_write_reg(CR0D, VIACR, 0x00); - viafb_write_reg(CR34, VIACR, 0x00); - viafb_write_reg_mask(CR48, VIACR, 0x00, 0x1F); - - if (viafb_dual_fb) { - viaparinfo->iga_path = IGA1; - viaparinfo1->iga_path = IGA2; - } - - if (viafb_SAMM_ON == 1) { - if (!viafb_dual_fb) { - if (viafb_second_size) - size = viafb_second_size * 1024 * 1024; - else - size = 8 * 1024 * 1024; - } else { + DEBUG_MSG(KERN_DEBUG "viafb_set_primary_address(0x%08X)\n", addr); + viafb_write_reg(CR0D, VIACR, addr & 0xFF); + viafb_write_reg(CR0C, VIACR, (addr >> 8) & 0xFF); + viafb_write_reg(CR34, VIACR, (addr >> 16) & 0xFF); + viafb_write_reg_mask(CR48, VIACR, (addr >> 24) & 0x1F, 0x1F); +} - size = viaparinfo1->memsize; - } - offset = viafb_second_offset; - DEBUG_MSG(KERN_INFO - "viafb_second_size=%lx, second start_adddress=%lx\n", - size, offset); - } - if (viafb_SAMM_ON == 1) { - offset = offset >> 3; - - tmp = viafb_read_reg(VIACR, 0x62) & 0x01; - tmp |= (offset & 0x7F) << 1; - viafb_write_reg(CR62, VIACR, tmp); - viafb_write_reg(CR63, VIACR, ((offset & 0x7F80) >> 7)); - viafb_write_reg(CR64, VIACR, ((offset & 0x7F8000) >> 15)); - viafb_write_reg(CRA3, VIACR, ((offset & 0x3800000) >> 23)); - } else { - /* update starting address */ - viafb_write_reg(CR62, VIACR, 0x00); - viafb_write_reg(CR63, VIACR, 0x00); - viafb_write_reg(CR64, VIACR, 0x00); - viafb_write_reg(CRA3, VIACR, 0x00); - } +void viafb_set_secondary_address(u32 addr) +{ + DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_address(0x%08X)\n", addr); + /* secondary display supports only quadword aligned memory */ + viafb_write_reg_mask(CR62, VIACR, (addr >> 2) & 0xFE, 0xFE); + viafb_write_reg(CR63, VIACR, (addr >> 10) & 0xFF); + viafb_write_reg(CR64, VIACR, (addr >> 18) & 0xFF); + viafb_write_reg_mask(CRA3, VIACR, (addr >> 26) & 0x07, 0x07); +} - if (viafb_SAMM_ON == 1) { - if (viafb_accel) { - if (!viafb_dual_fb) - length = size - viaparinfo->fbmem_used; - else - length = size - viaparinfo1->fbmem_used; - } else - length = size; - offset = (unsigned long)(void *)viafb_FB_MM + - viafb_second_offset; - memset((void *)offset, 0, length); - } +void viafb_set_primary_pitch(u32 pitch) +{ + DEBUG_MSG(KERN_DEBUG "viafb_set_primary_pitch(0x%08X)\n", pitch); + /* spec does not say that first adapter skips 3 bits but old + * code did it and seems to be reasonable in analogy to 2nd adapter + */ + pitch = pitch >> 3; + viafb_write_reg(0x13, VIACR, pitch & 0xFF); + viafb_write_reg_mask(0x35, VIACR, (pitch >> (8 - 5)) & 0xE0, 0xE0); +} - viafb_lock_crt(); +void viafb_set_secondary_pitch(u32 pitch) +{ + DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_pitch(0x%08X)\n", pitch); + pitch = pitch >> 3; + viafb_write_reg(0x66, VIACR, pitch & 0xFF); + viafb_write_reg_mask(0x67, VIACR, (pitch >> 8) & 0x03, 0x03); + viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80); } void viafb_set_output_path(int device, int set_iga, int output_interface) @@ -1123,30 +1114,6 @@ void viafb_write_regx(struct io_reg RegTable[], int ItemNum) } } -void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga) -{ - int reg_value; - int viafb_load_reg_num; - struct io_register *reg; - - switch (set_iga) { - case IGA1_IGA2: - case IGA1: - reg_value = IGA1_OFFSET_FORMULA(h_addr, bpp_byte); - viafb_load_reg_num = offset_reg.iga1_offset_reg.reg_num; - reg = offset_reg.iga1_offset_reg.reg; - viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); - if (set_iga == IGA1) - break; - case IGA2: - reg_value = IGA2_OFFSET_FORMULA(h_addr, bpp_byte); - viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num; - reg = offset_reg.iga2_offset_reg.reg; - viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); - break; - } -} - void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) { int reg_value; @@ -1277,6 +1244,15 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active) VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; } + if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) { + iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH; + iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD; + iga1_fifo_high_threshold = + VX855_IGA1_FIFO_HIGH_THRESHOLD; + iga1_display_queue_expire_num = + VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; + } + /* Set Display FIFO Depath Select */ reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth); viafb_load_reg_num = @@ -1408,6 +1384,15 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active) VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; } + if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) { + iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH; + iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD; + iga2_fifo_high_threshold = + VX855_IGA2_FIFO_HIGH_THRESHOLD; + iga2_display_queue_expire_num = + VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; + } + if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { /* Set Display FIFO Depath Select */ reg_value = @@ -1496,6 +1481,8 @@ u32 viafb_get_clk_value(int clk) case UNICHROME_P4M900: case UNICHROME_VX800: return pll_value[i].cx700_pll; + case UNICHROME_VX855: + return pll_value[i].vx855_pll; } } } @@ -1529,6 +1516,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) case UNICHROME_P4M890: case UNICHROME_P4M900: case UNICHROME_VX800: + case UNICHROME_VX855: viafb_write_reg(SR44, VIASR, CLK / 0x10000); DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000); viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100); @@ -1557,6 +1545,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) case UNICHROME_P4M890: case UNICHROME_P4M900: case UNICHROME_VX800: + case UNICHROME_VX855: viafb_write_reg(SR4A, VIASR, CLK / 0x10000); viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100); viafb_write_reg(SR4C, VIASR, CLK % 0x100); @@ -1916,7 +1905,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, load_fix_bit_crtc_reg(); viafb_lock_crt(); viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); - viafb_load_offset_reg(h_addr, bpp_byte, set_iga); viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga); /* load FIFO */ @@ -1933,9 +1921,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, } -void viafb_init_chip_info(void) +void viafb_init_chip_info(struct pci_dev *pdev, + const struct pci_device_id *pdi) { - init_gfx_chip_info(); + init_gfx_chip_info(pdev, pdi); init_tmds_chip_info(); init_lvds_chip_info(); @@ -2008,24 +1997,12 @@ void viafb_update_device_setting(int hres, int vres, } } -static void init_gfx_chip_info(void) +static void init_gfx_chip_info(struct pci_dev *pdev, + const struct pci_device_id *pdi) { - struct pci_dev *pdev = NULL; - u32 i; u8 tmp; - /* Indentify GFX Chip Name */ - for (i = 0; pciidlist[i].vendor != 0; i++) { - pdev = pci_get_device(pciidlist[i].vendor, - pciidlist[i].device, 0); - if (pdev) - break; - } - - if (!pciidlist[i].vendor) - return ; - - viaparinfo->chip_info->gfx_chip_name = pciidlist[i].chip_index; + viaparinfo->chip_info->gfx_chip_name = pdi->driver_data; /* Check revision of CLE266 Chip */ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { @@ -2056,8 +2033,6 @@ static void init_gfx_chip_info(void) CX700_REVISION_700; } } - - pci_dev_put(pdev); } static void init_tmds_chip_info(void) @@ -2271,11 +2246,12 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, break; case UNICHROME_CX700: - viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs); - case UNICHROME_VX800: - viafb_write_regx(VX800_ModeXregs, NUM_TOTAL_VX800_ModeXregs); + viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs); + break; + case UNICHROME_VX855: + viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs); break; } @@ -2291,7 +2267,8 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, outb(VPIT.SR[i - 1], VIASR + 1); } - viafb_set_start_addr(); + viafb_set_primary_address(0); + viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); viafb_set_iga_path(); /* Write CRTC */ @@ -2371,6 +2348,9 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, } } + viafb_set_primary_pitch(viafbinfo->fix.line_length); + viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length + : viafbinfo->fix.line_length); /* Update Refresh Rate Setting */ /* Clear On Screen */ @@ -2545,38 +2525,6 @@ void viafb_crt_enable(void) viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4); } -void viafb_get_mmio_info(unsigned long *mmio_base, - unsigned long *mmio_len) -{ - struct pci_dev *pdev = NULL; - u32 vendor, device; - u32 i; - - for (i = 0; pciidlist[i].vendor != 0; i++) - if (viaparinfo->chip_info->gfx_chip_name == - pciidlist[i].chip_index) - break; - - if (!pciidlist[i].vendor) - return ; - - vendor = pciidlist[i].vendor; - device = pciidlist[i].device; - - pdev = pci_get_device(vendor, device, NULL); - - if (!pdev) { - *mmio_base = 0; - *mmio_len = 0; - return ; - } - - *mmio_base = pci_resource_start(pdev, 1); - *mmio_len = pci_resource_len(pdev, 1); - - pci_dev_put(pdev); -} - static void enable_second_display_channel(void) { /* to enable second display channel. */ @@ -2593,44 +2541,7 @@ static void disable_second_display_channel(void) viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); } -void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len) -{ - struct pci_dev *pdev = NULL; - u32 vendor, device; - u32 i; - - for (i = 0; pciidlist[i].vendor != 0; i++) - if (viaparinfo->chip_info->gfx_chip_name == - pciidlist[i].chip_index) - break; - - if (!pciidlist[i].vendor) - return ; - - vendor = pciidlist[i].vendor; - device = pciidlist[i].device; - - pdev = pci_get_device(vendor, device, NULL); - - if (!pdev) { - *fb_base = viafb_read_reg(VIASR, SR30) << 24; - *fb_len = viafb_get_memsize(); - DEBUG_MSG(KERN_INFO "Get FB info from SR30!\n"); - DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base); - DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len); - return ; - } - - *fb_base = (unsigned int)pci_resource_start(pdev, 0); - *fb_len = get_fb_size_from_pci(); - DEBUG_MSG(KERN_INFO "Get FB info from PCI system!\n"); - DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base); - DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len); - - pci_dev_put(pdev); -} - -static int get_fb_size_from_pci(void) +int viafb_get_fb_size_from_pci(void) { unsigned long configid, deviceid, FBSize = 0; int VideoMemSize; @@ -2656,6 +2567,7 @@ static int get_fb_size_from_pci(void) case P4M890_FUNCTION3: case P4M900_FUNCTION3: case VX800_FUNCTION3: + case VX855_FUNCTION3: /*case CN750_FUNCTION3: */ outl(configid + 0xA0, (unsigned long)0xCF8); FBSize = inl((unsigned long)0xCFC); @@ -2719,6 +2631,10 @@ static int get_fb_size_from_pci(void) VideoMemSize = (256 << 20); /*256M */ break; + case 0x00007000: /* Only on VX855/875 */ + VideoMemSize = (512 << 20); /*512M */ + break; + default: VideoMemSize = (32 << 20); /*32M */ break; @@ -2788,24 +2704,6 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ } } -void viafb_memory_pitch_patch(struct fb_info *info) -{ - if (info->var.xres != info->var.xres_virtual) { - viafb_load_offset_reg(info->var.xres_virtual, - info->var.bits_per_pixel >> 3, IGA1); - - if (viafb_SAMM_ON) { - viafb_load_offset_reg(viafb_second_virtual_xres, - viafb_bpp1 >> 3, - IGA2); - } else { - viafb_load_offset_reg(info->var.xres_virtual, - info->var.bits_per_pixel >> 3, IGA2); - } - - } -} - /*According var's xres, yres fill var's other timing information*/ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, int mode_index) diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 6ff38fa8569a..b874d952b446 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -147,14 +147,8 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */ /* location: {CR5F,0,4} */ #define IGA2_VER_SYNC_END_REG_NUM 1 -/* Define Offset and Fetch Count Register*/ +/* Define Fetch Count Register*/ -/* location: {CR13,0,7},{CR35,5,7} */ -#define IGA1_OFFSET_REG_NUM 2 -/* 8 bytes alignment. */ -#define IGA1_OFFSER_ALIGN_BYTE 8 -/* x: H resolution, y: color depth */ -#define IGA1_OFFSET_FORMULA(x, y) ((x*y)/IGA1_OFFSER_ALIGN_BYTE) /* location: {SR1C,0,7},{SR1D,0,1} */ #define IGA1_FETCH_COUNT_REG_NUM 2 /* 16 bytes alignment. */ @@ -164,11 +158,6 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */ #define IGA1_FETCH_COUNT_FORMULA(x, y) \ (((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE) -/* location: {CR66,0,7},{CR67,0,1} */ -#define IGA2_OFFSET_REG_NUM 2 -#define IGA2_OFFSET_ALIGN_BYTE 8 -/* x: H resolution, y: color depth */ -#define IGA2_OFFSET_FORMULA(x, y) ((x*y)/IGA2_OFFSET_ALIGN_BYTE) /* location: {CR65,0,7},{CR67,2,3} */ #define IGA2_FETCH_COUNT_REG_NUM 2 #define IGA2_FETCH_COUNT_ALIGN_BYTE 16 @@ -335,6 +324,17 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */ /* location: {CR94,0,6} */ #define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128 +/* For VT3409 */ +#define VX855_IGA1_FIFO_MAX_DEPTH 400 +#define VX855_IGA1_FIFO_THRESHOLD 320 +#define VX855_IGA1_FIFO_HIGH_THRESHOLD 320 +#define VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 160 + +#define VX855_IGA2_FIFO_MAX_DEPTH 200 +#define VX855_IGA2_FIFO_THRESHOLD 160 +#define VX855_IGA2_FIFO_HIGH_THRESHOLD 160 +#define VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 320 + #define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1 #define IGA1_FIFO_THRESHOLD_REG_NUM 2 #define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2 @@ -617,23 +617,6 @@ struct iga2_ver_sync_end { struct io_register reg[IGA2_VER_SYNC_END_REG_NUM]; }; -/* IGA1 Offset Register */ -struct iga1_offset { - int reg_num; - struct io_register reg[IGA1_OFFSET_REG_NUM]; -}; - -/* IGA2 Offset Register */ -struct iga2_offset { - int reg_num; - struct io_register reg[IGA2_OFFSET_REG_NUM]; -}; - -struct offset { - struct iga1_offset iga1_offset_reg; - struct iga2_offset iga2_offset_reg; -}; - /* IGA1 Fetch Count Register */ struct iga1_fetch_count { int reg_num; @@ -716,6 +699,7 @@ struct pll_map { u32 cle266_pll; u32 k800_pll; u32 cx700_pll; + u32 vx855_pll; }; struct rgbLUT { @@ -860,6 +844,8 @@ struct iga2_crtc_timing { #define P4M900_FUNCTION3 0x3364 /* VT3353 chipset*/ #define VX800_FUNCTION3 0x3353 +/* VT3409 chipset*/ +#define VX855_FUNCTION3 0x3409 #define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value) @@ -883,7 +869,6 @@ extern int viafb_dual_fb; extern int viafb_LCD2_ON; extern int viafb_LCD_ON; extern int viafb_DVI_ON; -extern int viafb_accel; extern int viafb_hotplug; void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); @@ -904,7 +889,6 @@ void viafb_write_reg(u8 index, u16 io_port, u8 data); u8 viafb_read_reg(int io_port, u8 index); void viafb_lock_crt(void); void viafb_unlock_crt(void); -void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga); void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); void viafb_write_regx(struct io_reg RegTable[], int ItemNum); struct VideoModeTable *viafb_get_modetbl_pointer(int Index); @@ -917,17 +901,20 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, int vmode_index1, int hor_res1, int ver_res1, int video_bpp1); -void viafb_init_chip_info(void); +void viafb_init_chip_info(struct pci_dev *pdev, + const struct pci_device_id *pdi); void viafb_init_dac(int set_iga); int viafb_get_pixclock(int hres, int vres, int vmode_refresh); int viafb_get_refresh(int hres, int vres, u32 float_refresh); void viafb_update_device_setting(int hres, int vres, int bpp, int vmode_refresh, int flag); -void viafb_get_mmio_info(unsigned long *mmio_base, - unsigned long *mmio_len); +int viafb_get_fb_size_from_pci(void); void viafb_set_iga_path(void); -void viafb_set_start_addr(void); +void viafb_set_primary_address(u32 addr); +void viafb_set_secondary_address(u32 addr); +void viafb_set_primary_pitch(u32 pitch); +void viafb_set_secondary_pitch(u32 pitch); void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); #endif /* __HW_H__ */ diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h index 842fe30b9868..de899807eade 100644 --- a/drivers/video/via/ioctl.h +++ b/drivers/video/via/ioctl.h @@ -50,8 +50,6 @@ #define VIAFB_GET_GAMMA_LUT 0x56494124 #define VIAFB_SET_GAMMA_LUT 0x56494125 #define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126 -#define VIAFB_SET_VIDEO_DEVICE 0x56494127 -#define VIAFB_GET_VIDEO_DEVICE 0x56494128 #define VIAFB_SET_SECOND_MODE 0x56494129 #define VIAFB_SYNC_SURFACE 0x56494130 #define VIAFB_GET_DRIVER_CAPS 0x56494131 @@ -179,9 +177,7 @@ struct viafb_ioctl_setting { unsigned short second_dev_bpp; /* Indicate which device are primary display device. */ unsigned int primary_device; - /* Indicate which device will show video. only valid in duoview mode */ - unsigned int video_device_status; - unsigned int struct_reserved[34]; + unsigned int struct_reserved[35]; struct viafb_ioctl_lcd_attribute lcd_attributes; }; diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 78c6b3387947..e3e597f937a5 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c @@ -207,13 +207,13 @@ static bool lvds_identify_integratedlvds(void) int viafb_lvds_trasmitter_identify(void) { - viaparinfo->i2c_stuff.i2c_port = I2CPORTINDEX; + viaparinfo->shared->i2c_stuff.i2c_port = I2CPORTINDEX; if (viafb_lvds_identify_vt1636()) { viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX; DEBUG_MSG(KERN_INFO "Found VIA VT1636 LVDS on port i2c 0x31 \n"); } else { - viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX; + viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX; if (viafb_lvds_identify_vt1636()) { viaparinfo->chip_info->lvds_chip_info.i2c_port = GPIOPORTINDEX; @@ -470,7 +470,7 @@ static int lvds_register_read(int index) { u8 data; - viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX; + viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX; viafb_i2c_readbyte((u8) viaparinfo->chip_info-> lvds_chip_info.lvds_chip_slave_addr, (u8) index, &data); @@ -952,13 +952,10 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, int video_index = plvds_setting_info->lcd_panel_size; int set_iga = plvds_setting_info->iga_path; int mode_bpp = plvds_setting_info->bpp; - int viafb_load_reg_num = 0; - int reg_value = 0; int set_hres, set_vres; int panel_hres, panel_vres; u32 pll_D_N; int offset; - struct io_register *reg = NULL; struct display_timing mode_crt_reg, panel_crt_reg; struct crt_mode_table *panel_crt_table = NULL; struct VideoModeTable *vmode_tbl = NULL; @@ -1038,16 +1035,11 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, } /* Offset for simultaneous */ - reg_value = offset; - viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num; - reg = offset_reg.iga2_offset_reg.reg; - viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); + viafb_set_secondary_pitch(offset << 3); DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n"); viafb_load_fetch_count_reg(set_hres, 4, IGA2); /* Fetch count for simultaneous */ } else { /* SAMM */ - /* Offset for IGA2 only */ - viafb_load_offset_reg(set_hres, mode_bpp / 8, set_iga); /* Fetch count for IGA2 only */ viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 2e1254da9c8c..7cd03e2a1275 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -167,6 +167,10 @@ #define SR4B 0x4B #define SR4C 0x4C #define SR52 0x52 +#define SR57 0x57 +#define SR58 0x58 +#define SR59 0x59 +#define SR5D 0x5D #define SR5E 0x5E #define SR65 0x65 @@ -966,6 +970,100 @@ #define CX700_297_500M 0x00CE0403 #define CX700_122_614M 0x00870802 +/* PLL for VX855 */ +#define VX855_22_000M 0x007B1005 +#define VX855_25_175M 0x008D1005 +#define VX855_26_719M 0x00961005 +#define VX855_26_880M 0x00961005 +#define VX855_27_000M 0x00971005 +#define VX855_29_581M 0x00A51005 +#define VX855_29_829M 0x00641003 +#define VX855_31_490M 0x00B01005 +#define VX855_31_500M 0x00B01005 +#define VX855_31_728M 0x008E1004 +#define VX855_32_668M 0x00921004 +#define VX855_36_000M 0x00A11004 +#define VX855_40_000M 0x00700C05 +#define VX855_41_291M 0x00730C05 +#define VX855_43_163M 0x00790C05 +#define VX855_45_250M 0x007F0C05 /* 45.46MHz */ +#define VX855_46_000M 0x00670C04 +#define VX855_46_996M 0x00690C04 +#define VX855_48_000M 0x00860C05 +#define VX855_48_875M 0x00890C05 +#define VX855_49_500M 0x00530C03 +#define VX855_52_406M 0x00580C03 +#define VX855_52_977M 0x00940C05 +#define VX855_56_250M 0x009D0C05 +#define VX855_60_466M 0x00A90C05 +#define VX855_61_500M 0x00AC0C05 +#define VX855_65_000M 0x006D0C03 +#define VX855_65_178M 0x00B60C05 +#define VX855_66_750M 0x00700C03 /*67.116MHz */ +#define VX855_67_295M 0x00BC0C05 +#define VX855_68_179M 0x00BF0C05 +#define VX855_68_369M 0x00BF0C05 +#define VX855_69_924M 0x00C30C05 +#define VX855_70_159M 0x00C30C05 +#define VX855_72_000M 0x00A10C04 +#define VX855_73_023M 0x00CC0C05 +#define VX855_74_481M 0x00D10C05 +#define VX855_78_750M 0x006E0805 +#define VX855_79_466M 0x006F0805 +#define VX855_80_136M 0x00700805 +#define VX855_81_627M 0x00720805 +#define VX855_83_375M 0x00750805 +#define VX855_83_527M 0x00750805 +#define VX855_83_950M 0x00750805 +#define VX855_84_537M 0x00760805 +#define VX855_84_750M 0x00760805 /* 84.537Mhz */ +#define VX855_85_500M 0x00760805 /* 85.909080 MHz*/ +#define VX855_85_860M 0x00760805 +#define VX855_85_909M 0x00760805 +#define VX855_88_750M 0x007C0805 +#define VX855_89_489M 0x007D0805 +#define VX855_94_500M 0x00840805 +#define VX855_96_648M 0x00870805 +#define VX855_97_750M 0x00890805 +#define VX855_101_000M 0x008D0805 +#define VX855_106_500M 0x00950805 +#define VX855_108_000M 0x00970805 +#define VX855_110_125M 0x00990805 +#define VX855_112_000M 0x009D0805 +#define VX855_113_309M 0x009F0805 +#define VX855_115_000M 0x00A10805 +#define VX855_118_840M 0x00A60805 +#define VX855_119_000M 0x00A70805 +#define VX855_121_750M 0x00AA0805 /* 121.704MHz */ +#define VX855_122_614M 0x00AC0805 +#define VX855_126_266M 0x00B10805 +#define VX855_130_250M 0x00B60805 /* 130.250 */ +#define VX855_135_000M 0x00BD0805 +#define VX855_136_700M 0x00BF0805 +#define VX855_137_750M 0x00C10805 +#define VX855_138_400M 0x00C20805 +#define VX855_144_300M 0x00CA0805 +#define VX855_146_760M 0x00CE0805 +#define VX855_148_500M 0x00D00805 +#define VX855_153_920M 0x00540402 +#define VX855_156_000M 0x006C0405 +#define VX855_156_867M 0x006E0405 +#define VX855_157_500M 0x006E0405 +#define VX855_162_000M 0x00710405 +#define VX855_172_798M 0x00790405 +#define VX855_187_000M 0x00830405 +#define VX855_193_295M 0x00870405 +#define VX855_202_500M 0x008E0405 +#define VX855_204_000M 0x008F0405 +#define VX855_218_500M 0x00990405 +#define VX855_229_500M 0x00A10405 +#define VX855_234_000M 0x00A40405 +#define VX855_267_250M 0x00BB0405 +#define VX855_297_500M 0x00D00405 +#define VX855_339_500M 0x00770005 +#define VX855_340_772M 0x00770005 + + /* Definition CRTC Timing Index */ #define H_TOTAL_INDEX 0 #define H_ADDR_INDEX 1 diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index 0f3ed4eb236d..15543e968248 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -97,7 +97,7 @@ int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata) mm1[0] = index; msgs[0].len = 1; msgs[1].len = 1; msgs[0].buf = mm1; msgs[1].buf = pdata; - i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2); + i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2); return 0; } @@ -111,7 +111,7 @@ int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data) msgs.addr = slave_addr / 2; msgs.len = 2; msgs.buf = msg; - return i2c_transfer(&viaparinfo->i2c_stuff.adapter, &msgs, 1); + return i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, &msgs, 1); } int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len) @@ -125,53 +125,53 @@ int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len) mm1[0] = index; msgs[0].len = 1; msgs[1].len = buff_len; msgs[0].buf = mm1; msgs[1].buf = buff; - i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2); + i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2); return 0; } int viafb_create_i2c_bus(void *viapar) { int ret; - struct viafb_par *par = (struct viafb_par *)viapar; - - strcpy(par->i2c_stuff.adapter.name, "via_i2c"); - par->i2c_stuff.i2c_port = 0x0; - par->i2c_stuff.adapter.owner = THIS_MODULE; - par->i2c_stuff.adapter.id = 0x01FFFF; - par->i2c_stuff.adapter.class = 0; - par->i2c_stuff.adapter.algo_data = &par->i2c_stuff.algo; - par->i2c_stuff.adapter.dev.parent = NULL; - par->i2c_stuff.algo.setsda = via_i2c_setsda; - par->i2c_stuff.algo.setscl = via_i2c_setscl; - par->i2c_stuff.algo.getsda = via_i2c_getsda; - par->i2c_stuff.algo.getscl = via_i2c_getscl; - par->i2c_stuff.algo.udelay = 40; - par->i2c_stuff.algo.timeout = 20; - par->i2c_stuff.algo.data = &par->i2c_stuff; - - i2c_set_adapdata(&par->i2c_stuff.adapter, &par->i2c_stuff); + struct via_i2c_stuff *i2c_stuff = + &((struct viafb_par *)viapar)->shared->i2c_stuff; + + strcpy(i2c_stuff->adapter.name, "via_i2c"); + i2c_stuff->i2c_port = 0x0; + i2c_stuff->adapter.owner = THIS_MODULE; + i2c_stuff->adapter.id = 0x01FFFF; + i2c_stuff->adapter.class = 0; + i2c_stuff->adapter.algo_data = &i2c_stuff->algo; + i2c_stuff->adapter.dev.parent = NULL; + i2c_stuff->algo.setsda = via_i2c_setsda; + i2c_stuff->algo.setscl = via_i2c_setscl; + i2c_stuff->algo.getsda = via_i2c_getsda; + i2c_stuff->algo.getscl = via_i2c_getscl; + i2c_stuff->algo.udelay = 40; + i2c_stuff->algo.timeout = 20; + i2c_stuff->algo.data = i2c_stuff; + + i2c_set_adapdata(&i2c_stuff->adapter, i2c_stuff); /* Raise SCL and SDA */ - par->i2c_stuff.i2c_port = I2CPORTINDEX; - via_i2c_setsda(&par->i2c_stuff, 1); - via_i2c_setscl(&par->i2c_stuff, 1); + i2c_stuff->i2c_port = I2CPORTINDEX; + via_i2c_setsda(i2c_stuff, 1); + via_i2c_setscl(i2c_stuff, 1); - par->i2c_stuff.i2c_port = GPIOPORTINDEX; - via_i2c_setsda(&par->i2c_stuff, 1); - via_i2c_setscl(&par->i2c_stuff, 1); + i2c_stuff->i2c_port = GPIOPORTINDEX; + via_i2c_setsda(i2c_stuff, 1); + via_i2c_setscl(i2c_stuff, 1); udelay(20); - ret = i2c_bit_add_bus(&par->i2c_stuff.adapter); + ret = i2c_bit_add_bus(&i2c_stuff->adapter); if (ret == 0) - DEBUG_MSG("I2C bus %s registered.\n", - par->i2c_stuff.adapter.name); + DEBUG_MSG("I2C bus %s registered.\n", i2c_stuff->adapter.name); else DEBUG_MSG("Failed to register I2C bus %s.\n", - par->i2c_stuff.adapter.name); + i2c_stuff->adapter.name); return ret; } void viafb_delete_i2c_buss(void *par) { - i2c_del_adapter(&((struct viafb_par *)par)->i2c_stuff.adapter); + i2c_del_adapter(&((struct viafb_par *)par)->shared->i2c_stuff.adapter); } diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 72833f3334b5..56ec696e8afa 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -20,11 +20,12 @@ */ #include <linux/module.h> +#include <linux/seq_file.h> +#include <linux/stat.h> #define _MASTER_FILE #include "global.h" -static int MAX_CURS = 32; static struct fb_var_screeninfo default_var; static char *viafb_name = "Via"; static u32 pseudo_pal[17]; @@ -33,12 +34,11 @@ static u32 pseudo_pal[17]; static char *viafb_mode = "640x480"; static char *viafb_mode1 = "640x480"; +static int viafb_accel = 1; + /* Added for specifying active devices.*/ char *viafb_active_dev = ""; -/* Added for specifying video on devices.*/ -char *viafb_video_dev = ""; - /*Added for specify lcd output port*/ char *viafb_lcd_port = ""; char *viafb_dvi_port = ""; @@ -50,71 +50,20 @@ static void apply_second_mode_setting(struct fb_var_screeninfo *sec_var); static void retrieve_device_setting(struct viafb_ioctl_setting *setting_info); -static void viafb_set_video_device(u32 video_dev_info); -static void viafb_get_video_device(u32 *video_dev_info); - -/* Mode information */ -static const struct viafb_modeinfo viafb_modentry[] = { - {480, 640, VIA_RES_480X640}, - {640, 480, VIA_RES_640X480}, - {800, 480, VIA_RES_800X480}, - {800, 600, VIA_RES_800X600}, - {1024, 768, VIA_RES_1024X768}, - {1152, 864, VIA_RES_1152X864}, - {1280, 1024, VIA_RES_1280X1024}, - {1600, 1200, VIA_RES_1600X1200}, - {1440, 1050, VIA_RES_1440X1050}, - {1280, 768, VIA_RES_1280X768,}, - {1280, 800, VIA_RES_1280X800}, - {1280, 960, VIA_RES_1280X960}, - {1920, 1440, VIA_RES_1920X1440}, - {848, 480, VIA_RES_848X480}, - {1400, 1050, VIA_RES_1400X1050}, - {720, 480, VIA_RES_720X480}, - {720, 576, VIA_RES_720X576}, - {1024, 512, VIA_RES_1024X512}, - {1024, 576, VIA_RES_1024X576}, - {1024, 600, VIA_RES_1024X600}, - {1280, 720, VIA_RES_1280X720}, - {1920, 1080, VIA_RES_1920X1080}, - {1366, 768, VIA_RES_1368X768}, - {1680, 1050, VIA_RES_1680X1050}, - {960, 600, VIA_RES_960X600}, - {1000, 600, VIA_RES_1000X600}, - {1024, 576, VIA_RES_1024X576}, - {1024, 600, VIA_RES_1024X600}, - {1088, 612, VIA_RES_1088X612}, - {1152, 720, VIA_RES_1152X720}, - {1200, 720, VIA_RES_1200X720}, - {1280, 600, VIA_RES_1280X600}, - {1360, 768, VIA_RES_1360X768}, - {1440, 900, VIA_RES_1440X900}, - {1600, 900, VIA_RES_1600X900}, - {1600, 1024, VIA_RES_1600X1024}, - {1792, 1344, VIA_RES_1792X1344}, - {1856, 1392, VIA_RES_1856X1392}, - {1920, 1200, VIA_RES_1920X1200}, - {2048, 1536, VIA_RES_2048X1536}, - {0, 0, VIA_RES_INVALID} -}; static struct fb_ops viafb_ops; -static int viafb_update_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) -{ - struct viafb_par *ppar; - ppar = info->par; - - DEBUG_MSG(KERN_INFO "viafb_update_fix!\n"); - fix->visual = - ppar->bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - fix->line_length = ppar->linelength; +static void viafb_update_fix(struct fb_info *info) +{ + u32 bpp = info->var.bits_per_pixel; - return 0; + info->fix.visual = + bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + info->fix.line_length = + ((info->var.xres_virtual + 7) & ~7) * bpp / 8; } - static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, struct viafb_par *viaparinfo) { @@ -123,8 +72,6 @@ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, fix->smem_start = viaparinfo->fbmem; fix->smem_len = viaparinfo->fbmem_free; - fix->mmio_start = viaparinfo->mmio_base; - fix->mmio_len = viaparinfo->mmio_len; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; @@ -147,28 +94,12 @@ static int viafb_release(struct fb_info *info, int user) return 0; } -static void viafb_update_viafb_par(struct fb_info *info) -{ - struct viafb_par *ppar; - - ppar = info->par; - ppar->bpp = info->var.bits_per_pixel; - ppar->linelength = ((info->var.xres_virtual + 7) & ~7) * ppar->bpp / 8; - ppar->hres = info->var.xres; - ppar->vres = info->var.yres; - ppar->xoffset = info->var.xoffset; - ppar->yoffset = info->var.yoffset; -} - static int viafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { int vmode_index, htotal, vtotal; - struct viafb_par *ppar; + struct viafb_par *ppar = info->par; u32 long_refresh; - struct viafb_par *p_viafb_par; - ppar = info->par; - DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); /* Sanity check */ @@ -212,23 +143,21 @@ static int viafb_check_var(struct fb_var_screeninfo *var, /* Adjust var according to our driver's own table */ viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); - - /* This is indeed a patch for VT3353 */ - if (!info->par) - return -1; - p_viafb_par = (struct viafb_par *)info->par; - if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800) - var->accel_flags = 0; + if (info->var.accel_flags & FB_ACCELF_TEXT && + !ppar->shared->engine_mmio) + info->var.accel_flags = 0; return 0; } static int viafb_set_par(struct fb_info *info) { + struct viafb_par *viapar = info->par; int vmode_index; int vmode_index1 = 0; DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); + viapar->depth = fb_get_color_depth(&info->var, &info->fix); viafb_update_device_setting(info->var.xres, info->var.yres, info->var.bits_per_pixel, viafb_refresh, 0); @@ -252,21 +181,12 @@ static int viafb_set_par(struct fb_info *info) info->var.bits_per_pixel, vmode_index1, viafb_second_xres, viafb_second_yres, viafb_bpp1); - /*We should set memory offset according virtual_x */ - /*Fix me:put this function into viafb_setmode */ - viafb_memory_pitch_patch(info); - - /* Update ***fb_par information */ - viafb_update_viafb_par(info); - - /* Update other fixed information */ - viafb_update_fix(&info->fix, info); + viafb_update_fix(info); viafb_bpp = info->var.bits_per_pixel; - /* Update viafb_accel, it is necessary to our 2D accelerate */ - viafb_accel = info->var.accel_flags; - - if (viafb_accel) - viafb_set_2d_color_depth(info->var.bits_per_pixel); + if (info->var.accel_flags & FB_ACCELF_TEXT) + info->flags &= ~FBINFO_HWACCEL_DISABLED; + else + info->flags |= FBINFO_HWACCEL_DISABLED; } return 0; @@ -503,12 +423,7 @@ static int viafb_pan_display(struct fb_var_screeninfo *var, var->bits_per_pixel / 16; DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset); - - viafb_write_reg_mask(0x48, 0x3d4, ((offset >> 24) & 0x3), 0x3); - viafb_write_reg_mask(0x34, 0x3d4, ((offset >> 16) & 0xff), 0xff); - viafb_write_reg_mask(0x0c, 0x3d4, ((offset >> 8) & 0xff), 0xff); - viafb_write_reg_mask(0x0d, 0x3d4, (offset & 0xff), 0xff); - + viafb_set_primary_address(offset); return 0; } @@ -560,7 +475,6 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) u32 __user *argp = (u32 __user *) arg; u32 gpu32; - u32 video_dev_info = 0; DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); memset(&u, 0, sizeof(u)); @@ -792,15 +706,6 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) if (put_user(state_info, argp)) return -EFAULT; break; - case VIAFB_SET_VIDEO_DEVICE: - get_user(video_dev_info, argp); - viafb_set_video_device(video_dev_info); - break; - case VIAFB_GET_VIDEO_DEVICE: - viafb_get_video_device(&video_dev_info); - if (put_user(video_dev_info, argp)) - return -EFAULT; - break; case VIAFB_SYNC_SURFACE: DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n"); break; @@ -866,10 +771,12 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) static void viafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - u32 col = 0, rop = 0; - int pitch; + struct viafb_par *viapar = info->par; + struct viafb_shared *shared = viapar->shared; + u32 fg_color; + u8 rop; - if (!viafb_accel) { + if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) { cfb_fillrect(info, rect); return; } @@ -877,68 +784,31 @@ static void viafb_fillrect(struct fb_info *info, if (!rect->width || !rect->height) return; - switch (rect->rop) { - case ROP_XOR: + if (info->fix.visual == FB_VISUAL_TRUECOLOR) + fg_color = ((u32 *)info->pseudo_palette)[rect->color]; + else + fg_color = rect->color; + + if (rect->rop == ROP_XOR) rop = 0x5A; - break; - case ROP_COPY: - default: + else rop = 0xF0; - break; - } - - switch (info->var.bits_per_pixel) { - case 8: - col = rect->color; - break; - case 16: - col = ((u32 *) (info->pseudo_palette))[rect->color]; - break; - case 32: - col = ((u32 *) (info->pseudo_palette))[rect->color]; - break; - } - - /* BitBlt Source Address */ - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); - /* Source Base Address */ - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); - /* Destination Base Address */ - writel(((unsigned long) (info->screen_base) - - (unsigned long) viafb_FB_MM) >> 3, - viaparinfo->io_virt + VIA_REG_DSTBASE); - /* Pitch */ - pitch = (info->var.xres_virtual + 7) & ~7; - writel(VIA_PITCH_ENABLE | - (((pitch * - info->var.bits_per_pixel >> 3) >> 3) | - (((pitch * info-> - var.bits_per_pixel >> 3) >> 3) << 16)), - viaparinfo->io_virt + VIA_REG_PITCH); - /* BitBlt Destination Address */ - writel(((rect->dy << 16) | rect->dx), - viaparinfo->io_virt + VIA_REG_DSTPOS); - /* Dimension: width & height */ - writel((((rect->height - 1) << 16) | (rect->width - 1)), - viaparinfo->io_virt + VIA_REG_DIMENSION); - /* Forground color or Destination color */ - writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR); - /* GE Command */ - writel((0x01 | 0x2000 | (rop << 24)), - viaparinfo->io_virt + VIA_REG_GECMD); + DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n"); + if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_FILL, + rect->width, rect->height, info->var.bits_per_pixel, + viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy, + NULL, 0, 0, 0, 0, fg_color, 0, rop)) + cfb_fillrect(info, rect); } static void viafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { - u32 dy = area->dy, sy = area->sy, direction = 0x0; - u32 sx = area->sx, dx = area->dx, width = area->width; - int pitch; - - DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n"); + struct viafb_par *viapar = info->par; + struct viafb_shared *shared = viapar->shared; - if (!viafb_accel) { + if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) { cfb_copyarea(info, area); return; } @@ -946,263 +816,148 @@ static void viafb_copyarea(struct fb_info *info, if (!area->width || !area->height) return; - if (sy < dy) { - dy += area->height - 1; - sy += area->height - 1; - direction |= 0x4000; - } - - if (sx < dx) { - dx += width - 1; - sx += width - 1; - direction |= 0x8000; - } - - /* Source Base Address */ - writel(((unsigned long) (info->screen_base) - - (unsigned long) viafb_FB_MM) >> 3, - viaparinfo->io_virt + VIA_REG_SRCBASE); - /* Destination Base Address */ - writel(((unsigned long) (info->screen_base) - - (unsigned long) viafb_FB_MM) >> 3, - viaparinfo->io_virt + VIA_REG_DSTBASE); - /* Pitch */ - pitch = (info->var.xres_virtual + 7) & ~7; - /* VIA_PITCH_ENABLE can be omitted now. */ - writel(VIA_PITCH_ENABLE | - (((pitch * - info->var.bits_per_pixel >> 3) >> 3) | (((pitch * - info->var. - bits_per_pixel - >> 3) >> 3) - << 16)), - viaparinfo->io_virt + VIA_REG_PITCH); - /* BitBlt Source Address */ - writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS); - /* BitBlt Destination Address */ - writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS); - /* Dimension: width & height */ - writel((((area->height - 1) << 16) | (area->width - 1)), - viaparinfo->io_virt + VIA_REG_DIMENSION); - /* GE Command */ - writel((0x01 | direction | (0xCC << 24)), - viaparinfo->io_virt + VIA_REG_GECMD); - + DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n"); + if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_COLOR, + area->width, area->height, info->var.bits_per_pixel, + viapar->vram_addr, info->fix.line_length, area->dx, area->dy, + NULL, viapar->vram_addr, info->fix.line_length, + area->sx, area->sy, 0, 0, 0)) + cfb_copyarea(info, area); } static void viafb_imageblit(struct fb_info *info, const struct fb_image *image) { - u32 size, bg_col = 0, fg_col = 0, *udata; - int i; - int pitch; + struct viafb_par *viapar = info->par; + struct viafb_shared *shared = viapar->shared; + u32 fg_color = 0, bg_color = 0; + u8 op; - if (!viafb_accel) { + if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt || + (image->depth != 1 && image->depth != viapar->depth)) { cfb_imageblit(info, image); return; } - udata = (u32 *) image->data; - - switch (info->var.bits_per_pixel) { - case 8: - bg_col = image->bg_color; - fg_col = image->fg_color; - break; - case 16: - bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color]; - fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color]; - break; - case 32: - bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color]; - fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color]; - break; - } - size = image->width * image->height; - - /* Source Base Address */ - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); - /* Destination Base Address */ - writel(((unsigned long) (info->screen_base) - - (unsigned long) viafb_FB_MM) >> 3, - viaparinfo->io_virt + VIA_REG_DSTBASE); - /* Pitch */ - pitch = (info->var.xres_virtual + 7) & ~7; - writel(VIA_PITCH_ENABLE | - (((pitch * - info->var.bits_per_pixel >> 3) >> 3) | (((pitch * - info->var. - bits_per_pixel - >> 3) >> 3) - << 16)), - viaparinfo->io_virt + VIA_REG_PITCH); - /* BitBlt Source Address */ - writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS); - /* BitBlt Destination Address */ - writel(((image->dy << 16) | image->dx), - viaparinfo->io_virt + VIA_REG_DSTPOS); - /* Dimension: width & height */ - writel((((image->height - 1) << 16) | (image->width - 1)), - viaparinfo->io_virt + VIA_REG_DIMENSION); - /* fb color */ - writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR); - /* bg color */ - writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR); - /* GE Command */ - writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD); - - for (i = 0; i < size / 4; i++) { - writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE); - udata++; - } + if (image->depth == 1) { + op = VIA_BITBLT_MONO; + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + fg_color = + ((u32 *)info->pseudo_palette)[image->fg_color]; + bg_color = + ((u32 *)info->pseudo_palette)[image->bg_color]; + } else { + fg_color = image->fg_color; + bg_color = image->bg_color; + } + } else + op = VIA_BITBLT_COLOR; + DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n"); + if (shared->hw_bitblt(shared->engine_mmio, op, + image->width, image->height, info->var.bits_per_pixel, + viapar->vram_addr, info->fix.line_length, image->dx, image->dy, + (u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0)) + cfb_imageblit(info, image); } static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) { - u32 temp, xx, yy, bg_col = 0, fg_col = 0; - int i, j = 0; - static int hw_cursor; - struct viafb_par *p_viafb_par; - - if (viafb_accel) - hw_cursor = 1; - - if (!viafb_accel) { - if (hw_cursor) { - viafb_show_hw_cursor(info, HW_Cursor_OFF); - hw_cursor = 0; - } - return -ENODEV; - } + struct viafb_par *viapar = info->par; + void __iomem *engine = viapar->shared->engine_mmio; + u32 temp, xx, yy, bg_color = 0, fg_color = 0, + chip_name = viapar->shared->chip_info.gfx_chip_name; + int i, j = 0, cur_size = 64; - if ((((struct viafb_par *)(info->par))->iga_path == IGA2) - && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) + if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo) return -ENODEV; - /* When duoview and using lcd , use soft cursor */ - if (viafb_LCD_ON || ((struct viafb_par *)(info->par))->duoview) + if (chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) return -ENODEV; viafb_show_hw_cursor(info, HW_Cursor_OFF); - viacursor = *cursor; if (cursor->set & FB_CUR_SETHOT) { - viacursor.hot = cursor->hot; - temp = ((viacursor.hot.x) << 16) + viacursor.hot.y; - writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_ORG); + temp = (cursor->hot.x << 16) + cursor->hot.y; + writel(temp, engine + VIA_REG_CURSOR_ORG); } if (cursor->set & FB_CUR_SETPOS) { - viacursor.image.dx = cursor->image.dx; - viacursor.image.dy = cursor->image.dy; yy = cursor->image.dy - info->var.yoffset; xx = cursor->image.dx - info->var.xoffset; temp = yy & 0xFFFF; temp |= (xx << 16); - writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_POS); + writel(temp, engine + VIA_REG_CURSOR_POS); } - if (cursor->set & FB_CUR_SETSIZE) { - temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE); + if (cursor->image.width <= 32 && cursor->image.height <= 32) + cur_size = 32; + else if (cursor->image.width <= 64 && cursor->image.height <= 64) + cur_size = 64; + else { + printk(KERN_WARNING "viafb_cursor: The cursor is too large " + "%dx%d", cursor->image.width, cursor->image.height); + return -ENXIO; + } - if ((cursor->image.width <= 32) - && (cursor->image.height <= 32)) { - MAX_CURS = 32; + if (cursor->set & FB_CUR_SETSIZE) { + temp = readl(engine + VIA_REG_CURSOR_MODE); + if (cur_size == 32) temp |= 0x2; - } else if ((cursor->image.width <= 64) - && (cursor->image.height <= 64)) { - MAX_CURS = 64; - temp &= 0xFFFFFFFD; - } else { - DEBUG_MSG(KERN_INFO - "The cursor image is biger than 64x64 bits...\n"); - return -ENXIO; - } - writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE); + else + temp &= ~0x2; - viacursor.image.height = cursor->image.height; - viacursor.image.width = cursor->image.width; + writel(temp, engine + VIA_REG_CURSOR_MODE); } if (cursor->set & FB_CUR_SETCMAP) { - viacursor.image.fg_color = cursor->image.fg_color; - viacursor.image.bg_color = cursor->image.bg_color; - - switch (info->var.bits_per_pixel) { - case 8: - case 16: - case 32: - bg_col = - (0xFF << 24) | - (((info->cmap.red)[viacursor.image.bg_color] & - 0xFF00) << 8) | - ((info->cmap.green)[viacursor.image.bg_color] & - 0xFF00) | - (((info->cmap.blue)[viacursor.image.bg_color] & - 0xFF00) >> 8); - fg_col = - (0xFF << 24) | - (((info->cmap.red)[viacursor.image.fg_color] & - 0xFF00) << 8) | - ((info->cmap.green)[viacursor.image.fg_color] & - 0xFF00) | - (((info->cmap.blue)[viacursor.image.fg_color] & - 0xFF00) >> 8); - break; - default: - return 0; - } - - /* This is indeed a patch for VT3324/VT3353 */ - if (!info->par) - return 0; - p_viafb_par = (struct viafb_par *)info->par; - - if ((p_viafb_par->chip_info->gfx_chip_name == - UNICHROME_CX700) || - ((p_viafb_par->chip_info->gfx_chip_name == - UNICHROME_VX800))) { - bg_col = - (((info->cmap.red)[viacursor.image.bg_color] & - 0xFFC0) << 14) | - (((info->cmap.green)[viacursor.image.bg_color] & - 0xFFC0) << 4) | - (((info->cmap.blue)[viacursor.image.bg_color] & - 0xFFC0) >> 6); - fg_col = - (((info->cmap.red)[viacursor.image.fg_color] & - 0xFFC0) << 14) | - (((info->cmap.green)[viacursor.image.fg_color] & - 0xFFC0) << 4) | - (((info->cmap.blue)[viacursor.image.fg_color] & - 0xFFC0) >> 6); + fg_color = cursor->image.fg_color; + bg_color = cursor->image.bg_color; + if (chip_name == UNICHROME_CX700 || + chip_name == UNICHROME_VX800 || + chip_name == UNICHROME_VX855) { + fg_color = + ((info->cmap.red[fg_color] & 0xFFC0) << 14) | + ((info->cmap.green[fg_color] & 0xFFC0) << 4) | + ((info->cmap.blue[fg_color] & 0xFFC0) >> 6); + bg_color = + ((info->cmap.red[bg_color] & 0xFFC0) << 14) | + ((info->cmap.green[bg_color] & 0xFFC0) << 4) | + ((info->cmap.blue[bg_color] & 0xFFC0) >> 6); + } else { + fg_color = + ((info->cmap.red[fg_color] & 0xFF00) << 8) | + (info->cmap.green[fg_color] & 0xFF00) | + ((info->cmap.blue[fg_color] & 0xFF00) >> 8); + bg_color = + ((info->cmap.red[bg_color] & 0xFF00) << 8) | + (info->cmap.green[bg_color] & 0xFF00) | + ((info->cmap.blue[bg_color] & 0xFF00) >> 8); } - writel(bg_col, viaparinfo->io_virt + VIA_REG_CURSOR_BG); - writel(fg_col, viaparinfo->io_virt + VIA_REG_CURSOR_FG); + writel(bg_color, engine + VIA_REG_CURSOR_BG); + writel(fg_color, engine + VIA_REG_CURSOR_FG); } if (cursor->set & FB_CUR_SETSHAPE) { struct { - u8 data[CURSOR_SIZE / 8]; - u32 bak[CURSOR_SIZE / 32]; + u8 data[CURSOR_SIZE]; + u32 bak[CURSOR_SIZE / 4]; } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC); - int size = - ((viacursor.image.width + 7) >> 3) * - viacursor.image.height; + int size = ((cursor->image.width + 7) >> 3) * + cursor->image.height; - if (cr_data == NULL) - goto out; + if (!cr_data) + return -ENOMEM; - if (MAX_CURS == 32) { - for (i = 0; i < (CURSOR_SIZE / 32); i++) { + if (cur_size == 32) { + for (i = 0; i < (CURSOR_SIZE / 4); i++) { cr_data->bak[i] = 0x0; cr_data->bak[i + 1] = 0xFFFFFFFF; i += 1; } - } else if (MAX_CURS == 64) { - for (i = 0; i < (CURSOR_SIZE / 32); i++) { + } else { + for (i = 0; i < (CURSOR_SIZE / 4); i++) { cr_data->bak[i] = 0x0; cr_data->bak[i + 1] = 0x0; cr_data->bak[i + 2] = 0xFFFFFFFF; @@ -1211,27 +966,27 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) } } - switch (viacursor.rop) { + switch (cursor->rop) { case ROP_XOR: for (i = 0; i < size; i++) - cr_data->data[i] = viacursor.mask[i]; + cr_data->data[i] = cursor->mask[i]; break; case ROP_COPY: for (i = 0; i < size; i++) - cr_data->data[i] = viacursor.mask[i]; + cr_data->data[i] = cursor->mask[i]; break; default: break; } - if (MAX_CURS == 32) { + if (cur_size == 32) { for (i = 0; i < size; i++) { cr_data->bak[j] = (u32) cr_data->data[i]; cr_data->bak[j + 1] = ~cr_data->bak[j]; j += 2; } - } else if (MAX_CURS == 64) { + } else { for (i = 0; i < size; i++) { cr_data->bak[j] = (u32) cr_data->data[i]; cr_data->bak[j + 1] = 0x0; @@ -1241,14 +996,12 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) } } - memcpy(((struct viafb_par *)(info->par))->fbmem_virt + - ((struct viafb_par *)(info->par))->cursor_start, - cr_data->bak, CURSOR_SIZE); -out: + memcpy_toio(viafbinfo->screen_base + viapar->shared-> + cursor_vram_addr, cr_data->bak, CURSOR_SIZE); kfree(cr_data); } - if (viacursor.enable) + if (cursor->enable) viafb_show_hw_cursor(info, HW_Cursor_ON); return 0; @@ -1256,8 +1009,8 @@ out: static int viafb_sync(struct fb_info *info) { - if (viafb_accel) - viafb_wait_engine_idle(); + if (!(info->flags & FBINFO_HWACCEL_DISABLED)) + viafb_wait_engine_idle(info); return 0; } @@ -1266,12 +1019,16 @@ int viafb_get_mode_index(int hres, int vres) u32 i; DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n"); - for (i = 0; viafb_modentry[i].mode_index != VIA_RES_INVALID; i++) - if (viafb_modentry[i].xres == hres && - viafb_modentry[i].yres == vres) + for (i = 0; i < NUM_TOTAL_MODETABLE; i++) + if (CLE266Modes[i].mode_array && + CLE266Modes[i].crtc[0].crtc.hor_addr == hres && + CLE266Modes[i].crtc[0].crtc.ver_addr == vres) break; - return viafb_modentry[i].mode_index; + if (i == NUM_TOTAL_MODETABLE) + return VIA_RES_INVALID; + + return CLE266Modes[i].ModeIndex; } static void check_available_device_to_enable(int device_id) @@ -1375,36 +1132,11 @@ static void viafb_set_device(struct device_t active_dev) viafb_SAMM_ON = active_dev.samm; viafb_primary_dev = active_dev.primary_dev; - viafb_set_start_addr(); + viafb_set_primary_address(0); + viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); viafb_set_iga_path(); } -static void viafb_set_video_device(u32 video_dev_info) -{ - viaparinfo->video_on_crt = STATE_OFF; - viaparinfo->video_on_dvi = STATE_OFF; - viaparinfo->video_on_lcd = STATE_OFF; - - /* Check available device to enable: */ - if ((video_dev_info & CRT_Device) == CRT_Device) - viaparinfo->video_on_crt = STATE_ON; - else if ((video_dev_info & DVI_Device) == DVI_Device) - viaparinfo->video_on_dvi = STATE_ON; - else if ((video_dev_info & LCD_Device) == LCD_Device) - viaparinfo->video_on_lcd = STATE_ON; -} - -static void viafb_get_video_device(u32 *video_dev_info) -{ - *video_dev_info = None_Device; - if (viaparinfo->video_on_crt == STATE_ON) - *video_dev_info |= CRT_Device; - else if (viaparinfo->video_on_dvi == STATE_ON) - *video_dev_info |= DVI_Device; - else if (viaparinfo->video_on_lcd == STATE_ON) - *video_dev_info |= LCD_Device; -} - static int get_primary_device(void) { int primary_device = 0; @@ -1446,18 +1178,6 @@ static int get_primary_device(void) return primary_device; } -static u8 is_duoview(void) -{ - if (0 == viafb_SAMM_ON) { - if (viafb_LCD_ON + viafb_LCD2_ON + - viafb_DVI_ON + viafb_CRT_ON == 2) - return true; - return false; - } else { - return false; - } -} - static void apply_second_mode_setting(struct fb_var_screeninfo *sec_var) { @@ -1559,14 +1279,13 @@ static int apply_device_setting(struct viafb_ioctl_setting setting_info, if (viafb_SAMM_ON) viafb_primary_dev = setting_info.primary_device; - viafb_set_start_addr(); + viafb_set_primary_address(0); + viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); viafb_set_iga_path(); } need_set_mode = 1; } - viaparinfo->duoview = is_duoview(); - if (!need_set_mode) { ; } else { @@ -1589,18 +1308,6 @@ static void retrieve_device_setting(struct viafb_ioctl_setting setting_info->device_status |= LCD_Device; if (viafb_LCD2_ON == 1) setting_info->device_status |= LCD2_Device; - if ((viaparinfo->video_on_crt == 1) && (viafb_CRT_ON == 1)) { - setting_info->video_device_status = - viaparinfo->crt_setting_info->iga_path; - } else if ((viaparinfo->video_on_dvi == 1) && (viafb_DVI_ON == 1)) { - setting_info->video_device_status = - viaparinfo->tmds_setting_info->iga_path; - } else if ((viaparinfo->video_on_lcd == 1) && (viafb_LCD_ON == 1)) { - setting_info->video_device_status = - viaparinfo->lvds_setting_info->iga_path; - } else { - setting_info->video_device_status = 0; - } setting_info->samm_status = viafb_SAMM_ON; setting_info->primary_device = get_primary_device(); @@ -1687,25 +1394,6 @@ static void parse_active_dev(void) viafb_CRT_ON = STATE_ON; viafb_SAMM_ON = STATE_OFF; } - viaparinfo->duoview = is_duoview(); -} - -static void parse_video_dev(void) -{ - viaparinfo->video_on_crt = STATE_OFF; - viaparinfo->video_on_dvi = STATE_OFF; - viaparinfo->video_on_lcd = STATE_OFF; - - if (!strncmp(viafb_video_dev, "CRT", 3)) { - /* Video on CRT */ - viaparinfo->video_on_crt = STATE_ON; - } else if (!strncmp(viafb_video_dev, "DVI", 3)) { - /* Video on DVI */ - viaparinfo->video_on_dvi = STATE_ON; - } else if (!strncmp(viafb_video_dev, "LCD", 3)) { - /* Video on LCD */ - viaparinfo->video_on_lcd = STATE_ON; - } } static int parse_port(char *opt_str, int *output_interface) @@ -1754,10 +1442,8 @@ static void parse_dvi_port(void) * DVP1Driving, DFPHigh, DFPLow CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], * CR9B, SR65, CR97, CR99 */ -static int viafb_dvp0_proc_read(char *buf, char **start, off_t offset, -int count, int *eof, void *data) +static int viafb_dvp0_proc_show(struct seq_file *m, void *v) { - int len = 0; u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0; dvp0_data_dri = (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 | @@ -1766,13 +1452,17 @@ int count, int *eof, void *data) (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 | (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2; dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f; - len += - sprintf(buf + len, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri); - *eof = 1; /*Inform kernel end of data */ - return len; + seq_printf(m, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri); + return 0; } -static int viafb_dvp0_proc_write(struct file *file, - const char __user *buffer, unsigned long count, void *data) + +static int viafb_dvp0_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, viafb_dvp0_proc_show, NULL); +} + +static ssize_t viafb_dvp0_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { char buf[20], *value, *pbuf; u8 reg_val = 0; @@ -1816,21 +1506,33 @@ static int viafb_dvp0_proc_write(struct file *file, } return count; } -static int viafb_dvp1_proc_read(char *buf, char **start, off_t offset, - int count, int *eof, void *data) + +static const struct file_operations viafb_dvp0_proc_fops = { + .owner = THIS_MODULE, + .open = viafb_dvp0_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = viafb_dvp0_proc_write, +}; + +static int viafb_dvp1_proc_show(struct seq_file *m, void *v) { - int len = 0; u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0; dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f; dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2; dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03; - len += - sprintf(buf + len, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri); - *eof = 1; /*Inform kernel end of data */ - return len; + seq_printf(m, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri); + return 0; } -static int viafb_dvp1_proc_write(struct file *file, - const char __user *buffer, unsigned long count, void *data) + +static int viafb_dvp1_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, viafb_dvp1_proc_show, NULL); +} + +static ssize_t viafb_dvp1_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { char buf[20], *value, *pbuf; u8 reg_val = 0; @@ -1869,18 +1571,30 @@ static int viafb_dvp1_proc_write(struct file *file, return count; } -static int viafb_dfph_proc_read(char *buf, char **start, off_t offset, - int count, int *eof, void *data) +static const struct file_operations viafb_dvp1_proc_fops = { + .owner = THIS_MODULE, + .open = viafb_dvp1_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = viafb_dvp1_proc_write, +}; + +static int viafb_dfph_proc_show(struct seq_file *m, void *v) { - int len = 0; u8 dfp_high = 0; dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f; - len += sprintf(buf + len, "%x\n", dfp_high); - *eof = 1; /*Inform kernel end of data */ - return len; + seq_printf(m, "%x\n", dfp_high); + return 0; } -static int viafb_dfph_proc_write(struct file *file, - const char __user *buffer, unsigned long count, void *data) + +static int viafb_dfph_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, viafb_dfph_proc_show, NULL); +} + +static ssize_t viafb_dfph_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { char buf[20]; u8 reg_val = 0; @@ -1895,18 +1609,31 @@ static int viafb_dfph_proc_write(struct file *file, viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); return count; } -static int viafb_dfpl_proc_read(char *buf, char **start, off_t offset, - int count, int *eof, void *data) + +static const struct file_operations viafb_dfph_proc_fops = { + .owner = THIS_MODULE, + .open = viafb_dfph_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = viafb_dfph_proc_write, +}; + +static int viafb_dfpl_proc_show(struct seq_file *m, void *v) { - int len = 0; u8 dfp_low = 0; dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f; - len += sprintf(buf + len, "%x\n", dfp_low); - *eof = 1; /*Inform kernel end of data */ - return len; + seq_printf(m, "%x\n", dfp_low); + return 0; } -static int viafb_dfpl_proc_write(struct file *file, - const char __user *buffer, unsigned long count, void *data) + +static int viafb_dfpl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, viafb_dfpl_proc_show, NULL); +} + +static ssize_t viafb_dfpl_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { char buf[20]; u8 reg_val = 0; @@ -1921,10 +1648,18 @@ static int viafb_dfpl_proc_write(struct file *file, viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); return count; } -static int viafb_vt1636_proc_read(char *buf, char **start, - off_t offset, int count, int *eof, void *data) + +static const struct file_operations viafb_dfpl_proc_fops = { + .owner = THIS_MODULE, + .open = viafb_dfpl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = viafb_dfpl_proc_write, +}; + +static int viafb_vt1636_proc_show(struct seq_file *m, void *v) { - int len = 0; u8 vt1636_08 = 0, vt1636_09 = 0; switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { case VT1636_LVDS: @@ -1934,7 +1669,7 @@ static int viafb_vt1636_proc_read(char *buf, char **start, vt1636_09 = viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info, &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f; - len += sprintf(buf + len, "%x %x\n", vt1636_08, vt1636_09); + seq_printf(m, "%x %x\n", vt1636_08, vt1636_09); break; default: break; @@ -1947,16 +1682,21 @@ static int viafb_vt1636_proc_read(char *buf, char **start, vt1636_09 = viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2, &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f; - len += sprintf(buf + len, " %x %x\n", vt1636_08, vt1636_09); + seq_printf(m, " %x %x\n", vt1636_08, vt1636_09); break; default: break; } - *eof = 1; /*Inform kernel end of data */ - return len; + return 0; } -static int viafb_vt1636_proc_write(struct file *file, - const char __user *buffer, unsigned long count, void *data) + +static int viafb_vt1636_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, viafb_vt1636_proc_show, NULL); +} + +static ssize_t viafb_vt1636_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { char buf[30], *value, *pbuf; struct IODATA reg_val; @@ -2045,39 +1785,27 @@ static int viafb_vt1636_proc_write(struct file *file, return count; } +static const struct file_operations viafb_vt1636_proc_fops = { + .owner = THIS_MODULE, + .open = viafb_vt1636_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = viafb_vt1636_proc_write, +}; + static void viafb_init_proc(struct proc_dir_entry **viafb_entry) { - struct proc_dir_entry *entry; *viafb_entry = proc_mkdir("viafb", NULL); if (viafb_entry) { - entry = create_proc_entry("dvp0", 0, *viafb_entry); - if (entry) { - entry->read_proc = viafb_dvp0_proc_read; - entry->write_proc = viafb_dvp0_proc_write; - } - entry = create_proc_entry("dvp1", 0, *viafb_entry); - if (entry) { - entry->read_proc = viafb_dvp1_proc_read; - entry->write_proc = viafb_dvp1_proc_write; - } - entry = create_proc_entry("dfph", 0, *viafb_entry); - if (entry) { - entry->read_proc = viafb_dfph_proc_read; - entry->write_proc = viafb_dfph_proc_write; - } - entry = create_proc_entry("dfpl", 0, *viafb_entry); - if (entry) { - entry->read_proc = viafb_dfpl_proc_read; - entry->write_proc = viafb_dfpl_proc_write; - } + proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops); + proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops); + proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops); + proc_create("dfpl", 0, *viafb_entry, &viafb_dfpl_proc_fops); if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info. lvds_chip_name || VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { - entry = create_proc_entry("vt1636", 0, *viafb_entry); - if (entry) { - entry->read_proc = viafb_vt1636_proc_read; - entry->write_proc = viafb_vt1636_proc_write; - } + proc_create("vt1636", 0, *viafb_entry, &viafb_vt1636_proc_fops); } } @@ -2094,51 +1822,61 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) remove_proc_entry("viafb", NULL); } -static int __devinit via_pci_probe(void) +static void parse_mode(const char *str, u32 *xres, u32 *yres) { - unsigned long default_xres, default_yres; - char *tmpc, *tmpm; - char *tmpc_sec, *tmpm_sec; + char *ptr; + + *xres = simple_strtoul(str, &ptr, 10); + if (ptr[0] != 'x') + goto out_default; + + *yres = simple_strtoul(&ptr[1], &ptr, 10); + if (ptr[0]) + goto out_default; + + return; + +out_default: + printk(KERN_WARNING "viafb received invalid mode string: %s\n", str); + *xres = 640; + *yres = 480; +} + +static int __devinit via_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + u32 default_xres, default_yres; int vmode_index; - u32 tmds_length, lvds_length, crt_length, chip_length, viafb_par_length; + u32 viafb_par_length; DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); - tmds_length = ALIGN(sizeof(struct tmds_setting_information), - BITS_PER_LONG/8); - lvds_length = ALIGN(sizeof(struct lvds_setting_information), - BITS_PER_LONG/8); - crt_length = ALIGN(sizeof(struct lvds_setting_information), - BITS_PER_LONG/8); - chip_length = ALIGN(sizeof(struct chip_information), BITS_PER_LONG/8); /* Allocate fb_info and ***_par here, also including some other needed * variables */ - viafbinfo = framebuffer_alloc(viafb_par_length + 2 * lvds_length + - tmds_length + crt_length + chip_length, NULL); + viafbinfo = framebuffer_alloc(viafb_par_length + + ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8), + &pdev->dev); if (!viafbinfo) { printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); return -ENODEV; } viaparinfo = (struct viafb_par *)viafbinfo->par; - viaparinfo->tmds_setting_info = (struct tmds_setting_information *) - ((unsigned long)viaparinfo + viafb_par_length); - viaparinfo->lvds_setting_info = (struct lvds_setting_information *) - ((unsigned long)viaparinfo->tmds_setting_info + tmds_length); - viaparinfo->lvds_setting_info2 = (struct lvds_setting_information *) - ((unsigned long)viaparinfo->lvds_setting_info + lvds_length); - viaparinfo->crt_setting_info = (struct crt_setting_information *) - ((unsigned long)viaparinfo->lvds_setting_info2 + lvds_length); - viaparinfo->chip_info = (struct chip_information *) - ((unsigned long)viaparinfo->crt_setting_info + crt_length); + viaparinfo->shared = viafbinfo->par + viafb_par_length; + viaparinfo->vram_addr = 0; + viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info; + viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info; + viaparinfo->lvds_setting_info2 = + &viaparinfo->shared->lvds_setting_info2; + viaparinfo->crt_setting_info = &viaparinfo->shared->crt_setting_info; + viaparinfo->chip_info = &viaparinfo->shared->chip_info; if (viafb_dual_fb) viafb_SAMM_ON = 1; parse_active_dev(); - parse_video_dev(); parse_lcd_port(); parse_dvi_port(); @@ -2149,32 +1887,32 @@ static int __devinit via_pci_probe(void) /* Set up I2C bus stuff */ viafb_create_i2c_bus(viaparinfo); - viafb_init_chip_info(); - viafb_get_fb_info(&viaparinfo->fbmem, &viaparinfo->memsize); + viafb_init_chip_info(pdev, ent); + viaparinfo->fbmem = pci_resource_start(pdev, 0); + viaparinfo->memsize = viafb_get_fb_size_from_pci(); viaparinfo->fbmem_free = viaparinfo->memsize; viaparinfo->fbmem_used = 0; - viaparinfo->fbmem_virt = ioremap_nocache(viaparinfo->fbmem, + viafbinfo->screen_base = ioremap_nocache(viaparinfo->fbmem, viaparinfo->memsize); - viafbinfo->screen_base = (char *)viaparinfo->fbmem_virt; - - if (!viaparinfo->fbmem_virt) { + if (!viafbinfo->screen_base) { printk(KERN_INFO "ioremap failed\n"); - return -1; + return -ENOMEM; } - viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len); - viaparinfo->io_virt = ioremap_nocache(viaparinfo->mmio_base, - viaparinfo->mmio_len); - + viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1); + viafbinfo->fix.mmio_len = pci_resource_len(pdev, 1); viafbinfo->node = 0; viafbinfo->fbops = &viafb_ops; viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; viafbinfo->pseudo_palette = pseudo_pal; - if (viafb_accel) { - viafb_init_accel(); - viafb_init_2d_engine(); - viafb_hw_cursor_init(); + if (viafb_accel && !viafb_init_engine(viafbinfo)) { + viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA | + FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; + default_var.accel_flags = FB_ACCELF_TEXT; + } else { + viafbinfo->flags |= FBINFO_HWACCEL_DISABLED; + default_var.accel_flags = 0; } if (viafb_second_size && (viafb_second_size < 8)) { @@ -2186,27 +1924,14 @@ static int __devinit via_pci_probe(void) viafb_second_size * 1024 * 1024; } - viafb_FB_MM = viaparinfo->fbmem_virt; - tmpm = viafb_mode; - tmpc = strsep(&tmpm, "x"); - strict_strtoul(tmpc, 0, &default_xres); - strict_strtoul(tmpm, 0, &default_yres); - + parse_mode(viafb_mode, &default_xres, &default_yres); vmode_index = viafb_get_mode_index(default_xres, default_yres); DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index); if (viafb_SAMM_ON == 1) { - if (strcmp(viafb_mode, viafb_mode1)) { - tmpm_sec = viafb_mode1; - tmpc_sec = strsep(&tmpm_sec, "x"); - strict_strtoul(tmpc_sec, 0, - (unsigned long *)&viafb_second_xres); - strict_strtoul(tmpm_sec, 0, - (unsigned long *)&viafb_second_yres); - } else { - viafb_second_xres = default_xres; - viafb_second_yres = default_yres; - } + parse_mode(viafb_mode1, &viafb_second_xres, + &viafb_second_yres); + if (0 == viafb_second_virtual_xres) { switch (viafb_second_xres) { case 1400: @@ -2256,18 +1981,9 @@ static int __devinit via_pci_probe(void) default_var.lower_margin = 4; default_var.hsync_len = default_var.left_margin; default_var.vsync_len = 4; - default_var.accel_flags = 0; - - if (viafb_accel) { - viafbinfo->flags |= - (FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | - FBINFO_HWACCEL_IMAGEBLIT); - default_var.accel_flags |= FB_ACCELF_TEXT; - } else - viafbinfo->flags |= FBINFO_HWACCEL_DISABLED; if (viafb_dual_fb) { - viafbinfo1 = framebuffer_alloc(viafb_par_length, NULL); + viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev); if (!viafbinfo1) { printk(KERN_ERR "allocate the second framebuffer struct error\n"); @@ -2276,11 +1992,10 @@ static int __devinit via_pci_probe(void) } viaparinfo1 = viafbinfo1->par; memcpy(viaparinfo1, viaparinfo, viafb_par_length); + viaparinfo1->vram_addr = viafb_second_offset; viaparinfo1->memsize = viaparinfo->memsize - viafb_second_offset; viaparinfo->memsize = viafb_second_offset; - viaparinfo1->fbmem_virt = viaparinfo->fbmem_virt + - viafb_second_offset; viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset; viaparinfo1->fbmem_used = viaparinfo->fbmem_used; @@ -2288,20 +2003,13 @@ static int __devinit via_pci_probe(void) viaparinfo1->fbmem_used; viaparinfo->fbmem_free = viaparinfo->memsize; viaparinfo->fbmem_used = 0; - if (viafb_accel) { - viaparinfo1->cursor_start = - viaparinfo->cursor_start - viafb_second_offset; - viaparinfo1->VQ_start = viaparinfo->VQ_start - - viafb_second_offset; - viaparinfo1->VQ_end = viaparinfo->VQ_end - - viafb_second_offset; - } + viaparinfo->iga_path = IGA1; + viaparinfo1->iga_path = IGA2; memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info)); + viafbinfo1->par = viaparinfo1; viafbinfo1->screen_base = viafbinfo->screen_base + viafb_second_offset; - viafbinfo1->fix.smem_start = viaparinfo1->fbmem; - viafbinfo1->fix.smem_len = viaparinfo1->fbmem_free; default_var.xres = viafb_second_xres; default_var.yres = viafb_second_yres; @@ -2323,15 +2031,17 @@ static int __devinit via_pci_probe(void) viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); viafb_check_var(&default_var, viafbinfo1); viafbinfo1->var = default_var; - viafb_update_viafb_par(viafbinfo); - viafb_update_fix(&viafbinfo1->fix, viafbinfo1); + viafb_update_fix(viafbinfo1); + viaparinfo1->depth = fb_get_color_depth(&viafbinfo1->var, + &viafbinfo1->fix); } viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); viafb_check_var(&default_var, viafbinfo); viafbinfo->var = default_var; - viafb_update_viafb_par(viafbinfo); - viafb_update_fix(&viafbinfo->fix, viafbinfo); + viafb_update_fix(viafbinfo); + viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, + &viafbinfo->fix); default_var.activate = FB_ACTIVATE_NOW; fb_alloc_cmap(&viafbinfo->cmap, 256, 0); @@ -2353,20 +2063,20 @@ static int __devinit via_pci_probe(void) viafbinfo->node, viafbinfo->fix.id, default_var.xres, default_var.yres, default_var.bits_per_pixel); - viafb_init_proc(&viaparinfo->proc_entry); + viafb_init_proc(&viaparinfo->shared->proc_entry); viafb_init_dac(IGA2); return 0; } -static void __devexit via_pci_remove(void) +static void __devexit via_pci_remove(struct pci_dev *pdev) { DEBUG_MSG(KERN_INFO "via_pci_remove!\n"); fb_dealloc_cmap(&viafbinfo->cmap); unregister_framebuffer(viafbinfo); if (viafb_dual_fb) unregister_framebuffer(viafbinfo1); - iounmap((void *)viaparinfo->fbmem_virt); - iounmap(viaparinfo->io_virt); + iounmap((void *)viafbinfo->screen_base); + iounmap(viaparinfo->shared->engine_mmio); viafb_delete_i2c_buss(viaparinfo); @@ -2374,7 +2084,7 @@ static void __devexit via_pci_remove(void) if (viafb_dual_fb) framebuffer_release(viafbinfo1); - viafb_remove_proc(viaparinfo->proc_entry); + viafb_remove_proc(viaparinfo->shared->proc_entry); } #ifndef MODULE @@ -2441,8 +2151,6 @@ static int __init viafb_setup(char *options) else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) strict_strtoul(this_opt + 15, 0, (unsigned long *)&viafb_lcd_mode); - else if (!strncmp(this_opt, "viafb_video_dev=", 16)) - viafb_video_dev = kstrdup(this_opt + 16, GFP_KERNEL); else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL); else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) @@ -2452,6 +2160,40 @@ static int __init viafb_setup(char *options) } #endif +static struct pci_device_id viafb_pci_table[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID), + .driver_data = UNICHROME_CLE266 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID), + .driver_data = UNICHROME_PM800 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID), + .driver_data = UNICHROME_K400 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID), + .driver_data = UNICHROME_K800 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID), + .driver_data = UNICHROME_CN700 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID), + .driver_data = UNICHROME_K8M890 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID), + .driver_data = UNICHROME_CX700 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID), + .driver_data = UNICHROME_P4M900 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID), + .driver_data = UNICHROME_CN750 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID), + .driver_data = UNICHROME_VX800 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), + .driver_data = UNICHROME_VX855 }, + { } +}; +MODULE_DEVICE_TABLE(pci, viafb_pci_table); + +static struct pci_driver viafb_driver = { + .name = "viafb", + .id_table = viafb_pci_table, + .probe = via_pci_probe, + .remove = __devexit_p(via_pci_remove), +}; + static int __init viafb_init(void) { #ifndef MODULE @@ -2463,13 +2205,13 @@ static int __init viafb_init(void) printk(KERN_INFO "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", VERSION_MAJOR, VERSION_MINOR); - return via_pci_probe(); + return pci_register_driver(&viafb_driver); } static void __exit viafb_exit(void) { DEBUG_MSG(KERN_INFO "viafb_exit!\n"); - via_pci_remove(); + pci_unregister_driver(&viafb_driver); } static struct fb_ops viafb_ops = { @@ -2494,82 +2236,79 @@ module_init(viafb_init); module_exit(viafb_exit); #ifdef MODULE -module_param(viafb_memsize, int, 0); +module_param(viafb_memsize, int, S_IRUSR); -module_param(viafb_mode, charp, 0); +module_param(viafb_mode, charp, S_IRUSR); MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); -module_param(viafb_mode1, charp, 0); +module_param(viafb_mode1, charp, S_IRUSR); MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)"); -module_param(viafb_bpp, int, 0); +module_param(viafb_bpp, int, S_IRUSR); MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)"); -module_param(viafb_bpp1, int, 0); +module_param(viafb_bpp1, int, S_IRUSR); MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)"); -module_param(viafb_refresh, int, 0); +module_param(viafb_refresh, int, S_IRUSR); MODULE_PARM_DESC(viafb_refresh, "Set CRT viafb_refresh rate (default = 60)"); -module_param(viafb_refresh1, int, 0); +module_param(viafb_refresh1, int, S_IRUSR); MODULE_PARM_DESC(viafb_refresh1, "Set CRT refresh rate (default = 60)"); -module_param(viafb_lcd_panel_id, int, 0); +module_param(viafb_lcd_panel_id, int, S_IRUSR); MODULE_PARM_DESC(viafb_lcd_panel_id, "Set Flat Panel type(Default=1024x768)"); -module_param(viafb_lcd_dsp_method, int, 0); +module_param(viafb_lcd_dsp_method, int, S_IRUSR); MODULE_PARM_DESC(viafb_lcd_dsp_method, "Set Flat Panel display scaling method.(Default=Expandsion)"); -module_param(viafb_SAMM_ON, int, 0); +module_param(viafb_SAMM_ON, int, S_IRUSR); MODULE_PARM_DESC(viafb_SAMM_ON, "Turn on/off flag of SAMM(Default=OFF)"); -module_param(viafb_accel, int, 0); +module_param(viafb_accel, int, S_IRUSR); MODULE_PARM_DESC(viafb_accel, - "Set 2D Hardware Acceleration.(Default = OFF)"); + "Set 2D Hardware Acceleration: 0 = OFF, 1 = ON (default)"); -module_param(viafb_active_dev, charp, 0); +module_param(viafb_active_dev, charp, S_IRUSR); MODULE_PARM_DESC(viafb_active_dev, "Specify active devices."); -module_param(viafb_display_hardware_layout, int, 0); +module_param(viafb_display_hardware_layout, int, S_IRUSR); MODULE_PARM_DESC(viafb_display_hardware_layout, "Display Hardware Layout (LCD Only, DVI Only...,etc)"); -module_param(viafb_second_size, int, 0); +module_param(viafb_second_size, int, S_IRUSR); MODULE_PARM_DESC(viafb_second_size, "Set secondary device memory size"); -module_param(viafb_dual_fb, int, 0); +module_param(viafb_dual_fb, int, S_IRUSR); MODULE_PARM_DESC(viafb_dual_fb, "Turn on/off flag of dual framebuffer devices.(Default = OFF)"); -module_param(viafb_platform_epia_dvi, int, 0); +module_param(viafb_platform_epia_dvi, int, S_IRUSR); MODULE_PARM_DESC(viafb_platform_epia_dvi, "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)"); -module_param(viafb_device_lcd_dualedge, int, 0); +module_param(viafb_device_lcd_dualedge, int, S_IRUSR); MODULE_PARM_DESC(viafb_device_lcd_dualedge, "Turn on/off flag of dual edge panel.(Default = OFF)"); -module_param(viafb_bus_width, int, 0); +module_param(viafb_bus_width, int, S_IRUSR); MODULE_PARM_DESC(viafb_bus_width, "Set bus width of panel.(Default = 12)"); -module_param(viafb_lcd_mode, int, 0); +module_param(viafb_lcd_mode, int, S_IRUSR); MODULE_PARM_DESC(viafb_lcd_mode, "Set Flat Panel mode(Default=OPENLDI)"); -module_param(viafb_video_dev, charp, 0); -MODULE_PARM_DESC(viafb_video_dev, "Specify video devices."); - -module_param(viafb_lcd_port, charp, 0); +module_param(viafb_lcd_port, charp, S_IRUSR); MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port."); -module_param(viafb_dvi_port, charp, 0); +module_param(viafb_dvi_port, charp, S_IRUSR); MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port."); MODULE_LICENSE("GPL"); diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index 227b000feb38..0c94d2441922 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h @@ -37,51 +37,50 @@ #define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */ #define VERSION_MINOR 4 +struct viafb_shared { + struct proc_dir_entry *proc_entry; /*viafb proc entry */ + + /* I2C stuff */ + struct via_i2c_stuff i2c_stuff; + + /* All the information will be needed to set engine */ + struct tmds_setting_information tmds_setting_info; + struct crt_setting_information crt_setting_info; + struct lvds_setting_information lvds_setting_info; + struct lvds_setting_information lvds_setting_info2; + struct chip_information chip_info; + + /* hardware acceleration stuff */ + void __iomem *engine_mmio; + u32 cursor_vram_addr; + u32 vq_vram_addr; /* virtual queue address in video ram */ + int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height, + u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, + u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, + u32 fg_color, u32 bg_color, u8 fill_rop); +}; + struct viafb_par { - int bpp; - int hres; - int vres; - int linelength; - u32 xoffset; - u32 yoffset; - - void __iomem *fbmem_virt; /*framebuffer virtual memory address */ - void __iomem *io_virt; /*iospace virtual memory address */ + u8 depth; + u32 vram_addr; + unsigned int fbmem; /*framebuffer physical memory address */ unsigned int memsize; /*size of fbmem */ - unsigned int io; /*io space address */ - unsigned long mmio_base; /*mmio base address */ - unsigned long mmio_len; /*mmio base length */ u32 fbmem_free; /* Free FB memory */ u32 fbmem_used; /* Use FB memory size */ - u32 cursor_start; /* Cursor Start Address */ - u32 VQ_start; /* Virtual Queue Start Address */ - u32 VQ_end; /* Virtual Queue End Address */ u32 iga_path; - struct proc_dir_entry *proc_entry; /*viafb proc entry */ - u8 duoview; /*Is working in duoview mode? */ - /* I2C stuff */ - struct via_i2c_stuff i2c_stuff; + struct viafb_shared *shared; /* All the information will be needed to set engine */ + /* depreciated, use the ones in shared directly */ struct tmds_setting_information *tmds_setting_info; struct crt_setting_information *crt_setting_info; struct lvds_setting_information *lvds_setting_info; struct lvds_setting_information *lvds_setting_info2; struct chip_information *chip_info; - - /* some information related to video playing */ - int video_on_crt; - int video_on_dvi; - int video_on_lcd; - -}; -struct viafb_modeinfo { - u32 xres; - u32 yres; - int mode_index; }; + extern unsigned int viafb_second_virtual_yres; extern unsigned int viafb_second_virtual_xres; extern unsigned int viafb_second_offset; @@ -91,14 +90,12 @@ extern int viafb_dual_fb; extern int viafb_LCD2_ON; extern int viafb_LCD_ON; extern int viafb_DVI_ON; -extern int viafb_accel; extern int viafb_hotplug; extern int viafb_memsize; extern int strict_strtoul(const char *cp, unsigned int base, unsigned long *res); -void viafb_memory_pitch_patch(struct fb_info *info); void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, int mode_index); int viafb_get_mode_index(int hres, int vres); diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index 6dcf583a837d..b74f8a67923c 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c @@ -100,12 +100,8 @@ struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ {VIACR, CR32, 0xFF, 0x00}, {VIACR, CR33, 0xFF, 0x00}, -{VIACR, CR34, 0xFF, 0x00}, {VIACR, CR35, 0xFF, 0x00}, {VIACR, CR36, 0x08, 0x00}, -{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ {VIACR, CR69, 0xFF, 0x00}, {VIACR, CR6A, 0xFF, 0x40}, {VIACR, CR6B, 0xFF, 0x00}, @@ -159,16 +155,12 @@ struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, {VIASR, CR30, 0xFF, 0x04}, {VIACR, CR32, 0xFF, 0x00}, {VIACR, CR33, 0x7F, 0x00}, -{VIACR, CR34, 0xFF, 0x00}, {VIACR, CR35, 0xFF, 0x00}, {VIACR, CR36, 0xFF, 0x31}, {VIACR, CR41, 0xFF, 0x80}, {VIACR, CR42, 0xFF, 0x00}, {VIACR, CR55, 0x80, 0x00}, {VIACR, CR5D, 0x80, 0x00}, /*Horizontal Retrace Start bit[11] should be 0*/ -{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */ {VIACR, CR69, 0xFF, 0x00}, {VIACR, CR6A, 0xFD, 0x40}, @@ -233,9 +225,6 @@ struct io_reg KM400_ModeXregs[] = { {VIACR, CR55, 0x80, 0x00}, {VIACR, CR5D, 0x80, 0x00}, {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */ - {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ - {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ - {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */ {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */ {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ @@ -285,14 +274,9 @@ struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ {VIACR, CR32, 0xFF, 0x00}, {VIACR, CR33, 0xFF, 0x00}, -{VIACR, CR34, 0xFF, 0x00}, {VIACR, CR35, 0xFF, 0x00}, {VIACR, CR36, 0x08, 0x00}, {VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */ -{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */ {VIACR, CR69, 0xFF, 0x00}, {VIACR, CR6A, 0xFF, 0x40}, {VIACR, CR6B, 0xFF, 0x00}, @@ -325,69 +309,61 @@ struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, {VIACR, CR96, 0xFF, 0x00}, {VIACR, CR97, 0xFF, 0x00}, {VIACR, CR99, 0xFF, 0x00}, -{VIACR, CR9B, 0xFF, 0x00}, -{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */ +{VIACR, CR9B, 0xFF, 0x00} }; -/* For VT3353: Common Setting for Video Mode */ -struct io_reg VX800_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, +struct io_reg VX855_ModeXregs[] = { +{VIASR, SR10, 0xFF, 0x01}, {VIASR, SR15, 0x02, 0x02}, {VIASR, SR16, 0xBF, 0x08}, {VIASR, SR17, 0xFF, 0x1F}, {VIASR, SR18, 0xFF, 0x4E}, {VIASR, SR1A, 0xFB, 0x08}, {VIASR, SR1B, 0xFF, 0xF0}, -{VIASR, SR1E, 0xFF, 0x01}, -{VIASR, SR2A, 0xFF, 0x00}, +{VIASR, SR1E, 0x07, 0x01}, +{VIASR, SR2A, 0xF0, 0x00}, +{VIASR, SR58, 0xFF, 0x00}, +{VIASR, SR59, 0xFF, 0x00}, {VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */ +{VIACR, CR09, 0xFF, 0x00}, /* Initial CR09=0*/ +{VIACR, CR11, 0x8F, 0x00}, /* IGA1 initial Vertical end */ +{VIACR, CR17, 0x7F, 0x00}, /* IGA1 CRT Mode control init */ {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */ {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */ {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */ {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ {VIACR, CR32, 0xFF, 0x00}, -{VIACR, CR33, 0xFF, 0x00}, -{VIACR, CR34, 0xFF, 0x00}, +{VIACR, CR33, 0x7F, 0x00}, {VIACR, CR35, 0xFF, 0x00}, {VIACR, CR36, 0x08, 0x00}, -{VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */ -{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */ -{VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */ {VIACR, CR69, 0xFF, 0x00}, -{VIACR, CR6A, 0xFF, 0x40}, +{VIACR, CR6A, 0xFD, 0x60}, {VIACR, CR6B, 0xFF, 0x00}, {VIACR, CR6C, 0xFF, 0x00}, -{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ -{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ -{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ -{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ -{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ -{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ -{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ -{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ -{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ -{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ -{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ -{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ -{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ -{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ -{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ -{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ -{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ -{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */ -{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */ -{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */ -{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */ -{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */ -{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */ -{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */ -{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */ +{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ +{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ +{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ +{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ +{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ +{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ +{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ +{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ +{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ +{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ +{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ +{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ +{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ +{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ +{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ +{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ +{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ +{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */ +{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */ {VIACR, CR96, 0xFF, 0x00}, {VIACR, CR97, 0xFF, 0x00}, {VIACR, CR99, 0xFF, 0x00}, {VIACR, CR9B, 0xFF, 0x00}, -{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */ +{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */ }; /* Video Mode Table */ @@ -401,7 +377,6 @@ struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00}, {VIASR, SR1A, 0xFB, 0x08}, {VIACR, CR32, 0xFF, 0x00}, -{VIACR, CR34, 0xFF, 0x00}, {VIACR, CR35, 0xFF, 0x00}, {VIACR, CR36, 0x08, 0x00}, {VIACR, CR6A, 0xFF, 0x80}, @@ -1084,3 +1059,14 @@ struct VideoModeTable CEA_HDMI_Modes[] = { {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} }; + +int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl); +int NUM_TOTAL_CEA_MODES = ARRAY_SIZE(CEA_HDMI_Modes); +int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs); +int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs); +int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs); +int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs); +int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs); +int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); +int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); +int NUM_TOTAL_MODETABLE = ARRAY_SIZE(CLE266Modes); diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index 1a5de50a23a2..a9d6554fabdf 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h @@ -50,128 +50,35 @@ struct res_map_refresh { int vmode_refresh; }; -#define NUM_TOTAL_RES_MAP_REFRESH ARRAY_SIZE(res_map_refresh_tbl) -#define NUM_TOTAL_CEA_MODES ARRAY_SIZE(CEA_HDMI_Modes) -#define NUM_TOTAL_CN400_ModeXregs ARRAY_SIZE(CN400_ModeXregs) -#define NUM_TOTAL_CN700_ModeXregs ARRAY_SIZE(CN700_ModeXregs) -#define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs) -#define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs) -#define NUM_TOTAL_VX800_ModeXregs ARRAY_SIZE(VX800_ModeXregs) -#define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs) -#define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table) -#define NUM_TOTAL_MODETABLE ARRAY_SIZE(CLE266Modes) +extern int NUM_TOTAL_RES_MAP_REFRESH; +extern int NUM_TOTAL_CEA_MODES; +extern int NUM_TOTAL_CN400_ModeXregs; +extern int NUM_TOTAL_CN700_ModeXregs; +extern int NUM_TOTAL_KM400_ModeXregs; +extern int NUM_TOTAL_CX700_ModeXregs; +extern int NUM_TOTAL_VX855_ModeXregs; +extern int NUM_TOTAL_CLE266_ModeXregs; +extern int NUM_TOTAL_PATCH_MODE; +extern int NUM_TOTAL_MODETABLE; /********************/ /* Mode Table */ /********************/ -/* 480x640 */ -extern struct crt_mode_table CRTM480x640[1]; -/* 640x480*/ -extern struct crt_mode_table CRTM640x480[5]; -/*720x480 (GTF)*/ -extern struct crt_mode_table CRTM720x480[1]; -/*720x576 (GTF)*/ -extern struct crt_mode_table CRTM720x576[1]; -/* 800x480 (CVT) */ -extern struct crt_mode_table CRTM800x480[1]; -/* 800x600*/ -extern struct crt_mode_table CRTM800x600[5]; -/* 848x480 (CVT) */ -extern struct crt_mode_table CRTM848x480[1]; -/*856x480 (GTF) convert to 852x480*/ -extern struct crt_mode_table CRTM852x480[1]; -/*1024x512 (GTF)*/ -extern struct crt_mode_table CRTM1024x512[1]; -/* 1024x600*/ -extern struct crt_mode_table CRTM1024x600[1]; -/* 1024x768*/ -extern struct crt_mode_table CRTM1024x768[4]; -/* 1152x864*/ -extern struct crt_mode_table CRTM1152x864[1]; -/* 1280x720 (HDMI 720P)*/ -extern struct crt_mode_table CRTM1280x720[2]; -/*1280x768 (GTF)*/ -extern struct crt_mode_table CRTM1280x768[2]; -/* 1280x800 (CVT) */ -extern struct crt_mode_table CRTM1280x800[1]; -/*1280x960*/ -extern struct crt_mode_table CRTM1280x960[1]; -/* 1280x1024*/ -extern struct crt_mode_table CRTM1280x1024[3]; -/* 1368x768 (GTF) */ -extern struct crt_mode_table CRTM1368x768[1]; -/*1440x1050 (GTF)*/ -extern struct crt_mode_table CRTM1440x1050[1]; -/* 1600x1200*/ -extern struct crt_mode_table CRTM1600x1200[2]; -/* 1680x1050 (CVT) */ -extern struct crt_mode_table CRTM1680x1050[2]; -/* 1680x1050 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1680x1050_RB[1]; -/* 1920x1080 (CVT)*/ -extern struct crt_mode_table CRTM1920x1080[1]; -/* 1920x1080 (CVT with Reduce Blanking) */ -extern struct crt_mode_table CRTM1920x1080_RB[1]; -/* 1920x1440*/ -extern struct crt_mode_table CRTM1920x1440[2]; -/* 1400x1050 (CVT) */ -extern struct crt_mode_table CRTM1400x1050[2]; -/* 1400x1050 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1400x1050_RB[1]; -/* 960x600 (CVT) */ -extern struct crt_mode_table CRTM960x600[1]; -/* 1000x600 (GTF) */ -extern struct crt_mode_table CRTM1000x600[1]; -/* 1024x576 (GTF) */ -extern struct crt_mode_table CRTM1024x576[1]; -/* 1088x612 (CVT) */ -extern struct crt_mode_table CRTM1088x612[1]; -/* 1152x720 (CVT) */ -extern struct crt_mode_table CRTM1152x720[1]; -/* 1200x720 (GTF) */ -extern struct crt_mode_table CRTM1200x720[1]; -/* 1280x600 (GTF) */ -extern struct crt_mode_table CRTM1280x600[1]; -/* 1360x768 (CVT) */ -extern struct crt_mode_table CRTM1360x768[1]; -/* 1360x768 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1360x768_RB[1]; -/* 1366x768 (GTF) */ -extern struct crt_mode_table CRTM1366x768[2]; -/* 1440x900 (CVT) */ -extern struct crt_mode_table CRTM1440x900[2]; -/* 1440x900 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1440x900_RB[1]; -/* 1600x900 (CVT) */ -extern struct crt_mode_table CRTM1600x900[1]; -/* 1600x900 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1600x900_RB[1]; -/* 1600x1024 (GTF) */ -extern struct crt_mode_table CRTM1600x1024[1]; -/* 1792x1344 (DMT) */ -extern struct crt_mode_table CRTM1792x1344[1]; -/* 1856x1392 (DMT) */ -extern struct crt_mode_table CRTM1856x1392[1]; -/* 1920x1200 (CVT) */ -extern struct crt_mode_table CRTM1920x1200[1]; -/* 1920x1200 (CVT with Reduce Blanking) */ -extern struct crt_mode_table CRTM1920x1200_RB[1]; -/* 2048x1536 (CVT) */ -extern struct crt_mode_table CRTM2048x1536[1]; -extern struct VideoModeTable CLE266Modes[47]; -extern struct crt_mode_table CEAM1280x720[1]; -extern struct crt_mode_table CEAM1920x1080[1]; -extern struct VideoModeTable CEA_HDMI_Modes[2]; +extern struct VideoModeTable CLE266Modes[]; +extern struct crt_mode_table CEAM1280x720[]; +extern struct crt_mode_table CEAM1920x1080[]; +extern struct VideoModeTable CEA_HDMI_Modes[]; -extern struct res_map_refresh res_map_refresh_tbl[61]; -extern struct io_reg CN400_ModeXregs[52]; -extern struct io_reg CN700_ModeXregs[66]; -extern struct io_reg KM400_ModeXregs[55]; -extern struct io_reg CX700_ModeXregs[58]; -extern struct io_reg VX800_ModeXregs[58]; -extern struct io_reg CLE266_ModeXregs[32]; -extern struct io_reg PM1024x768[2]; -extern struct patch_table res_patch_table[1]; +extern struct res_map_refresh res_map_refresh_tbl[]; +extern struct io_reg CN400_ModeXregs[]; +extern struct io_reg CN700_ModeXregs[]; +extern struct io_reg KM400_ModeXregs[]; +extern struct io_reg CX700_ModeXregs[]; +extern struct io_reg VX800_ModeXregs[]; +extern struct io_reg VX855_ModeXregs[]; +extern struct io_reg CLE266_ModeXregs[]; +extern struct io_reg PM1024x768[]; +extern struct patch_table res_patch_table[]; extern struct VPITTable VPIT; #endif /* __VIAMODE_H__ */ diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c index 322a9f993550..a6b37494e79a 100644 --- a/drivers/video/via/vt1636.c +++ b/drivers/video/via/vt1636.c @@ -27,7 +27,7 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information { u8 data; - viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; + viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data); return data; @@ -39,7 +39,7 @@ void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information { int index, data; - viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; + viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; index = io_data.Index; data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info, |