[PATCH] powermac: Combined fixes for backlight code

This patch fixes several problems:
- pmac_backlight_key() is called under interrupt context, and therefore
  can't use mutexes or semaphores, so defer the backlight level for
  later, as it's not critical (original code by Aristeu S. Rozanski F.
  <aris@valeta.org>).
- Add exports for functions that might be called from modules
- Fix Kconfig depdencies on PMAC_BACKLIGHT.
- Fix locking issues on calls from inside the driver (reported by
  Aristeu S. Rozanski F., too)
- Fix wrong calculation of backlight values in some of the drivers
- Replace pmac_backlight_key_up/down by inline functions

[akpm@osdl.org: fix function prototypes]
Signed-off-by: Michael Hanselmann <linux-kernel@hansmi.ch>
Acked-by: Aristeu S. Rozanski F. <aris@valeta.org>
Acked-by: Rene Nussbaumer <linux-kernel@killerfox.forkbomb.ch>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Michael Hanselmann 2006-07-10 04:44:45 -07:00 committed by Linus Torvalds
parent 58d383a622
commit e01af0384f
10 changed files with 162 additions and 97 deletions

View file

@ -15,6 +15,15 @@
#define OLD_BACKLIGHT_MAX 15 #define OLD_BACKLIGHT_MAX 15
static void pmac_backlight_key_worker(void *data);
static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker, NULL);
/* Although this variable is used in interrupt context, it makes no sense to
* protect it. No user is able to produce enough key events per second and
* notice the errors that might happen.
*/
static int pmac_backlight_key_queued;
/* Protect the pmac_backlight variable */ /* Protect the pmac_backlight variable */
DEFINE_MUTEX(pmac_backlight_mutex); DEFINE_MUTEX(pmac_backlight_mutex);
@ -71,7 +80,7 @@ int pmac_backlight_curve_lookup(struct fb_info *info, int value)
return level; return level;
} }
static void pmac_backlight_key(int direction) static void pmac_backlight_key_worker(void *data)
{ {
mutex_lock(&pmac_backlight_mutex); mutex_lock(&pmac_backlight_mutex);
if (pmac_backlight) { if (pmac_backlight) {
@ -82,7 +91,8 @@ static void pmac_backlight_key(int direction)
props = pmac_backlight->props; props = pmac_backlight->props;
brightness = props->brightness + brightness = props->brightness +
((direction?-1:1) * (props->max_brightness / 15)); ((pmac_backlight_key_queued?-1:1) *
(props->max_brightness / 15));
if (brightness < 0) if (brightness < 0)
brightness = 0; brightness = 0;
@ -97,14 +107,13 @@ static void pmac_backlight_key(int direction)
mutex_unlock(&pmac_backlight_mutex); mutex_unlock(&pmac_backlight_mutex);
} }
void pmac_backlight_key_up() void pmac_backlight_key(int direction)
{ {
pmac_backlight_key(0); /* we can receive multiple interrupts here, but the scheduled work
} * will run only once, with the last value
*/
void pmac_backlight_key_down() pmac_backlight_key_queued = direction;
{ schedule_work(&pmac_backlight_key_work);
pmac_backlight_key(1);
} }
int pmac_backlight_set_legacy_brightness(int brightness) int pmac_backlight_set_legacy_brightness(int brightness)
@ -157,3 +166,7 @@ int pmac_backlight_get_legacy_brightness()
return result; return result;
} }
EXPORT_SYMBOL_GPL(pmac_backlight);
EXPORT_SYMBOL_GPL(pmac_backlight_mutex);
EXPORT_SYMBOL_GPL(pmac_has_backlight_type);

View file

@ -113,7 +113,10 @@ config PMAC_MEDIABAY
config PMAC_BACKLIGHT config PMAC_BACKLIGHT
bool "Backlight control for LCD screens" bool "Backlight control for LCD screens"
depends on ADB_PMU && (BROKEN || !PPC64) depends on ADB_PMU && FB = y && (BROKEN || !PPC64)
select FB_BACKLIGHT
select BACKLIGHT_CLASS_DEVICE
select BACKLIGHT_LCD_SUPPORT
help help
Say Y here to enable Macintosh specific extensions of the generic Say Y here to enable Macintosh specific extensions of the generic
backlight code. With this enabled, the brightness keys on older backlight code. With this enabled, the brightness keys on older

View file

@ -455,6 +455,7 @@ static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par);
static void wait_for_fifo(u16 entries, struct aty128fb_par *par); static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
static void wait_for_idle(struct aty128fb_par *par); static void wait_for_idle(struct aty128fb_par *par);
static u32 depth_to_dst(u32 depth); static u32 depth_to_dst(u32 depth);
static void aty128_bl_set_power(struct fb_info *info, int power);
#define BIOS_IN8(v) (readb(bios + (v))) #define BIOS_IN8(v) (readb(bios + (v)))
#define BIOS_IN16(v) (readb(bios + (v)) | \ #define BIOS_IN16(v) (readb(bios + (v)) | \
@ -1257,25 +1258,11 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
reg &= ~LVDS_DISPLAY_DIS; reg &= ~LVDS_DISPLAY_DIS;
aty_st_le32(LVDS_GEN_CNTL, reg); aty_st_le32(LVDS_GEN_CNTL, reg);
#ifdef CONFIG_FB_ATY128_BACKLIGHT #ifdef CONFIG_FB_ATY128_BACKLIGHT
mutex_lock(&info->bl_mutex); aty128_bl_set_power(info, FB_BLANK_UNBLANK);
if (info->bl_dev) {
down(&info->bl_dev->sem);
info->bl_dev->props->update_status(info->bl_dev);
up(&info->bl_dev->sem);
}
mutex_unlock(&info->bl_mutex);
#endif #endif
} else { } else {
#ifdef CONFIG_FB_ATY128_BACKLIGHT #ifdef CONFIG_FB_ATY128_BACKLIGHT
mutex_lock(&info->bl_mutex); aty128_bl_set_power(info, FB_BLANK_POWERDOWN);
if (info->bl_dev) {
down(&info->bl_dev->sem);
info->bl_dev->props->brightness = 0;
info->bl_dev->props->power = FB_BLANK_POWERDOWN;
info->bl_dev->props->update_status(info->bl_dev);
up(&info->bl_dev->sem);
}
mutex_unlock(&info->bl_mutex);
#endif #endif
reg = aty_ld_le32(LVDS_GEN_CNTL); reg = aty_ld_le32(LVDS_GEN_CNTL);
reg |= LVDS_DISPLAY_DIS; reg |= LVDS_DISPLAY_DIS;
@ -1702,6 +1689,7 @@ static int __devinit aty128fb_setup(char *options)
static struct backlight_properties aty128_bl_data; 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, static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
int level) int level)
{ {
@ -1709,10 +1697,8 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
int atylevel; int atylevel;
/* Get and convert the value */ /* Get and convert the value */
mutex_lock(&info->bl_mutex);
atylevel = MAX_LEVEL - atylevel = MAX_LEVEL -
(info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
mutex_unlock(&info->bl_mutex);
if (atylevel < 0) if (atylevel < 0)
atylevel = 0; atylevel = 0;
@ -1730,7 +1716,8 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
/* That one prevents proper CRT output with LCD off */ /* That one prevents proper CRT output with LCD off */
#undef BACKLIGHT_DAC_OFF #undef BACKLIGHT_DAC_OFF
static int aty128_bl_update_status(struct backlight_device *bd) /* 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); struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
@ -1783,6 +1770,19 @@ static int aty128_bl_update_status(struct backlight_device *bd)
return 0; 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) static int aty128_bl_get_brightness(struct backlight_device *bd)
{ {
return bd->props->brightness; return bd->props->brightness;
@ -1795,6 +1795,16 @@ static struct backlight_properties aty128_bl_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1), .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
}; };
static void aty128_bl_set_power(struct fb_info *info, int power)
{
mutex_lock(&info->bl_mutex);
up(&info->bl_dev->sem);
info->bl_dev->props->power = power;
__aty128_bl_update_status(info->bl_dev);
down(&info->bl_dev->sem);
mutex_unlock(&info->bl_mutex);
}
static void aty128_bl_init(struct aty128fb_par *par) static void aty128_bl_init(struct aty128fb_par *par)
{ {
struct fb_info *info = pci_get_drvdata(par->pdev); struct fb_info *info = pci_get_drvdata(par->pdev);
@ -2197,12 +2207,8 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
return 0; return 0;
#ifdef CONFIG_FB_ATY128_BACKLIGHT #ifdef CONFIG_FB_ATY128_BACKLIGHT
if (machine_is(powermac) && blank) { if (machine_is(powermac) && blank)
down(&fb->bl_dev->sem); aty128_bl_set_power(fb, FB_BLANK_POWERDOWN);
fb->bl_dev->props->power = FB_BLANK_POWERDOWN;
fb->bl_dev->props->update_status(fb->bl_dev);
up(&fb->bl_dev->sem);
}
#endif #endif
if (blank & FB_BLANK_VSYNC_SUSPEND) if (blank & FB_BLANK_VSYNC_SUSPEND)
@ -2218,14 +2224,12 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
aty128_set_crt_enable(par, par->crt_on && !blank); aty128_set_crt_enable(par, par->crt_on && !blank);
aty128_set_lcd_enable(par, par->lcd_on && !blank); aty128_set_lcd_enable(par, par->lcd_on && !blank);
} }
#ifdef CONFIG_FB_ATY128_BACKLIGHT #ifdef CONFIG_FB_ATY128_BACKLIGHT
if (machine_is(powermac) && !blank) { if (machine_is(powermac) && !blank)
down(&fb->bl_dev->sem); aty128_bl_set_power(fb, FB_BLANK_UNBLANK);
fb->bl_dev->props->power = FB_BLANK_UNBLANK;
fb->bl_dev->props->update_status(fb->bl_dev);
up(&fb->bl_dev->sem);
}
#endif #endif
return 0; return 0;
} }

View file

@ -2129,15 +2129,14 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
static struct backlight_properties aty_bl_data; static struct backlight_properties aty_bl_data;
/* Call with fb_info->bl_mutex held */
static int aty_bl_get_level_brightness(struct atyfb_par *par, int level) static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
{ {
struct fb_info *info = pci_get_drvdata(par->pdev); struct fb_info *info = pci_get_drvdata(par->pdev);
int atylevel; int atylevel;
/* Get and convert the value */ /* Get and convert the value */
mutex_lock(&info->bl_mutex);
atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
mutex_unlock(&info->bl_mutex);
if (atylevel < 0) if (atylevel < 0)
atylevel = 0; atylevel = 0;
@ -2147,7 +2146,8 @@ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
return atylevel; return atylevel;
} }
static int aty_bl_update_status(struct backlight_device *bd) /* Call with fb_info->bl_mutex held */
static int __aty_bl_update_status(struct backlight_device *bd)
{ {
struct atyfb_par *par = class_get_devdata(&bd->class_dev); struct atyfb_par *par = class_get_devdata(&bd->class_dev);
unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
@ -2172,6 +2172,19 @@ static int aty_bl_update_status(struct backlight_device *bd)
return 0; return 0;
} }
static int aty_bl_update_status(struct backlight_device *bd)
{
struct atyfb_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 = __aty_bl_update_status(bd);
mutex_unlock(&info->bl_mutex);
return ret;
}
static int aty_bl_get_brightness(struct backlight_device *bd) static int aty_bl_get_brightness(struct backlight_device *bd)
{ {
return bd->props->brightness; return bd->props->brightness;
@ -2184,6 +2197,16 @@ static struct backlight_properties aty_bl_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1), .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
}; };
static void aty_bl_set_power(struct fb_info *info, int power)
{
mutex_lock(&info->bl_mutex);
up(&info->bl_dev->sem);
info->bl_dev->props->power = power;
__aty_bl_update_status(info->bl_dev);
down(&info->bl_dev->sem);
mutex_unlock(&info->bl_mutex);
}
static void aty_bl_init(struct atyfb_par *par) static void aty_bl_init(struct atyfb_par *par)
{ {
struct fb_info *info = pci_get_drvdata(par->pdev); struct fb_info *info = pci_get_drvdata(par->pdev);
@ -2790,16 +2813,8 @@ static int atyfb_blank(int blank, struct fb_info *info)
return 0; return 0;
#ifdef CONFIG_PMAC_BACKLIGHT #ifdef CONFIG_PMAC_BACKLIGHT
if (machine_is(powermac) && blank > FB_BLANK_NORMAL) { if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
mutex_lock(&info->bl_mutex); aty_bl_set_power(info, FB_BLANK_POWERDOWN);
if (info->bl_dev) {
down(&info->bl_dev->sem);
info->bl_dev->props->power = FB_BLANK_POWERDOWN;
info->bl_dev->props->update_status(info->bl_dev);
up(&info->bl_dev->sem);
}
mutex_unlock(&info->bl_mutex);
}
#elif defined(CONFIG_FB_ATY_GENERIC_LCD) #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank > FB_BLANK_NORMAL && if (par->lcd_table && blank > FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@ -2830,16 +2845,8 @@ static int atyfb_blank(int blank, struct fb_info *info)
aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
#ifdef CONFIG_PMAC_BACKLIGHT #ifdef CONFIG_PMAC_BACKLIGHT
if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) { if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
mutex_lock(&info->bl_mutex); aty_bl_set_power(info, FB_BLANK_UNBLANK);
if (info->bl_dev) {
down(&info->bl_dev->sem);
info->bl_dev->props->power = FB_BLANK_UNBLANK;
info->bl_dev->props->update_status(info->bl_dev);
up(&info->bl_dev->sem);
}
mutex_unlock(&info->bl_mutex);
}
#elif defined(CONFIG_FB_ATY_GENERIC_LCD) #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank <= FB_BLANK_NORMAL && if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {

View file

@ -149,12 +149,11 @@ static int chipsfb_blank(int blank, struct fb_info *info)
mutex_lock(&pmac_backlight_mutex); mutex_lock(&pmac_backlight_mutex);
if (pmac_backlight) { if (pmac_backlight) {
down(&pmac_backlight->sem);
/* used to disable backlight only for blank > 1, but it seems /* used to disable backlight only for blank > 1, but it seems
* useful at blank = 1 too (saves battery, extends backlight * useful at blank = 1 too (saves battery, extends backlight
* life) * life)
*/ */
down(&pmac_backlight->sem);
if (blank) if (blank)
pmac_backlight->props->power = FB_BLANK_POWERDOWN; pmac_backlight->props->power = FB_BLANK_POWERDOWN;
else else

View file

@ -26,9 +26,11 @@
*/ */
#define MIN_LEVEL 0x158 #define MIN_LEVEL 0x158
#define MAX_LEVEL 0x534 #define MAX_LEVEL 0x534
#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
static struct backlight_properties nvidia_bl_data; static struct backlight_properties nvidia_bl_data;
/* Call with fb_info->bl_mutex held */
static int nvidia_bl_get_level_brightness(struct nvidia_par *par, static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
int level) int level)
{ {
@ -36,9 +38,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
int nlevel; int nlevel;
/* Get and convert the value */ /* Get and convert the value */
mutex_lock(&info->bl_mutex); nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
mutex_unlock(&info->bl_mutex);
if (nlevel < 0) if (nlevel < 0)
nlevel = 0; nlevel = 0;
@ -50,7 +50,8 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
return nlevel; return nlevel;
} }
static int nvidia_bl_update_status(struct backlight_device *bd) /* Call with fb_info->bl_mutex held */
static int __nvidia_bl_update_status(struct backlight_device *bd)
{ {
struct nvidia_par *par = class_get_devdata(&bd->class_dev); struct nvidia_par *par = class_get_devdata(&bd->class_dev);
u32 tmp_pcrt, tmp_pmc, fpcontrol; u32 tmp_pcrt, tmp_pmc, fpcontrol;
@ -84,6 +85,19 @@ static int nvidia_bl_update_status(struct backlight_device *bd)
return 0; return 0;
} }
static int nvidia_bl_update_status(struct backlight_device *bd)
{
struct nvidia_par *par = class_get_devdata(&bd->class_dev);
struct fb_info *info = pci_get_drvdata(par->pci_dev);
int ret;
mutex_lock(&info->bl_mutex);
ret = __nvidia_bl_update_status(bd);
mutex_unlock(&info->bl_mutex);
return ret;
}
static int nvidia_bl_get_brightness(struct backlight_device *bd) static int nvidia_bl_get_brightness(struct backlight_device *bd)
{ {
return bd->props->brightness; return bd->props->brightness;
@ -96,6 +110,16 @@ static struct backlight_properties nvidia_bl_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1), .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
}; };
void nvidia_bl_set_power(struct fb_info *info, int power)
{
mutex_lock(&info->bl_mutex);
up(&info->bl_dev->sem);
info->bl_dev->props->power = power;
__nvidia_bl_update_status(info->bl_dev);
down(&info->bl_dev->sem);
mutex_unlock(&info->bl_mutex);
}
void nvidia_bl_init(struct nvidia_par *par) void nvidia_bl_init(struct nvidia_par *par)
{ {
struct fb_info *info = pci_get_drvdata(par->pci_dev); struct fb_info *info = pci_get_drvdata(par->pci_dev);

View file

@ -68,9 +68,11 @@ extern u8 byte_rev[256];
#ifdef CONFIG_FB_NVIDIA_BACKLIGHT #ifdef CONFIG_FB_NVIDIA_BACKLIGHT
extern void nvidia_bl_init(struct nvidia_par *par); extern void nvidia_bl_init(struct nvidia_par *par);
extern void nvidia_bl_exit(struct nvidia_par *par); extern void nvidia_bl_exit(struct nvidia_par *par);
extern void nvidia_bl_set_power(struct fb_info *info, int power);
#else #else
static inline void nvidia_bl_init(struct nvidia_par *par) {} static inline void nvidia_bl_init(struct nvidia_par *par) {}
static inline void nvidia_bl_exit(struct nvidia_par *par) {} static inline void nvidia_bl_exit(struct nvidia_par *par) {}
static inline void nvidia_bl_set_power(struct fb_info *info, int power) {}
#endif #endif
#endif /* __NV_PROTO_H__ */ #endif /* __NV_PROTO_H__ */

View file

@ -932,16 +932,7 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
NVWriteSeq(par, 0x01, tmp); NVWriteSeq(par, 0x01, tmp);
NVWriteCrtc(par, 0x1a, vesa); NVWriteCrtc(par, 0x1a, vesa);
#ifdef CONFIG_FB_NVIDIA_BACKLIGHT nvidia_bl_set_power(info, blank);
mutex_lock(&info->bl_mutex);
if (info->bl_dev) {
down(&info->bl_dev->sem);
info->bl_dev->props->power = blank;
info->bl_dev->props->update_status(info->bl_dev);
up(&info->bl_dev->sem);
}
mutex_unlock(&info->bl_mutex);
#endif
NVTRACE_LEAVE(); NVTRACE_LEAVE();

View file

@ -277,9 +277,11 @@ static const struct riva_regs reg_template = {
*/ */
#define MIN_LEVEL 0x158 #define MIN_LEVEL 0x158
#define MAX_LEVEL 0x534 #define MAX_LEVEL 0x534
#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
static struct backlight_properties riva_bl_data; static struct backlight_properties riva_bl_data;
/* Call with fb_info->bl_mutex held */
static int riva_bl_get_level_brightness(struct riva_par *par, static int riva_bl_get_level_brightness(struct riva_par *par,
int level) int level)
{ {
@ -287,9 +289,7 @@ static int riva_bl_get_level_brightness(struct riva_par *par,
int nlevel; int nlevel;
/* Get and convert the value */ /* Get and convert the value */
mutex_lock(&info->bl_mutex); nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
mutex_unlock(&info->bl_mutex);
if (nlevel < 0) if (nlevel < 0)
nlevel = 0; nlevel = 0;
@ -301,7 +301,8 @@ static int riva_bl_get_level_brightness(struct riva_par *par,
return nlevel; return nlevel;
} }
static int riva_bl_update_status(struct backlight_device *bd) /* Call with fb_info->bl_mutex held */
static int __riva_bl_update_status(struct backlight_device *bd)
{ {
struct riva_par *par = class_get_devdata(&bd->class_dev); struct riva_par *par = class_get_devdata(&bd->class_dev);
U032 tmp_pcrt, tmp_pmc; U032 tmp_pcrt, tmp_pmc;
@ -326,6 +327,19 @@ static int riva_bl_update_status(struct backlight_device *bd)
return 0; return 0;
} }
static int riva_bl_update_status(struct backlight_device *bd)
{
struct riva_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 = __riva_bl_update_status(bd);
mutex_unlock(&info->bl_mutex);
return ret;
}
static int riva_bl_get_brightness(struct backlight_device *bd) static int riva_bl_get_brightness(struct backlight_device *bd)
{ {
return bd->props->brightness; return bd->props->brightness;
@ -338,6 +352,16 @@ static struct backlight_properties riva_bl_data = {
.max_brightness = (FB_BACKLIGHT_LEVELS - 1), .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
}; };
static void riva_bl_set_power(struct fb_info *info, int power)
{
mutex_lock(&info->bl_mutex);
up(&info->bl_dev->sem);
info->bl_dev->props->power = power;
__riva_bl_update_status(info->bl_dev);
down(&info->bl_dev->sem);
mutex_unlock(&info->bl_mutex);
}
static void riva_bl_init(struct riva_par *par) static void riva_bl_init(struct riva_par *par)
{ {
struct fb_info *info = pci_get_drvdata(par->pdev); struct fb_info *info = pci_get_drvdata(par->pdev);
@ -418,6 +442,7 @@ static void riva_bl_exit(struct riva_par *par)
#else #else
static inline void riva_bl_init(struct riva_par *par) {} static inline void riva_bl_init(struct riva_par *par) {}
static inline void riva_bl_exit(struct riva_par *par) {} static inline void riva_bl_exit(struct riva_par *par) {}
static inline void riva_bl_set_power(struct fb_info *info, int power) {}
#endif /* CONFIG_FB_RIVA_BACKLIGHT */ #endif /* CONFIG_FB_RIVA_BACKLIGHT */
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
@ -1336,16 +1361,7 @@ static int rivafb_blank(int blank, struct fb_info *info)
SEQout(par, 0x01, tmp); SEQout(par, 0x01, tmp);
CRTCout(par, 0x1a, vesa); CRTCout(par, 0x1a, vesa);
#ifdef CONFIG_FB_RIVA_BACKLIGHT riva_bl_set_power(info, blank);
mutex_lock(&info->bl_mutex);
if (info->bl_dev) {
down(&info->bl_dev->sem);
info->bl_dev->props->power = blank;
info->bl_dev->props->update_status(info->bl_dev);
up(&info->bl_dev->sem);
}
mutex_unlock(&info->bl_mutex);
#endif
NVTRACE_LEAVE(); NVTRACE_LEAVE();

View file

@ -16,13 +16,19 @@
extern struct backlight_device *pmac_backlight; extern struct backlight_device *pmac_backlight;
extern struct mutex pmac_backlight_mutex; extern struct mutex pmac_backlight_mutex;
extern void pmac_backlight_calc_curve(struct fb_info*);
extern int pmac_backlight_curve_lookup(struct fb_info *info, int value); extern int pmac_backlight_curve_lookup(struct fb_info *info, int value);
extern int pmac_has_backlight_type(const char *type); extern int pmac_has_backlight_type(const char *type);
extern void pmac_backlight_key_up(void); extern void pmac_backlight_key(int direction);
extern void pmac_backlight_key_down(void); static inline void pmac_backlight_key_up(void)
{
pmac_backlight_key(0);
}
static inline void pmac_backlight_key_down(void)
{
pmac_backlight_key(1);
}
extern int pmac_backlight_set_legacy_brightness(int brightness); extern int pmac_backlight_set_legacy_brightness(int brightness);
extern int pmac_backlight_get_legacy_brightness(void); extern int pmac_backlight_get_legacy_brightness(void);