1
0

[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

@@ -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_idle(struct aty128fb_par *par);
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_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;
aty_st_le32(LVDS_GEN_CNTL, reg);
#ifdef CONFIG_FB_ATY128_BACKLIGHT
mutex_lock(&info->bl_mutex);
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);
aty128_bl_set_power(info, FB_BLANK_UNBLANK);
#endif
} else {
#ifdef CONFIG_FB_ATY128_BACKLIGHT
mutex_lock(&info->bl_mutex);
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);
aty128_bl_set_power(info, FB_BLANK_POWERDOWN);
#endif
reg = aty_ld_le32(LVDS_GEN_CNTL);
reg |= LVDS_DISPLAY_DIS;
@@ -1702,6 +1689,7 @@ static int __devinit aty128fb_setup(char *options)
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)
{
@@ -1709,10 +1697,8 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
int atylevel;
/* Get and convert the value */
mutex_lock(&info->bl_mutex);
atylevel = MAX_LEVEL -
(info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
mutex_unlock(&info->bl_mutex);
if (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 */
#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);
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;
}
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;
@@ -1795,6 +1795,16 @@ static struct backlight_properties aty128_bl_data = {
.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)
{
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;
#ifdef CONFIG_FB_ATY128_BACKLIGHT
if (machine_is(powermac) && blank) {
down(&fb->bl_dev->sem);
fb->bl_dev->props->power = FB_BLANK_POWERDOWN;
fb->bl_dev->props->update_status(fb->bl_dev);
up(&fb->bl_dev->sem);
}
if (machine_is(powermac) && blank)
aty128_bl_set_power(fb, FB_BLANK_POWERDOWN);
#endif
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_lcd_enable(par, par->lcd_on && !blank);
}
#ifdef CONFIG_FB_ATY128_BACKLIGHT
if (machine_is(powermac) && !blank) {
down(&fb->bl_dev->sem);
fb->bl_dev->props->power = FB_BLANK_UNBLANK;
fb->bl_dev->props->update_status(fb->bl_dev);
up(&fb->bl_dev->sem);
}
if (machine_is(powermac) && !blank)
aty128_bl_set_power(fb, FB_BLANK_UNBLANK);
#endif
return 0;
}

View File

@@ -2129,15 +2129,14 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
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)
{
struct fb_info *info = pci_get_drvdata(par->pdev);
int atylevel;
/* Get and convert the value */
mutex_lock(&info->bl_mutex);
atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
mutex_unlock(&info->bl_mutex);
if (atylevel < 0)
atylevel = 0;
@@ -2147,7 +2146,8 @@ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
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);
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;
}
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)
{
return bd->props->brightness;
@@ -2184,6 +2197,16 @@ static struct backlight_properties aty_bl_data = {
.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)
{
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;
#ifdef CONFIG_PMAC_BACKLIGHT
if (machine_is(powermac) && blank > FB_BLANK_NORMAL) {
mutex_lock(&info->bl_mutex);
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);
}
if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
aty_bl_set_power(info, FB_BLANK_POWERDOWN);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank > FB_BLANK_NORMAL &&
(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);
#ifdef CONFIG_PMAC_BACKLIGHT
if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) {
mutex_lock(&info->bl_mutex);
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);
}
if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
aty_bl_set_power(info, FB_BLANK_UNBLANK);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
(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);
if (pmac_backlight) {
down(&pmac_backlight->sem);
/* used to disable backlight only for blank > 1, but it seems
* useful at blank = 1 too (saves battery, extends backlight
* life)
*/
down(&pmac_backlight->sem);
if (blank)
pmac_backlight->props->power = FB_BLANK_POWERDOWN;
else

View File

@@ -26,9 +26,11 @@
*/
#define MIN_LEVEL 0x158
#define MAX_LEVEL 0x534
#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
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,
int level)
{
@@ -36,9 +38,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
int nlevel;
/* Get and convert the value */
mutex_lock(&info->bl_mutex);
nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
mutex_unlock(&info->bl_mutex);
nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
if (nlevel < 0)
nlevel = 0;
@@ -50,7 +50,8 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
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);
u32 tmp_pcrt, tmp_pmc, fpcontrol;
@@ -84,6 +85,19 @@ static int nvidia_bl_update_status(struct backlight_device *bd)
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)
{
return bd->props->brightness;
@@ -96,6 +110,16 @@ static struct backlight_properties nvidia_bl_data = {
.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)
{
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
extern void nvidia_bl_init(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
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_set_power(struct fb_info *info, int power) {}
#endif
#endif /* __NV_PROTO_H__ */

View File

@@ -932,16 +932,7 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
NVWriteSeq(par, 0x01, tmp);
NVWriteCrtc(par, 0x1a, vesa);
#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
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
nvidia_bl_set_power(info, blank);
NVTRACE_LEAVE();

View File

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