2006-06-21 14:11:16 +04:00
/*
* via - pmu LED class device
*
* Copyright 2006 Johannes Berg < johannes @ sipsolutions . net >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE , GOOD TITLE or
* NON INFRINGEMENT . See the GNU General Public License for more
* details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*
*/
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/device.h>
# include <linux/leds.h>
# include <linux/adb.h>
# include <linux/pmu.h>
# include <asm/prom.h>
static spinlock_t pmu_blink_lock ;
static struct adb_request pmu_blink_req ;
/* -1: no change, 0: request off, 1: request on */
static int requested_change ;
static void pmu_req_done ( struct adb_request * req )
{
unsigned long flags ;
spin_lock_irqsave ( & pmu_blink_lock , flags ) ;
/* if someone requested a change in the meantime
* ( we only see the last one which is fine )
* then apply it now */
2007-05-07 19:08:00 +04:00
if ( requested_change ! = - 1 & & ! pmu_sys_suspended )
2006-06-21 14:11:16 +04:00
pmu_request ( & pmu_blink_req , NULL , 4 , 0xee , 4 , 0 , requested_change ) ;
/* reset requested change */
requested_change = - 1 ;
spin_unlock_irqrestore ( & pmu_blink_lock , flags ) ;
}
static void pmu_led_set ( struct led_classdev * led_cdev ,
enum led_brightness brightness )
{
unsigned long flags ;
spin_lock_irqsave ( & pmu_blink_lock , flags ) ;
switch ( brightness ) {
case LED_OFF :
requested_change = 0 ;
break ;
case LED_FULL :
requested_change = 1 ;
break ;
default :
goto out ;
break ;
}
/* if request isn't done, then don't do anything */
2007-05-07 19:08:00 +04:00
if ( pmu_blink_req . complete & & ! pmu_sys_suspended )
2006-06-21 14:11:16 +04:00
pmu_request ( & pmu_blink_req , NULL , 4 , 0xee , 4 , 0 , requested_change ) ;
out :
spin_unlock_irqrestore ( & pmu_blink_lock , flags ) ;
}
static struct led_classdev pmu_led = {
. name = " pmu-front-led " ,
2006-07-03 16:28:14 +04:00
# ifdef CONFIG_ADB_PMU_LED_IDE
2006-06-21 14:11:16 +04:00
. default_trigger = " ide-disk " ,
# endif
. brightness_set = pmu_led_set ,
} ;
static int __init via_pmu_led_init ( void )
{
struct device_node * dt ;
const char * model ;
/* only do this on keylargo based models */
if ( pmu_get_model ( ) ! = PMU_KEYLARGO_BASED )
return - ENODEV ;
dt = of_find_node_by_path ( " / " ) ;
if ( dt = = NULL )
return - ENODEV ;
2007-04-27 07:41:15 +04:00
model = of_get_property ( dt , " model " , NULL ) ;
2006-06-21 14:11:16 +04:00
if ( model = = NULL )
return - ENODEV ;
if ( strncmp ( model , " PowerBook " , strlen ( " PowerBook " ) ) ! = 0 & &
2007-03-23 02:31:08 +03:00
strncmp ( model , " iBook " , strlen ( " iBook " ) ) ! = 0 & &
strcmp ( model , " PowerMac7,2 " ) ! = 0 & &
strcmp ( model , " PowerMac7,3 " ) ! = 0 ) {
2006-06-21 14:11:16 +04:00
of_node_put ( dt ) ;
/* ignore */
return - ENODEV ;
}
of_node_put ( dt ) ;
spin_lock_init ( & pmu_blink_lock ) ;
/* no outstanding req */
pmu_blink_req . complete = 1 ;
pmu_blink_req . done = pmu_req_done ;
2007-05-07 19:08:00 +04:00
2006-06-21 14:11:16 +04:00
return led_classdev_register ( NULL , & pmu_led ) ;
}
late_initcall ( via_pmu_led_init ) ;