# HG changeset patch # User dkiper@xxxxxxxxxxxx # Date 1259014658 -3600 # Node ID 0659978a191179169437dbbc3ed224c23c6e1b8a # Parent 1db1bb63824b25f97d127449faeb3a56f1272c97 ATI drivers backported from Linux Kernel Ver. 2.6.29.2 Signed-off-by: Daniel Kiper diff -r 1db1bb63824b -r 0659978a1911 Documentation/fb/aty128fb.txt --- a/Documentation/fb/aty128fb.txt Mon Nov 23 07:32:47 2009 +0000 +++ b/Documentation/fb/aty128fb.txt Mon Nov 23 23:17:38 2009 +0100 @@ -54,8 +54,8 @@ Accepted options: noaccel - do not use acceleration engine. It is default. accel - use acceleration engine. Not finished. -vmode:x - chooses PowerMacintosh video mode . Depreciated. -cmode:x - chooses PowerMacintosh colour mode . Depreciated. +vmode:x - chooses PowerMacintosh video mode . Deprecated. +cmode:x - chooses PowerMacintosh colour mode . Deprecated. - selects startup videomode. See modedb.txt for detailed explanation. Default is 640x480x8bpp. diff -r 1db1bb63824b -r 0659978a1911 drivers/video/aty/ati_ids.h --- a/drivers/video/aty/ati_ids.h Mon Nov 23 07:32:47 2009 +0000 +++ b/drivers/video/aty/ati_ids.h Mon Nov 23 23:17:38 2009 +0100 @@ -188,10 +188,17 @@ #define PCI_CHIP_MACH64VT 0x5654 #define PCI_CHIP_MACH64VU 0x5655 #define PCI_CHIP_MACH64VV 0x5656 +#define PCI_CHIP_RC410_5A62 0x5A62 #define PCI_CHIP_RS300_5834 0x5834 #define PCI_CHIP_RS300_5835 0x5835 #define PCI_CHIP_RS300_5836 0x5836 #define PCI_CHIP_RS300_5837 0x5837 +#define PCI_CHIP_RS480_5955 0x5955 +#define PCI_CHIP_RV280_5960 0x5960 +#define PCI_CHIP_RV280_5961 0x5961 +#define PCI_CHIP_RV280_5962 0x5962 +#define PCI_CHIP_RV280_5964 0x5964 +#define PCI_CHIP_RS482_5975 0x5975 #define PCI_CHIP_RV370_5B60 0x5B60 #define PCI_CHIP_RV370_5B61 0x5B61 #define PCI_CHIP_RV370_5B62 0x5B62 @@ -200,13 +207,8 @@ #define PCI_CHIP_RV370_5B65 0x5B65 #define PCI_CHIP_RV370_5B66 0x5B66 #define PCI_CHIP_RV370_5B67 0x5B67 -#define PCI_CHIP_RV280_5960 0x5960 -#define PCI_CHIP_RV280_5961 0x5961 -#define PCI_CHIP_RV280_5962 0x5962 -#define PCI_CHIP_RV280_5964 0x5964 #define PCI_CHIP_RV280_5C61 0x5C61 #define PCI_CHIP_RV280_5C63 0x5C63 #define PCI_CHIP_R423_5D57 0x5D57 #define PCI_CHIP_RS350_7834 0x7834 #define PCI_CHIP_RS350_7835 0x7835 - diff -r 1db1bb63824b -r 0659978a1911 drivers/video/aty/aty128fb.c --- a/drivers/video/aty/aty128fb.c Mon Nov 23 07:32:47 2009 +0000 +++ b/drivers/video/aty/aty128fb.c Mon Nov 23 23:17:38 2009 +0100 @@ -56,7 +56,7 @@ #include #include #include -#include +#include #include #include #include @@ -91,7 +91,7 @@ #undef DEBUG #ifdef DEBUG -#define DBG(fmt, args...) printk(KERN_DEBUG "aty128fb: %s " fmt, __FUNCTION__, ##args); +#define DBG(fmt, args...) printk(KERN_DEBUG "aty128fb: %s " fmt, __func__, ##args); #else #define DBG(fmt, args...) #endif @@ -357,6 +357,12 @@ static int mtrr = 1; static int mtrr = 1; #endif +#ifdef CONFIG_PMAC_BACKLIGHT +static int backlight __devinitdata = 1; +#else +static int backlight __devinitdata = 0; +#endif + /* PLL constants */ struct aty128_constants { u32 ref_clk; @@ -1334,13 +1340,16 @@ static int aty128_var_to_pll(u32 period_ vclk = c.ppll_min/12; /* now, find an acceptable divider */ - for (i = 0; i < sizeof(post_dividers); i++) { + for (i = 0; i < ARRAY_SIZE(post_dividers); i++) { output_freq = post_dividers[i] * vclk; if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) { pll->post_divider = post_dividers[i]; break; } } + + if (i == ARRAY_SIZE(post_dividers)) + return -EINVAL; /* calculate feedback divider */ n = c.ref_divider * output_freq; @@ -1466,7 +1475,7 @@ static int aty128fb_set_par(struct fb_in aty128_set_pll(&par->pll, par); aty128_set_fifo(&par->fifo_reg, par); - config = aty_ld_le32(CONFIG_CNTL) & ~3; + config = aty_ld_le32(CNFG_CNTL) & ~3; #if defined(__BIG_ENDIAN) if (par->crtc.bpp == 32) @@ -1475,7 +1484,7 @@ static int aty128fb_set_par(struct fb_in config |= 1; /* make aperture do 16 bit swapping */ #endif - aty_st_le32(CONFIG_CNTL, config); + aty_st_le32(CNFG_CNTL, config); aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */ info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3; @@ -1646,6 +1655,9 @@ static int __devinit aty128fb_setup(char continue; } else if (!strncmp(this_opt, "crt:", 4)) { default_crt_on = simple_strtoul(this_opt+4, NULL, 0); + continue; + } else if (!strncmp(this_opt, "backlight:", 10)) { + backlight = simple_strtoul(this_opt+10, NULL, 0); continue; } #ifdef CONFIG_MTRR @@ -1690,9 +1702,6 @@ static int __devinit aty128fb_setup(char #ifdef CONFIG_FB_ATY128_BACKLIGHT #define MAX_LEVEL 0xFF -static struct backlight_properties aty128_bl_data; - -/* Call with fb_info->bl_mutex held */ static int aty128_bl_get_level_brightness(struct aty128fb_par *par, int level) { @@ -1700,6 +1709,7 @@ static int aty128_bl_get_level_brightnes int atylevel; /* Get and convert the value */ + /* No locking of bl_curve since we read a single value */ atylevel = MAX_LEVEL - (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); @@ -1719,19 +1729,18 @@ static int aty128_bl_get_level_brightnes /* That one prevents proper CRT output with LCD off */ #undef BACKLIGHT_DAC_OFF -/* Call with fb_info->bl_mutex held */ -static int __aty128_bl_update_status(struct backlight_device *bd) -{ - struct aty128fb_par *par = class_get_devdata(&bd->class_dev); +static int aty128_bl_update_status(struct backlight_device *bd) +{ + struct aty128fb_par *par = bl_get_data(bd); unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); int level; - if (bd->props->power != FB_BLANK_UNBLANK || - bd->props->fb_blank != FB_BLANK_UNBLANK || + if (bd->props.power != FB_BLANK_UNBLANK || + bd->props.fb_blank != FB_BLANK_UNBLANK || !par->lcd_on) level = 0; else - level = bd->props->brightness; + level = bd->props.brightness; reg |= LVDS_BL_MOD_EN | LVDS_BLON; if (level > 0) { @@ -1773,43 +1782,22 @@ static int __aty128_bl_update_status(str return 0; } -static int aty128_bl_update_status(struct backlight_device *bd) -{ - struct aty128fb_par *par = class_get_devdata(&bd->class_dev); - struct fb_info *info = pci_get_drvdata(par->pdev); - int ret; - - mutex_lock(&info->bl_mutex); - ret = __aty128_bl_update_status(bd); - mutex_unlock(&info->bl_mutex); - - return ret; -} - static int aty128_bl_get_brightness(struct backlight_device *bd) { - return bd->props->brightness; -} - -static struct backlight_properties aty128_bl_data = { - .owner = THIS_MODULE, + return bd->props.brightness; +} + +static struct backlight_ops aty128_bl_data = { .get_brightness = aty128_bl_get_brightness, .update_status = aty128_bl_update_status, - .max_brightness = (FB_BACKLIGHT_LEVELS - 1), }; static void aty128_bl_set_power(struct fb_info *info, int power) { - mutex_lock(&info->bl_mutex); - if (info->bl_dev) { - down(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __aty128_bl_update_status(info->bl_dev); - up(&info->bl_dev->sem); - } - - mutex_unlock(&info->bl_mutex); + info->bl_dev->props.power = power; + backlight_update_status(info->bl_dev); + } } static void aty128_bl_init(struct aty128fb_par *par) @@ -1829,32 +1817,22 @@ static void aty128_bl_init(struct aty128 snprintf(name, sizeof(name), "aty128bl%d", info->node); - bd = backlight_device_register(name, par, &aty128_bl_data); + bd = backlight_device_register(name, info->dev, par, &aty128_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; printk(KERN_WARNING "aty128: Backlight registration failed\n"); goto error; } - mutex_lock(&info->bl_mutex); info->bl_dev = bd; fb_bl_default_curve(info, 0, 63 * FB_BACKLIGHT_MAX / MAX_LEVEL, 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); - mutex_unlock(&info->bl_mutex); - - down(&bd->sem); - bd->props->brightness = aty128_bl_data.max_brightness; - bd->props->power = FB_BLANK_UNBLANK; - bd->props->update_status(bd); - up(&bd->sem); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); - if (!pmac_backlight) - pmac_backlight = bd; - mutex_unlock(&pmac_backlight_mutex); -#endif + + bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1; + bd->props.brightness = bd->props.max_brightness; + bd->props.power = FB_BLANK_UNBLANK; + backlight_update_status(bd); printk("aty128: Backlight initialized (%s)\n", name); @@ -1864,31 +1842,10 @@ error: return; } -static void aty128_bl_exit(struct aty128fb_par *par) -{ - struct fb_info *info = pci_get_drvdata(par->pdev); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); -#endif - - mutex_lock(&info->bl_mutex); - if (info->bl_dev) { -#ifdef CONFIG_PMAC_BACKLIGHT - if (pmac_backlight == info->bl_dev) - pmac_backlight = NULL; -#endif - - backlight_device_unregister(info->bl_dev); - info->bl_dev = NULL; - - printk("aty128: Backlight unloaded\n"); - } - mutex_unlock(&info->bl_mutex); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_unlock(&pmac_backlight_mutex); -#endif +static void aty128_bl_exit(struct backlight_device *bd) +{ + backlight_device_unregister(bd); + printk("aty128: Backlight unloaded\n"); } #endif /* CONFIG_FB_ATY128_BACKLIGHT */ @@ -1896,13 +1853,14 @@ static void aty128_bl_exit(struct aty128 * Initialisation */ -#ifdef CONFIG_PPC_PMAC +#ifdef CONFIG_PPC_PMAC__disabled static void aty128_early_resume(void *data) { struct aty128fb_par *par = data; if (try_acquire_console_sem()) return; + pci_restore_state(par->pdev); aty128_do_resume(par->pdev); release_console_sem(); } @@ -1913,12 +1871,12 @@ static int __devinit aty128_init(struct struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; struct fb_var_screeninfo var; - char video_card[DEVICE_NAME_SIZE]; + char video_card[50]; u8 chip_rev; u32 dac; /* Get the chip revision */ - chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; + chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F; strcpy(video_card, "Rage128 XX "); video_card[8] = ent->device >> 8; @@ -1926,7 +1884,7 @@ static int __devinit aty128_init(struct /* range check to make sure */ if (ent->driver_data < ARRAY_SIZE(r128_family)) - strncat(video_card, r128_family[ent->driver_data], sizeof(video_card)); + strlcat(video_card, r128_family[ent->driver_data], sizeof(video_card)); printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); @@ -1950,7 +1908,14 @@ static int __devinit aty128_init(struct /* Indicate sleep capability */ if (par->chip_gen == rage_M3) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1); +#if 0 /* Disable the early video resume hack for now as it's causing problems, among + * others we now rely on the PCI core restoring the config space for us, which + * isn't the case with that hack, and that code path causes various things to + * be called with interrupts off while they shouldn't. I'm leaving the code in + * as it can be useful for debugging purposes + */ pmac_set_early_video_resume(aty128_early_resume, par); +#endif } /* Find default mode */ @@ -2035,7 +2000,8 @@ static int __devinit aty128_init(struct par->lock_blank = 0; #ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_init(par); + if (backlight) + aty128_bl_init(par); #endif if (register_framebuffer(info) < 0) @@ -2099,7 +2065,7 @@ static int __devinit aty128_probe(struct /* Grab memory size from the card */ // How does this relate to the resource length from the PCI hardware? - par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; + par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF; /* Virtualize the framebuffer */ info->screen_base = ioremap(fb_addr, par->vram_size); @@ -2175,11 +2141,12 @@ static void __devexit aty128_remove(stru par = info->par; + unregister_framebuffer(info); + #ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_exit(par); -#endif - - unregister_framebuffer(info); + aty128_bl_exit(info->bl_dev); +#endif + #ifdef CONFIG_MTRR if (par->mtrr.vram_valid) mtrr_del(par->mtrr.vram, info->fix.smem_start, @@ -2204,34 +2171,35 @@ static int aty128fb_blank(int blank, str static int aty128fb_blank(int blank, struct fb_info *fb) { struct aty128fb_par *par = fb->par; - u8 state = 0; + u8 state; if (par->lock_blank || par->asleep) return 0; -#ifdef CONFIG_FB_ATY128_BACKLIGHT - if (machine_is(powermac) && blank) - aty128_bl_set_power(fb, FB_BLANK_POWERDOWN); -#endif - - if (blank & FB_BLANK_VSYNC_SUSPEND) - state |= 2; - if (blank & FB_BLANK_HSYNC_SUSPEND) - state |= 1; - if (blank & FB_BLANK_POWERDOWN) - state |= 4; - + switch (blank) { + case FB_BLANK_NORMAL: + state = 4; + break; + case FB_BLANK_VSYNC_SUSPEND: + state = 6; + break; + case FB_BLANK_HSYNC_SUSPEND: + state = 5; + break; + case FB_BLANK_POWERDOWN: + state = 7; + break; + case FB_BLANK_UNBLANK: + default: + state = 0; + break; + } aty_st_8(CRTC_EXT_CNTL+1, state); if (par->chip_gen == rage_M3) { aty128_set_crt_enable(par, par->crt_on && !blank); aty128_set_lcd_enable(par, par->lcd_on && !blank); } - -#ifdef CONFIG_FB_ATY128_BACKLIGHT - if (machine_is(powermac) && !blank) - aty128_bl_set_power(fb, FB_BLANK_UNBLANK); -#endif return 0; } @@ -2405,7 +2373,6 @@ static void aty128_set_suspend(struct at static void aty128_set_suspend(struct aty128fb_par *par, int suspend) { u32 pmgt; - u16 pwr_command; struct pci_dev *pdev = par->pdev; if (!par->pm_reg) @@ -2414,6 +2381,8 @@ static void aty128_set_suspend(struct at /* Set the chip into the appropriate suspend mode (we use D2, * D3 would require a complete re-initialisation of the chip, * including PCI config registers, clocks, AGP configuration, ...) + * + * For resume, the core will have already brought us back to D0 */ if (suspend) { /* Make sure CRTC2 is reset. Remove that the day we decide to @@ -2431,17 +2400,9 @@ static void aty128_set_suspend(struct at aty_st_le32(BUS_CNTL1, 0x00000010); aty_st_le32(MEM_POWER_MISC, 0x0c830000); mdelay(100); - pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); + /* Switch PCI power management to D2 */ - pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, - (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | 2); - pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); - } else { - /* Switch back PCI power management to D0 */ - mdelay(100); - pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, 0); - pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); - mdelay(100); + pci_set_power_state(pdev, PCI_D2); } } @@ -2449,6 +2410,12 @@ static int aty128_pci_suspend(struct pci { struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; + + /* 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. + */ + pci_save_state(pdev); /* We don't do anything but D2, for now we return 0, but * we may want to change that. How do we know if the BIOS @@ -2479,7 +2446,7 @@ static int aty128_pci_suspend(struct pci wait_for_idle(par); /* Blank display and LCD */ - aty128fb_blank(VESA_POWERDOWN, info); + aty128fb_blank(FB_BLANK_POWERDOWN, info); /* Sleep */ par->asleep = 1; @@ -2515,6 +2482,11 @@ static int aty128_do_resume(struct pci_d if (pdev->dev.power.power_state.event == PM_EVENT_ON) return 0; + + /* PCI state will have been restored by the core, so + * we should be in D0 now with our config space fully + * restored + */ /* Wakeup chip */ aty128_set_suspend(par, 0); diff -r 1db1bb63824b -r 0659978a1911 drivers/video/aty/atyfb.h --- a/drivers/video/aty/atyfb.h Mon Nov 23 07:32:47 2009 +0000 +++ b/drivers/video/aty/atyfb.h Mon Nov 23 23:17:38 2009 +0100 @@ -126,7 +126,7 @@ union aty_pll { */ struct atyfb_par { - struct aty_cmap_regs __iomem *aty_cmap_regs; + u32 pseudo_palette[16]; struct { u8 red, green, blue; } palette[256]; const struct aty_dac_ops *dac_ops; const struct aty_pll_ops *pll_ops; @@ -186,6 +186,7 @@ struct atyfb_par { int mtrr_aper; int mtrr_reg; #endif + u32 mem_cntl; }; /* @@ -227,7 +228,7 @@ static inline u32 aty_ld_le32(int regind regindex -= 0x800; #ifdef CONFIG_ATARI - return in_le32((volatile u32 *)(par->ati_regbase + regindex)); + return in_le32(par->ati_regbase + regindex); #else return readl(par->ati_regbase + regindex); #endif @@ -240,7 +241,7 @@ static inline void aty_st_le32(int regin regindex -= 0x800; #ifdef CONFIG_ATARI - out_le32((volatile u32 *)(par->ati_regbase + regindex), val); + out_le32(par->ati_regbase + regindex, val); #else writel(val, par->ati_regbase + regindex); #endif @@ -253,7 +254,7 @@ static inline void aty_st_le16(int regin if (regindex >= 0x400) regindex -= 0x800; #ifdef CONFIG_ATARI - out_le16((volatile u16 *)(par->ati_regbase + regindex), val); + out_le16(par->ati_regbase + regindex, val); #else writel(val, par->ati_regbase + regindex); #endif @@ -284,7 +285,8 @@ static inline void aty_st_8(int regindex #endif } -#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) +#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ +defined (CONFIG_FB_ATY_GENERIC_LCD) || defined (CONFIG_FB_ATY_BACKLIGHT) extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par); extern u32 aty_ld_lcd(int index, const struct atyfb_par *par); #endif @@ -315,6 +317,7 @@ struct aty_pll_ops { void (*set_pll) (const struct fb_info * info, const union aty_pll * pll); void (*get_pll) (const struct fb_info *info, union aty_pll * pll); int (*init_pll) (const struct fb_info * info, union aty_pll * pll); + void (*resume_pll)(const struct fb_info *info, union aty_pll *pll); }; extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */ @@ -355,5 +358,9 @@ static inline void wait_for_idle(struct extern void aty_reset_engine(const struct atyfb_par *par); extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info); -extern void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par); extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par); + +void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); +void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); +void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); + diff -r 1db1bb63824b -r 0659978a1911 drivers/video/aty/atyfb_base.c --- a/drivers/video/aty/atyfb_base.c Mon Nov 23 07:32:47 2009 +0000 +++ b/drivers/video/aty/atyfb_base.c Mon Nov 23 23:17:38 2009 +0100 @@ -26,7 +26,7 @@ * Anthony Tong * * Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern - * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug. + * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -68,7 +68,7 @@ #include #include -#include +#include #include