aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/aty/atyfb_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/aty/atyfb_base.c')
-rw-r--r--drivers/video/aty/atyfb_base.c178
1 files changed, 151 insertions, 27 deletions
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index c054bb28b1c4..c5185f7cf4ba 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -66,6 +66,7 @@
66#include <linux/interrupt.h> 66#include <linux/interrupt.h>
67#include <linux/spinlock.h> 67#include <linux/spinlock.h>
68#include <linux/wait.h> 68#include <linux/wait.h>
69#include <linux/backlight.h>
69 70
70#include <asm/io.h> 71#include <asm/io.h>
71#include <asm/uaccess.h> 72#include <asm/uaccess.h>
@@ -2115,45 +2116,142 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
2115 2116
2116#endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */ 2117#endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */
2117 2118
2118#ifdef CONFIG_PMAC_BACKLIGHT 2119/* Backlight */
2120#ifdef CONFIG_FB_ATY_BACKLIGHT
2121#define MAX_LEVEL 0xFF
2119 2122
2120 /* 2123static struct backlight_properties aty_bl_data;
2121 * LCD backlight control
2122 */
2123 2124
2124static int backlight_conv[] = { 2125static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
2125 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d, 2126{
2126 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff 2127 struct fb_info *info = pci_get_drvdata(par->pdev);
2127}; 2128 int atylevel;
2129
2130 /* Get and convert the value */
2131 mutex_lock(&info->bl_mutex);
2132 atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
2133 mutex_unlock(&info->bl_mutex);
2134
2135 if (atylevel < 0)
2136 atylevel = 0;
2137 else if (atylevel > MAX_LEVEL)
2138 atylevel = MAX_LEVEL;
2128 2139
2129static int aty_set_backlight_enable(int on, int level, void *data) 2140 return atylevel;
2141}
2142
2143static int aty_bl_update_status(struct backlight_device *bd)
2130{ 2144{
2131 struct fb_info *info = (struct fb_info *) data; 2145 struct atyfb_par *par = class_get_devdata(&bd->class_dev);
2132 struct atyfb_par *par = (struct atyfb_par *) info->par;
2133 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); 2146 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
2147 int level;
2148
2149 if (bd->props->power != FB_BLANK_UNBLANK ||
2150 bd->props->fb_blank != FB_BLANK_UNBLANK)
2151 level = 0;
2152 else
2153 level = bd->props->brightness;
2134 2154
2135 reg |= (BLMOD_EN | BIASMOD_EN); 2155 reg |= (BLMOD_EN | BIASMOD_EN);
2136 if (on && level > BACKLIGHT_OFF) { 2156 if (level > 0) {
2137 reg &= ~BIAS_MOD_LEVEL_MASK; 2157 reg &= ~BIAS_MOD_LEVEL_MASK;
2138 reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT); 2158 reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);
2139 } else { 2159 } else {
2140 reg &= ~BIAS_MOD_LEVEL_MASK; 2160 reg &= ~BIAS_MOD_LEVEL_MASK;
2141 reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT); 2161 reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);
2142 } 2162 }
2143 aty_st_lcd(LCD_MISC_CNTL, reg, par); 2163 aty_st_lcd(LCD_MISC_CNTL, reg, par);
2164
2144 return 0; 2165 return 0;
2145} 2166}
2146 2167
2147static int aty_set_backlight_level(int level, void *data) 2168static int aty_bl_get_brightness(struct backlight_device *bd)
2148{ 2169{
2149 return aty_set_backlight_enable(1, level, data); 2170 return bd->props->brightness;
2150} 2171}
2151 2172
2152static struct backlight_controller aty_backlight_controller = { 2173static struct backlight_properties aty_bl_data = {
2153 aty_set_backlight_enable, 2174 .owner = THIS_MODULE,
2154 aty_set_backlight_level 2175 .get_brightness = aty_bl_get_brightness,
2176 .update_status = aty_bl_update_status,
2177 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
2155}; 2178};
2156#endif /* CONFIG_PMAC_BACKLIGHT */ 2179
2180static void aty_bl_init(struct atyfb_par *par)
2181{
2182 struct fb_info *info = pci_get_drvdata(par->pdev);
2183 struct backlight_device *bd;
2184 char name[12];
2185
2186#ifdef CONFIG_PMAC_BACKLIGHT
2187 if (!pmac_has_backlight_type("ati"))
2188 return;
2189#endif
2190
2191 snprintf(name, sizeof(name), "atybl%d", info->node);
2192
2193 bd = backlight_device_register(name, par, &aty_bl_data);
2194 if (IS_ERR(bd)) {
2195 info->bl_dev = NULL;
2196 printk("aty: Backlight registration failed\n");
2197 goto error;
2198 }
2199
2200 mutex_lock(&info->bl_mutex);
2201 info->bl_dev = bd;
2202 fb_bl_default_curve(info, 0,
2203 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
2204 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
2205 mutex_unlock(&info->bl_mutex);
2206
2207 up(&bd->sem);
2208 bd->props->brightness = aty_bl_data.max_brightness;
2209 bd->props->power = FB_BLANK_UNBLANK;
2210 bd->props->update_status(bd);
2211 down(&bd->sem);
2212
2213#ifdef CONFIG_PMAC_BACKLIGHT
2214 mutex_lock(&pmac_backlight_mutex);
2215 if (!pmac_backlight)
2216 pmac_backlight = bd;
2217 mutex_unlock(&pmac_backlight_mutex);
2218#endif
2219
2220 printk("aty: Backlight initialized (%s)\n", name);
2221
2222 return;
2223
2224error:
2225 return;
2226}
2227
2228static void aty_bl_exit(struct atyfb_par *par)
2229{
2230 struct fb_info *info = pci_get_drvdata(par->pdev);
2231
2232#ifdef CONFIG_PMAC_BACKLIGHT
2233 mutex_lock(&pmac_backlight_mutex);
2234#endif
2235
2236 mutex_lock(&info->bl_mutex);
2237 if (info->bl_dev) {
2238#ifdef CONFIG_PMAC_BACKLIGHT
2239 if (pmac_backlight == info->bl_dev)
2240 pmac_backlight = NULL;
2241#endif
2242
2243 backlight_device_unregister(info->bl_dev);
2244
2245 printk("aty: Backlight unloaded\n");
2246 }
2247 mutex_unlock(&info->bl_mutex);
2248
2249#ifdef CONFIG_PMAC_BACKLIGHT
2250 mutex_unlock(&pmac_backlight_mutex);
2251#endif
2252}
2253
2254#endif /* CONFIG_FB_ATY_BACKLIGHT */
2157 2255
2158static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) 2256static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
2159{ 2257{
@@ -2513,9 +2611,13 @@ static int __init aty_init(struct fb_info *info, const char *name)
2513 /* these bits let the 101 powerbook wake up from sleep -- paulus */ 2611 /* these bits let the 101 powerbook wake up from sleep -- paulus */
2514 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) 2612 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par)
2515 | (USE_F32KHZ | TRISTATE_MEM_EN), par); 2613 | (USE_F32KHZ | TRISTATE_MEM_EN), par);
2516 } else if (M64_HAS(MOBIL_BUS)) 2614 } else
2517 register_backlight_controller(&aty_backlight_controller, info, "ati"); 2615#endif
2518#endif /* CONFIG_PMAC_BACKLIGHT */ 2616 if (M64_HAS(MOBIL_BUS)) {
2617#ifdef CONFIG_FB_ATY_BACKLIGHT
2618 aty_bl_init (par);
2619#endif
2620 }
2519 2621
2520 memset(&var, 0, sizeof(var)); 2622 memset(&var, 0, sizeof(var));
2521#ifdef CONFIG_PPC 2623#ifdef CONFIG_PPC
@@ -2674,8 +2776,16 @@ static int atyfb_blank(int blank, struct fb_info *info)
2674 return 0; 2776 return 0;
2675 2777
2676#ifdef CONFIG_PMAC_BACKLIGHT 2778#ifdef CONFIG_PMAC_BACKLIGHT
2677 if (machine_is(powermac) && blank > FB_BLANK_NORMAL) 2779 if (machine_is(powermac) && blank > FB_BLANK_NORMAL) {
2678 set_backlight_enable(0); 2780 mutex_lock(&info->bl_mutex);
2781 if (info->bl_dev) {
2782 down(&info->bl_dev->sem);
2783 info->bl_dev->props->power = FB_BLANK_POWERDOWN;
2784 info->bl_dev->props->update_status(info->bl_dev);
2785 up(&info->bl_dev->sem);
2786 }
2787 mutex_unlock(&info->bl_mutex);
2788 }
2679#elif defined(CONFIG_FB_ATY_GENERIC_LCD) 2789#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2680 if (par->lcd_table && blank > FB_BLANK_NORMAL && 2790 if (par->lcd_table && blank > FB_BLANK_NORMAL &&
2681 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { 2791 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2706,8 +2816,16 @@ static int atyfb_blank(int blank, struct fb_info *info)
2706 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); 2816 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
2707 2817
2708#ifdef CONFIG_PMAC_BACKLIGHT 2818#ifdef CONFIG_PMAC_BACKLIGHT
2709 if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) 2819 if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) {
2710 set_backlight_enable(1); 2820 mutex_lock(&info->bl_mutex);
2821 if (info->bl_dev) {
2822 down(&info->bl_dev->sem);
2823 info->bl_dev->props->power = FB_BLANK_UNBLANK;
2824 info->bl_dev->props->update_status(info->bl_dev);
2825 up(&info->bl_dev->sem);
2826 }
2827 mutex_unlock(&info->bl_mutex);
2828 }
2711#elif defined(CONFIG_FB_ATY_GENERIC_LCD) 2829#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2712 if (par->lcd_table && blank <= FB_BLANK_NORMAL && 2830 if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
2713 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { 2831 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -3440,6 +3558,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
3440 par->res_start = res_start; 3558 par->res_start = res_start;
3441 par->res_size = res_size; 3559 par->res_size = res_size;
3442 par->irq = pdev->irq; 3560 par->irq = pdev->irq;
3561 par->pdev = pdev;
3443 3562
3444 /* Setup "info" structure */ 3563 /* Setup "info" structure */
3445#ifdef __sparc__ 3564#ifdef __sparc__
@@ -3571,6 +3690,11 @@ static void __devexit atyfb_remove(struct fb_info *info)
3571 aty_set_crtc(par, &saved_crtc); 3690 aty_set_crtc(par, &saved_crtc);
3572 par->pll_ops->set_pll(info, &saved_pll); 3691 par->pll_ops->set_pll(info, &saved_pll);
3573 3692
3693#ifdef CONFIG_FB_ATY_BACKLIGHT
3694 if (M64_HAS(MOBIL_BUS))
3695 aty_bl_exit(par);
3696#endif
3697
3574 unregister_framebuffer(info); 3698 unregister_framebuffer(info);
3575 3699
3576#ifdef CONFIG_MTRR 3700#ifdef CONFIG_MTRR