2005-09-06 15:16:45 -07:00
/*
* Backlight control code for Sharp Zaurus SL - 5500
*
* Copyright 2005 John Lenz < lenz @ cs . wisc . edu >
* Maintainer : Pavel Machek < pavel @ suse . cz > ( unless John wants to : - )
* GPL v2
*
* This driver assumes single CPU . That ' s okay , because collie is
* slightly old hardware , and noone is going to retrofit second CPU to
* old PDA .
*/
/* LCD power functions */
# include <linux/module.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/device.h>
# include <linux/interrupt.h>
2006-06-26 00:26:27 -07:00
# include <linux/fb.h>
# include <linux/backlight.h>
2005-09-06 15:16:45 -07:00
# include <asm/hardware/locomo.h>
# include <asm/irq.h>
2006-03-25 03:07:33 -08:00
# include <asm/mach/sharpsl_param.h>
# include <asm/mach-types.h>
2005-09-06 15:16:45 -07:00
2006-03-25 03:07:33 -08:00
# include "../../../arch/arm/mach-sa1100/generic.h"
2005-09-06 15:16:45 -07:00
2006-06-26 00:26:27 -07:00
static struct backlight_device * locomolcd_bl_device ;
2005-09-06 15:16:45 -07:00
static struct locomo_dev * locomolcd_dev ;
2006-06-26 00:26:27 -07:00
static unsigned long locomolcd_flags ;
# define LOCOMOLCD_SUSPENDED 0x01
2005-09-06 15:16:45 -07:00
static void locomolcd_on ( int comadj )
{
2006-09-25 20:11:48 +01:00
locomo_gpio_set_dir ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_VSHA_ON , 0 ) ;
locomo_gpio_write ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_VSHA_ON , 1 ) ;
2005-09-06 15:16:45 -07:00
mdelay ( 2 ) ;
2006-09-25 20:11:48 +01:00
locomo_gpio_set_dir ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_VSHD_ON , 0 ) ;
locomo_gpio_write ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_VSHD_ON , 1 ) ;
2005-09-06 15:16:45 -07:00
mdelay ( 2 ) ;
locomo_m62332_senddata ( locomolcd_dev , comadj , 0 ) ;
mdelay ( 5 ) ;
2006-09-25 20:11:48 +01:00
locomo_gpio_set_dir ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_VEE_ON , 0 ) ;
locomo_gpio_write ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_VEE_ON , 1 ) ;
2005-09-06 15:16:45 -07:00
mdelay ( 10 ) ;
/* TFTCRST | CPSOUT=0 | CPSEN */
locomo_writel ( 0x01 , locomolcd_dev - > mapbase + LOCOMO_TC ) ;
/* Set CPSD */
locomo_writel ( 6 , locomolcd_dev - > mapbase + LOCOMO_CPSD ) ;
/* TFTCRST | CPSOUT=0 | CPSEN */
locomo_writel ( ( 0x04 | 0x01 ) , locomolcd_dev - > mapbase + LOCOMO_TC ) ;
mdelay ( 10 ) ;
2006-09-25 20:11:48 +01:00
locomo_gpio_set_dir ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_MOD , 0 ) ;
locomo_gpio_write ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_MOD , 1 ) ;
2005-09-06 15:16:45 -07:00
}
static void locomolcd_off ( int comadj )
{
/* TFTCRST=1 | CPSOUT=1 | CPSEN = 0 */
locomo_writel ( 0x06 , locomolcd_dev - > mapbase + LOCOMO_TC ) ;
mdelay ( 1 ) ;
2006-09-25 20:11:48 +01:00
locomo_gpio_write ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_VSHA_ON , 0 ) ;
2005-09-06 15:16:45 -07:00
mdelay ( 110 ) ;
2006-09-25 20:11:48 +01:00
locomo_gpio_write ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_VEE_ON , 0 ) ;
2005-09-06 15:16:45 -07:00
mdelay ( 700 ) ;
/* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */
locomo_writel ( 0 , locomolcd_dev - > mapbase + LOCOMO_TC ) ;
2006-09-25 20:11:48 +01:00
locomo_gpio_write ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_MOD , 0 ) ;
locomo_gpio_write ( locomolcd_dev - > dev . parent , LOCOMO_GPIO_LCD_VSHD_ON , 0 ) ;
2005-09-06 15:16:45 -07:00
}
void locomolcd_power ( int on )
{
2006-03-25 03:07:33 -08:00
int comadj = sharpsl_param . comadj ;
2005-09-06 15:16:45 -07:00
unsigned long flags ;
local_irq_save ( flags ) ;
if ( ! locomolcd_dev ) {
local_irq_restore ( flags ) ;
return ;
}
/* read comadj */
2006-06-26 00:26:27 -07:00
if ( comadj = = - 1 & & machine_is_collie ( ) )
comadj = 128 ;
if ( comadj = = - 1 & & machine_is_poodle ( ) )
comadj = 118 ;
2005-09-06 15:16:45 -07:00
if ( on )
locomolcd_on ( comadj ) ;
else
locomolcd_off ( comadj ) ;
local_irq_restore ( flags ) ;
}
EXPORT_SYMBOL ( locomolcd_power ) ;
2006-06-26 00:26:27 -07:00
static int current_intensity ;
static int locomolcd_set_intensity ( struct backlight_device * bd )
{
2007-02-10 23:07:48 +00:00
int intensity = bd - > props . brightness ;
2006-06-26 00:26:27 -07:00
2007-02-10 23:07:48 +00:00
if ( bd - > props . power ! = FB_BLANK_UNBLANK )
2006-06-26 00:26:27 -07:00
intensity = 0 ;
2007-02-10 23:07:48 +00:00
if ( bd - > props . fb_blank ! = FB_BLANK_UNBLANK )
2006-06-26 00:26:27 -07:00
intensity = 0 ;
if ( locomolcd_flags & LOCOMOLCD_SUSPENDED )
intensity = 0 ;
switch ( intensity ) {
/* AC and non-AC are handled differently, but produce same results in sharp code? */
case 0 : locomo_frontlight_set ( locomolcd_dev , 0 , 0 , 161 ) ; break ;
case 1 : locomo_frontlight_set ( locomolcd_dev , 117 , 0 , 161 ) ; break ;
case 2 : locomo_frontlight_set ( locomolcd_dev , 163 , 0 , 148 ) ; break ;
case 3 : locomo_frontlight_set ( locomolcd_dev , 194 , 0 , 161 ) ; break ;
case 4 : locomo_frontlight_set ( locomolcd_dev , 194 , 1 , 161 ) ; break ;
default :
return - ENODEV ;
}
current_intensity = intensity ;
return 0 ;
}
static int locomolcd_get_intensity ( struct backlight_device * bd )
{
return current_intensity ;
}
2009-12-14 00:58:57 +01:00
static const struct backlight_ops locomobl_data = {
2006-06-26 00:26:27 -07:00
. get_brightness = locomolcd_get_intensity ,
. update_status = locomolcd_set_intensity ,
} ;
# ifdef CONFIG_PM
static int locomolcd_suspend ( struct locomo_dev * dev , pm_message_t state )
{
locomolcd_flags | = LOCOMOLCD_SUSPENDED ;
locomolcd_set_intensity ( locomolcd_bl_device ) ;
return 0 ;
}
static int locomolcd_resume ( struct locomo_dev * dev )
{
locomolcd_flags & = ~ LOCOMOLCD_SUSPENDED ;
locomolcd_set_intensity ( locomolcd_bl_device ) ;
return 0 ;
}
# else
# define locomolcd_suspend NULL
# define locomolcd_resume NULL
# endif
2006-09-25 20:11:48 +01:00
static int locomolcd_probe ( struct locomo_dev * ldev )
2005-09-06 15:16:45 -07:00
{
2010-02-17 16:39:44 -05:00
struct backlight_properties props ;
2005-09-06 15:16:45 -07:00
unsigned long flags ;
local_irq_save ( flags ) ;
2006-09-25 20:11:48 +01:00
locomolcd_dev = ldev ;
2005-09-06 15:16:45 -07:00
2006-09-25 20:11:48 +01:00
locomo_gpio_set_dir ( ldev - > dev . parent , LOCOMO_GPIO_FL_VR , 0 ) ;
2006-06-26 00:26:27 -07:00
2005-09-06 15:16:45 -07:00
/* the poodle_lcd_power function is called for the first time
* from fs_initcall , which is before locomo is activated .
* We need to recall poodle_lcd_power here */
2006-06-26 00:26:27 -07:00
if ( machine_is_poodle ( ) )
locomolcd_power ( 1 ) ;
2005-09-06 15:16:45 -07:00
local_irq_restore ( flags ) ;
2006-06-26 00:26:27 -07:00
2010-02-17 16:39:44 -05:00
memset ( & props , 0 , sizeof ( struct backlight_properties ) ) ;
props . max_brightness = 4 ;
locomolcd_bl_device = backlight_device_register ( " locomo-bl " ,
& ldev - > dev , NULL ,
& locomobl_data , & props ) ;
2006-06-26 00:26:27 -07:00
if ( IS_ERR ( locomolcd_bl_device ) )
return PTR_ERR ( locomolcd_bl_device ) ;
/* Set up frontlight so that screen is readable */
2007-02-10 23:07:48 +00:00
locomolcd_bl_device - > props . brightness = 2 ;
2006-06-26 00:26:27 -07:00
locomolcd_set_intensity ( locomolcd_bl_device ) ;
2005-09-06 15:16:45 -07:00
return 0 ;
}
2006-06-26 00:26:27 -07:00
static int locomolcd_remove ( struct locomo_dev * dev )
2005-09-06 15:16:45 -07:00
{
unsigned long flags ;
2006-06-26 00:26:27 -07:00
2007-03-07 00:29:33 +01:00
locomolcd_bl_device - > props . brightness = 0 ;
locomolcd_bl_device - > props . power = 0 ;
2006-12-08 02:40:49 -08:00
locomolcd_set_intensity ( locomolcd_bl_device ) ;
2006-06-26 00:26:27 -07:00
backlight_device_unregister ( locomolcd_bl_device ) ;
2005-09-06 15:16:45 -07:00
local_irq_save ( flags ) ;
locomolcd_dev = NULL ;
local_irq_restore ( flags ) ;
return 0 ;
}
static struct locomo_driver poodle_lcd_driver = {
. drv = {
. name = " locomo-backlight " ,
} ,
. devid = LOCOMO_DEVID_BACKLIGHT ,
2006-06-26 00:26:27 -07:00
. probe = locomolcd_probe ,
. remove = locomolcd_remove ,
. suspend = locomolcd_suspend ,
. resume = locomolcd_resume ,
2005-09-06 15:16:45 -07:00
} ;
2006-06-26 00:26:27 -07:00
static int __init locomolcd_init ( void )
2005-09-06 15:16:45 -07:00
{
int ret = locomo_driver_register ( & poodle_lcd_driver ) ;
2006-06-26 00:26:27 -07:00
if ( ret )
return ret ;
2005-09-06 15:16:45 -07:00
# ifdef CONFIG_SA1100_COLLIE
sa1100fb_lcd_power = locomolcd_power ;
# endif
return 0 ;
}
2006-06-26 00:26:27 -07:00
static void __exit locomolcd_exit ( void )
{
locomo_driver_unregister ( & poodle_lcd_driver ) ;
}
module_init ( locomolcd_init ) ;
module_exit ( locomolcd_exit ) ;
MODULE_AUTHOR ( " John Lenz <lenz@cs.wisc.edu>, Pavel Machek <pavel@suse.cz> " ) ;
MODULE_DESCRIPTION ( " Collie LCD driver " ) ;
MODULE_LICENSE ( " GPL " ) ;