2012-07-30 23:38:28 +04:00
/***************************************************************************
* Copyright ( C ) 2010 - 2012 by Bruno Prémont < bonbons @ linux - vserver . org > *
* *
* Based on Logitech G13 driver ( v0 .4 ) *
* Copyright ( C ) 2009 by Rick L . Vinyard , Jr . < rvinyard @ cs . nmsu . edu > *
* *
* 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 , version 2 of the License . *
* *
* This driver 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 . See the GNU *
* General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this software . If not see < http : //www.gnu.org/licenses/>. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <linux/hid.h>
# include <linux/fb.h>
# include <linux/lcd.h>
# include "hid-picolcd.h"
/*
* lcd class device
*/
static int picolcd_get_contrast ( struct lcd_device * ldev )
{
struct picolcd_data * data = lcd_get_data ( ldev ) ;
return data - > lcd_contrast ;
}
static int picolcd_set_contrast ( struct lcd_device * ldev , int contrast )
{
struct picolcd_data * data = lcd_get_data ( ldev ) ;
struct hid_report * report = picolcd_out_report ( REPORT_CONTRAST , data - > hdev ) ;
unsigned long flags ;
if ( ! report | | report - > maxfield ! = 1 | | report - > field [ 0 ] - > report_count ! = 1 )
return - ENODEV ;
data - > lcd_contrast = contrast & 0x0ff ;
spin_lock_irqsave ( & data - > lock , flags ) ;
hid_set_field ( report - > field [ 0 ] , 0 , data - > lcd_contrast ) ;
2012-07-30 23:38:57 +04:00
if ( ! ( data - > status & PICOLCD_FAILED ) )
2013-02-25 14:31:46 +04:00
hid_hw_request ( data - > hdev , report , HID_REQ_SET_REPORT ) ;
2012-07-30 23:38:28 +04:00
spin_unlock_irqrestore ( & data - > lock , flags ) ;
return 0 ;
}
static int picolcd_check_lcd_fb ( struct lcd_device * ldev , struct fb_info * fb )
{
return fb & & fb = = picolcd_fbinfo ( ( struct picolcd_data * ) lcd_get_data ( ldev ) ) ;
}
static struct lcd_ops picolcd_lcdops = {
. get_contrast = picolcd_get_contrast ,
. set_contrast = picolcd_set_contrast ,
. check_fb = picolcd_check_lcd_fb ,
} ;
int picolcd_init_lcd ( struct picolcd_data * data , struct hid_report * report )
{
struct device * dev = & data - > hdev - > dev ;
struct lcd_device * ldev ;
if ( ! report )
return - ENODEV ;
if ( report - > maxfield ! = 1 | | report - > field [ 0 ] - > report_count ! = 1 | |
report - > field [ 0 ] - > report_size ! = 8 ) {
dev_err ( dev , " unsupported CONTRAST report " ) ;
return - EINVAL ;
}
ldev = lcd_device_register ( dev_name ( dev ) , dev , data , & picolcd_lcdops ) ;
if ( IS_ERR ( ldev ) ) {
dev_err ( dev , " failed to register LCD \n " ) ;
return PTR_ERR ( ldev ) ;
}
ldev - > props . max_contrast = 0x0ff ;
data - > lcd_contrast = 0xe5 ;
data - > lcd = ldev ;
picolcd_set_contrast ( ldev , 0xe5 ) ;
return 0 ;
}
void picolcd_exit_lcd ( struct picolcd_data * data )
{
struct lcd_device * ldev = data - > lcd ;
data - > lcd = NULL ;
if ( ldev )
lcd_device_unregister ( ldev ) ;
}
int picolcd_resume_lcd ( struct picolcd_data * data )
{
if ( ! data - > lcd )
return 0 ;
return picolcd_set_contrast ( data - > lcd , data - > lcd_contrast ) ;
}