2006-06-25 16:47:08 +04:00
/*
* Backlight code for nVidia based graphic cards
*
* Copyright 2004 Antonino Daplas < adaplas @ pol . net >
* Copyright ( c ) 2006 Michael Hanselmann < linux - kernel @ hansmi . ch >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/backlight.h>
# include <linux/fb.h>
# include <linux/pci.h>
2007-03-06 12:42:00 +03:00
# ifdef CONFIG_PMAC_BACKLIGHT
# include <asm/backlight.h>
# endif
2006-06-25 16:47:08 +04:00
# include "nv_local.h"
# include "nv_type.h"
# include "nv_proto.h"
/* We do not have any information about which values are allowed, thus
* we used safe values .
*/
# define MIN_LEVEL 0x158
# define MAX_LEVEL 0x534
2006-07-10 15:44:45 +04:00
# define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
2006-06-25 16:47:08 +04:00
static int nvidia_bl_get_level_brightness ( struct nvidia_par * par ,
int level )
{
struct fb_info * info = pci_get_drvdata ( par - > pci_dev ) ;
int nlevel ;
/* Get and convert the value */
2007-02-10 17:10:33 +03:00
/* No locking of bl_curve since we read a single value */
2006-07-10 15:44:45 +04:00
nlevel = MIN_LEVEL + info - > bl_curve [ level ] * LEVEL_STEP ;
2006-06-25 16:47:08 +04:00
if ( nlevel < 0 )
nlevel = 0 ;
else if ( nlevel < MIN_LEVEL )
nlevel = MIN_LEVEL ;
else if ( nlevel > MAX_LEVEL )
nlevel = MAX_LEVEL ;
return nlevel ;
}
2007-02-10 17:10:33 +03:00
static int nvidia_bl_update_status ( struct backlight_device * bd )
2006-06-25 16:47:08 +04:00
{
2007-07-09 15:17:24 +04:00
struct nvidia_par * par = bl_get_data ( bd ) ;
2006-06-25 16:47:08 +04:00
u32 tmp_pcrt , tmp_pmc , fpcontrol ;
int level ;
if ( ! par - > FlatPanel )
return 0 ;
2007-02-11 02:07:48 +03:00
if ( bd - > props . power ! = FB_BLANK_UNBLANK | |
bd - > props . fb_blank ! = FB_BLANK_UNBLANK )
2006-06-25 16:47:08 +04:00
level = 0 ;
else
2007-02-11 02:07:48 +03:00
level = bd - > props . brightness ;
2006-06-25 16:47:08 +04:00
tmp_pmc = NV_RD32 ( par - > PMC , 0x10F0 ) & 0x0000FFFF ;
tmp_pcrt = NV_RD32 ( par - > PCRTC0 , 0x081C ) & 0xFFFFFFFC ;
fpcontrol = NV_RD32 ( par - > PRAMDAC , 0x0848 ) & 0xCFFFFFCC ;
if ( level > 0 ) {
tmp_pcrt | = 0x1 ;
tmp_pmc | = ( 1 < < 31 ) ; /* backlight bit */
tmp_pmc | = nvidia_bl_get_level_brightness ( par , level ) < < 16 ;
fpcontrol | = par - > fpSyncs ;
} else
fpcontrol | = 0x20000022 ;
NV_WR32 ( par - > PCRTC0 , 0x081C , tmp_pcrt ) ;
NV_WR32 ( par - > PMC , 0x10F0 , tmp_pmc ) ;
NV_WR32 ( par - > PRAMDAC , 0x848 , fpcontrol ) ;
return 0 ;
}
static int nvidia_bl_get_brightness ( struct backlight_device * bd )
{
2007-02-11 02:07:48 +03:00
return bd - > props . brightness ;
2006-06-25 16:47:08 +04:00
}
2007-02-11 02:07:48 +03:00
static struct backlight_ops nvidia_bl_ops = {
2006-06-25 16:47:08 +04:00
. get_brightness = nvidia_bl_get_brightness ,
. update_status = nvidia_bl_update_status ,
} ;
void nvidia_bl_init ( struct nvidia_par * par )
{
struct fb_info * info = pci_get_drvdata ( par - > pci_dev ) ;
struct backlight_device * bd ;
char name [ 12 ] ;
if ( ! par - > FlatPanel )
return ;
# ifdef CONFIG_PMAC_BACKLIGHT
if ( ! machine_is ( powermac ) | |
! pmac_has_backlight_type ( " mnca " ) )
return ;
# endif
snprintf ( name , sizeof ( name ) , " nvidiabl%d " , info - > node ) ;
2007-02-11 02:07:48 +03:00
bd = backlight_device_register ( name , info - > dev , par , & nvidia_bl_ops ) ;
2006-06-25 16:47:08 +04:00
if ( IS_ERR ( bd ) ) {
info - > bl_dev = NULL ;
2006-08-31 08:04:34 +04:00
printk ( KERN_WARNING " nvidia: Backlight registration failed \n " ) ;
2006-06-25 16:47:08 +04:00
goto error ;
}
info - > bl_dev = bd ;
fb_bl_default_curve ( info , 0 ,
0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL ,
0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL ) ;
2007-02-11 02:07:48 +03:00
bd - > props . max_brightness = FB_BACKLIGHT_LEVELS - 1 ;
2007-02-27 01:06:09 +03:00
bd - > props . brightness = bd - > props . max_brightness ;
2007-02-11 02:07:48 +03:00
bd - > props . power = FB_BLANK_UNBLANK ;
2007-02-09 01:25:09 +03:00
backlight_update_status ( bd ) ;
2006-06-25 16:47:08 +04:00
printk ( " nvidia: Backlight initialized (%s) \n " , name ) ;
return ;
error :
return ;
}
void nvidia_bl_exit ( struct nvidia_par * par )
{
struct fb_info * info = pci_get_drvdata ( par - > pci_dev ) ;
2007-02-10 17:10:33 +03:00
struct backlight_device * bd = info - > bl_dev ;
2006-06-25 16:47:08 +04:00
2007-02-10 18:04:08 +03:00
backlight_device_unregister ( bd ) ;
printk ( " nvidia: Backlight unloaded \n " ) ;
2006-06-25 16:47:08 +04:00
}