diff options
Diffstat (limited to 'drivers/video/fbdev/aty/aty128fb.c')
| -rw-r--r-- | drivers/video/fbdev/aty/aty128fb.c | 263 |
1 files changed, 93 insertions, 170 deletions
diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c index 6cc46867ff57..f55b4c7609a8 100644 --- a/drivers/video/fbdev/aty/aty128fb.c +++ b/drivers/video/fbdev/aty/aty128fb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* $Id: aty128fb.c,v 1.1.1.1.36.1 1999/12/11 09:03:05 Exp $ * linux/drivers/video/aty128fb.c -- Frame buffer device for ATI Rage128 * @@ -22,7 +23,7 @@ * - Convert to new framebuffer API, * fix colormap setting at 16 bits/pixel (565) * - * Paul Mundt + * Paul Mundt * - PCI hotplug * * Jon Smirl <jonsmirl@yahoo.com> @@ -46,6 +47,7 @@ */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> @@ -67,7 +69,6 @@ #ifdef CONFIG_PPC_PMAC #include <asm/machdep.h> #include <asm/pmac_feature.h> -#include <asm/prom.h> #include "../macmodes.h" #endif @@ -161,10 +162,22 @@ static char * const r128_family[] = { static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static void aty128_remove(struct pci_dev *pdev); -static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state); -static int aty128_pci_resume(struct pci_dev *pdev); +static int aty128_pci_suspend_late(struct device *dev, pm_message_t state); +static int __maybe_unused aty128_pci_suspend(struct device *dev); +static int __maybe_unused aty128_pci_hibernate(struct device *dev); +static int __maybe_unused aty128_pci_freeze(struct device *dev); +static int __maybe_unused aty128_pci_resume(struct device *dev); static int aty128_do_resume(struct pci_dev *pdev); +static const struct dev_pm_ops aty128_pci_pm_ops = { + .suspend = aty128_pci_suspend, + .resume = aty128_pci_resume, + .freeze = aty128_pci_freeze, + .thaw = aty128_pci_resume, + .poweroff = aty128_pci_hibernate, + .restore = aty128_pci_resume, +}; + /* supported Rage128 chipsets */ static const struct pci_device_id aty128_pci_tbl[] = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LE, @@ -271,8 +284,7 @@ static struct pci_driver aty128fb_driver = { .id_table = aty128_pci_tbl, .probe = aty128_probe, .remove = aty128_remove, - .suspend = aty128_pci_suspend, - .resume = aty128_pci_resume, + .driver.pm = &aty128_pci_pm_ops, }; /* packed BIOS settings */ @@ -333,20 +345,6 @@ static const struct aty128_meminfo sdr_128 = { .name = "128-bit SDR SGRAM (1:1)", }; -static const struct aty128_meminfo sdr_64 = { - .ML = 4, - .MB = 8, - .Trcd = 3, - .Trp = 3, - .Twr = 1, - .CL = 3, - .Tr2w = 1, - .LoopLatency = 17, - .DspOn = 46, - .Rloop = 17, - .name = "64-bit SDR SGRAM (1:1)", -}; - static const struct aty128_meminfo sdr_sgram = { .ML = 4, .MB = 4, @@ -397,11 +395,7 @@ static int default_lcd_on = 1; static bool mtrr = true; #ifdef CONFIG_FB_ATY128_BACKLIGHT -#ifdef CONFIG_PMAC_BACKLIGHT -static int backlight = 1; -#else -static int backlight = 0; -#endif +static int backlight = IS_BUILTIN(CONFIG_PMAC_BACKLIGHT); #endif /* PLL constants */ @@ -486,11 +480,6 @@ static int aty128_encode_var(struct fb_var_screeninfo *var, const struct aty128fb_par *par); static int aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par); -#if 0 -static void aty128_get_pllinfo(struct aty128fb_par *par, void __iomem *bios); -static void __iomem *aty128_map_ROM(struct pci_dev *pdev, - const struct aty128fb_par *par); -#endif static void aty128_timings(struct aty128fb_par *par); static void aty128_init_engine(struct aty128fb_par *par); static void aty128_reset_engine(const struct aty128fb_par *par); @@ -513,8 +502,9 @@ static void aty128_bl_set_power(struct fb_info *info, int power); (readb(bios + (v) + 3) << 24)) -static struct fb_ops aty128fb_ops = { +static const struct fb_ops aty128fb_ops = { .owner = THIS_MODULE, + FB_DEFAULT_IOMEM_OPS, .fb_check_var = aty128fb_check_var, .fb_set_par = aty128fb_set_par, .fb_setcolreg = aty128fb_setcolreg, @@ -522,9 +512,6 @@ static struct fb_ops aty128fb_ops = { .fb_blank = aty128fb_blank, .fb_ioctl = aty128fb_ioctl, .fb_sync = aty128fb_sync, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, }; /* @@ -532,13 +519,13 @@ static struct fb_ops aty128fb_ops = { * - endian conversions may possibly be avoided by * using the other register aperture. TODO. */ -static inline u32 _aty_ld_le32(volatile unsigned int regindex, +static inline u32 _aty_ld_le32(volatile unsigned int regindex, const struct aty128fb_par *par) { return readl (par->regbase + regindex); } -static inline void _aty_st_le32(volatile unsigned int regindex, u32 val, +static inline void _aty_st_le32(volatile unsigned int regindex, u32 val, const struct aty128fb_par *par) { writel (val, par->regbase + regindex); @@ -571,12 +558,12 @@ static inline void _aty_st_8(unsigned int regindex, u8 val, static u32 _aty_ld_pll(unsigned int pll_index, const struct aty128fb_par *par) -{ +{ aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x3F); return aty_ld_le32(CLOCK_CNTL_DATA); } - + static void _aty_st_pll(unsigned int pll_index, u32 val, const struct aty128fb_par *par) { @@ -631,7 +618,7 @@ static int register_test(const struct aty128fb_par *par) aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA); if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA) - flag = 1; + flag = 1; } aty_st_le32(BIOS_0_SCRATCH, val); // restore value @@ -913,7 +900,7 @@ static void aty128_get_pllinfo(struct aty128fb_par *par, bios_hdr = BIOS_IN16(0x48); bios_pll = BIOS_IN16(bios_hdr + 0x30); - + par->constants.ppll_max = BIOS_IN32(bios_pll + 0x16); par->constants.ppll_min = BIOS_IN32(bios_pll + 0x12); par->constants.xclk = BIOS_IN16(bios_pll + 0x08); @@ -925,7 +912,7 @@ static void aty128_get_pllinfo(struct aty128fb_par *par, par->constants.xclk, par->constants.ref_divider, par->constants.ref_clk); -} +} #ifdef CONFIG_X86 static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par) @@ -937,7 +924,7 @@ static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par) */ u32 segstart; unsigned char __iomem *rom_base = NULL; - + for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { rom_base = ioremap(segstart, 0x10000); if (rom_base == NULL) @@ -963,7 +950,7 @@ static void aty128_timings(struct aty128fb_par *par) u32 x_mpll_ref_fb_div; u32 xclk_cntl; u32 Nx, M; - unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 }; + static const unsigned int PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 }; #endif if (!par->constants.ref_clk) @@ -1130,12 +1117,12 @@ static int aty128_var_to_crtc(const struct fb_var_screeninfo *var, v_sync_wid = 1; else if (v_sync_wid > 0x1f) /* 0x1f = max vwidth */ v_sync_wid = 0x1f; - + v_sync_strt = v_disp + lower; h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; - + c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; crtc->gen_cntl = 0x3000000L | c_sync | (dst << 8); @@ -1312,12 +1299,12 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) reg &= ~LVDS_DISPLAY_DIS; aty_st_le32(LVDS_GEN_CNTL, reg); #ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_set_power(info, FB_BLANK_UNBLANK); -#endif + aty128_bl_set_power(info, BACKLIGHT_POWER_ON); +#endif } else { #ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_set_power(info, FB_BLANK_POWERDOWN); -#endif + aty128_bl_set_power(info, BACKLIGHT_POWER_OFF); +#endif reg = aty_ld_le32(LVDS_GEN_CNTL); reg |= LVDS_DISPLAY_DIS; aty_st_le32(LVDS_GEN_CNTL, reg); @@ -1332,8 +1319,10 @@ static void aty128_set_pll(struct aty128_pll *pll, { u32 div3; - unsigned char post_conv[] = /* register values for post dividers */ - { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 }; + /* register values for post dividers */ + static const unsigned char post_conv[] = { + 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 + }; /* select PPLL_DIV_3 */ aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8)); @@ -1371,7 +1360,7 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, const struct aty128fb_par *par) { const struct aty128_constants c = par->constants; - unsigned char post_dividers[] = {1,2,4,8,3,6,12}; + static const unsigned char post_dividers[] = { 1, 2, 4, 8, 3, 6, 12 }; u32 output_freq; u32 vclk; /* in .01 MHz */ int i = 0; @@ -1491,7 +1480,7 @@ static int aty128_ddafifo(struct aty128_ddafifo *dsp, * This actually sets the video mode. */ static int aty128fb_set_par(struct fb_info *info) -{ +{ struct aty128fb_par *par = info->par; u32 config; int err; @@ -1605,7 +1594,7 @@ static int aty128_encode_var(struct fb_var_screeninfo *var, var->accel_flags = par->accel_flags; return 0; -} +} static int aty128fb_check_var(struct fb_var_screeninfo *var, @@ -1664,19 +1653,6 @@ static void aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue, struct aty128fb_par *par) { if (par->chip_gen == rage_M3) { -#if 0 - /* Note: For now, on M3, we set palette on both heads, which may - * be useless. Can someone with a M3 check this ? - * - * This code would still be useful if using the second CRTC to - * do mirroring - */ - - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | - DAC_PALETTE_ACCESS_CNTL); - aty_st_8(PALETTE_INDEX, regno); - aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue); -#endif aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL); } @@ -1788,12 +1764,10 @@ static int aty128_bl_update_status(struct backlight_device *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 || - !par->lcd_on) + if (!par->lcd_on) level = 0; else - level = bd->props.brightness; + level = backlight_get_brightness(bd); reg |= LVDS_BL_MOD_EN | LVDS_BLON; if (level > 0) { @@ -1870,7 +1844,7 @@ static void aty128_bl_init(struct aty128fb_par *par) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = FB_BACKLIGHT_LEVELS - 1; - bd = backlight_device_register(name, info->dev, par, &aty128_bl_data, + bd = backlight_device_register(name, info->device, par, &aty128_bl_data, &props); if (IS_ERR(bd)) { info->bl_dev = NULL; @@ -1884,7 +1858,7 @@ static void aty128_bl_init(struct aty128fb_par *par) 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); bd->props.brightness = bd->props.max_brightness; - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; backlight_update_status(bd); printk("aty128: Backlight initialized (%s)\n", name); @@ -1951,7 +1925,6 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) /* fill in info */ info->fbops = &aty128fb_ops; - info->flags = FBINFO_FLAG_DEFAULT; par->lcd_on = default_lcd_on; par->crt_on = default_crt_on; @@ -2002,12 +1975,12 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) /* PowerBook Titanium */ if (of_machine_is_compatible("PowerBook3,2")) default_vmode = VMODE_1152_768_60; - - if (default_cmode > 16) + + if (default_cmode > 16) default_cmode = CMODE_32; - else if (default_cmode > 8) + else if (default_cmode > 8) default_cmode = CMODE_16; - else + else default_cmode = CMODE_8; if (mac_vmode_to_var(default_vmode, default_cmode, &var)) @@ -2017,7 +1990,7 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) #endif /* CONFIG_PPC_PMAC */ { if (mode_option) - if (fb_find_mode(&var, info, mode_option, NULL, + if (fb_find_mode(&var, info, mode_option, NULL, 0, &defaultmode, 8) == 0) var = default_var; } @@ -2052,14 +2025,14 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) par->asleep = 0; par->lock_blank = 0; + if (register_framebuffer(info) < 0) + return 0; + #ifdef CONFIG_FB_ATY128_BACKLIGHT if (backlight) aty128_bl_init(par); #endif - if (register_framebuffer(info) < 0) - return 0; - fb_info(info, "%s frame buffer device on %s\n", info->fix.id, video_card); @@ -2078,6 +2051,10 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *bios = NULL; #endif + err = aperture_remove_conflicting_pci_devices(pdev, "aty128fb"); + if (err) + return err; + /* Enable device in PCI config */ if ((err = pci_enable_device(pdev))) { printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n", @@ -2102,10 +2079,9 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* We have the resources. Now virtualize them */ info = framebuffer_alloc(sizeof(struct aty128fb_par), &pdev->dev); - if (info == NULL) { - printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n"); + if (!info) goto err_free_mmio; - } + par = info->par; info->pseudo_palette = par->pseudo_palette; @@ -2188,12 +2164,12 @@ static void aty128_remove(struct pci_dev *pdev) par = info->par; - unregister_framebuffer(info); - #ifdef CONFIG_FB_ATY128_BACKLIGHT aty128_bl_exit(info->bl_dev); #endif + unregister_framebuffer(info); + arch_phys_wc_del(par->wc_cookie); iounmap(par->regbase); iounmap(info->screen_base); @@ -2325,7 +2301,7 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) struct aty128fb_par *par = info->par; u32 value; int rc; - + switch (cmd) { case FBIO_ATY128_SET_MIRROR: if (par->chip_gen != rage_M3) @@ -2337,8 +2313,8 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) par->crt_on = (value & 0x02) != 0; if (!par->crt_on && !par->lcd_on) par->lcd_on = 1; - aty128_set_crt_enable(par, par->crt_on); - aty128_set_lcd_enable(par, par->lcd_on); + aty128_set_crt_enable(par, par->crt_on); + aty128_set_lcd_enable(par, par->lcd_on); return 0; case FBIO_ATY128_GET_MIRROR: if (par->chip_gen != rage_M3) @@ -2349,78 +2325,13 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) return -EINVAL; } -#if 0 - /* - * Accelerated functions - */ - -static inline void aty128_rectcopy(int srcx, int srcy, int dstx, int dsty, - u_int width, u_int height, - struct fb_info_aty128 *par) -{ - u32 save_dp_datatype, save_dp_cntl, dstval; - - if (!width || !height) - return; - - dstval = depth_to_dst(par->current_par.crtc.depth); - if (dstval == DST_24BPP) { - srcx *= 3; - dstx *= 3; - width *= 3; - } else if (dstval == -EINVAL) { - printk("aty128fb: invalid depth or RGBA\n"); - return; - } - - wait_for_fifo(2, par); - save_dp_datatype = aty_ld_le32(DP_DATATYPE); - save_dp_cntl = aty_ld_le32(DP_CNTL); - - wait_for_fifo(6, par); - aty_st_le32(SRC_Y_X, (srcy << 16) | srcx); - aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT); - aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); - aty_st_le32(DP_DATATYPE, save_dp_datatype | dstval | SRC_DSTCOLOR); - - aty_st_le32(DST_Y_X, (dsty << 16) | dstx); - aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width); - - par->blitter_may_be_busy = 1; - - wait_for_fifo(2, par); - aty_st_le32(DP_DATATYPE, save_dp_datatype); - aty_st_le32(DP_CNTL, save_dp_cntl); -} - - - /* - * Text mode accelerated functions - */ - -static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, - int dx, int height, int width) -{ - sx *= fontwidth(p); - sy *= fontheight(p); - dx *= fontwidth(p); - dy *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); - - aty128_rectcopy(sx, sy, dx, dy, width, height, - (struct fb_info_aty128 *)p->fb_info); -} -#endif /* 0 */ - static void aty128_set_suspend(struct aty128fb_par *par, int suspend) { u32 pmgt; - struct pci_dev *pdev = par->pdev; if (!par->pdev->pm_cap) return; - + /* 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, ...) @@ -2443,23 +2354,15 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) aty_st_le32(BUS_CNTL1, 0x00000010); aty_st_le32(MEM_POWER_MISC, 0x0c830000); msleep(100); - - /* Switch PCI power management to D2 */ - pci_set_power_state(pdev, PCI_D2); } } -static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int aty128_pci_suspend_late(struct device *dev, pm_message_t state) { + struct pci_dev *pdev = to_pci_dev(dev); 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 * can properly take care of D3 ? Also, with swsusp, we @@ -2473,12 +2376,12 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) */ return 0; #endif /* CONFIG_PPC_PMAC */ - + if (state.event == pdev->dev.power.power_state.event) return 0; printk(KERN_DEBUG "aty128fb: suspending...\n"); - + console_lock(); fb_set_suspend(info, 1); @@ -2518,6 +2421,21 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } +static int __maybe_unused aty128_pci_suspend(struct device *dev) +{ + return aty128_pci_suspend_late(dev, PMSG_SUSPEND); +} + +static int __maybe_unused aty128_pci_hibernate(struct device *dev) +{ + return aty128_pci_suspend_late(dev, PMSG_HIBERNATE); +} + +static int __maybe_unused aty128_pci_freeze(struct device *dev) +{ + return aty128_pci_suspend_late(dev, PMSG_FREEZE); +} + static int aty128_do_resume(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); @@ -2564,12 +2482,12 @@ static int aty128_do_resume(struct pci_dev *pdev) return 0; } -static int aty128_pci_resume(struct pci_dev *pdev) +static int __maybe_unused aty128_pci_resume(struct device *dev) { int rc; console_lock(); - rc = aty128_do_resume(pdev); + rc = aty128_do_resume(to_pci_dev(dev)); console_unlock(); return rc; @@ -2580,7 +2498,12 @@ static int aty128fb_init(void) { #ifndef MODULE char *option = NULL; +#endif + if (fb_modesetting_disabled("aty128fb")) + return -ENODEV; + +#ifndef MODULE if (fb_get_options("aty128fb", &option)) return -ENODEV; aty128fb_setup(option); |
