2005-04-16 15:20:36 -07:00
/*
*
* handle saa7134 IR remotes via linux kernel input layer .
*
* 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 . 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 . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/interrupt.h>
# include <linux/input.h>
# include "saa7134-reg.h"
# include "saa7134.h"
2008-04-22 14:41:48 -03:00
static unsigned int disable_ir ;
2005-04-16 15:20:36 -07:00
module_param ( disable_ir , int , 0444 ) ;
MODULE_PARM_DESC ( disable_ir , " disable infrared remote support " ) ;
2008-04-22 14:41:48 -03:00
static unsigned int ir_debug ;
2005-04-16 15:20:36 -07:00
module_param ( ir_debug , int , 0644 ) ;
MODULE_PARM_DESC ( ir_debug , " enable debug messages [IR] " ) ;
2008-04-22 14:41:48 -03:00
static int pinnacle_remote ;
2006-03-25 23:14:42 -03:00
module_param ( pinnacle_remote , int , 0644 ) ; /* Choose Pinnacle PCTV remote */
MODULE_PARM_DESC ( pinnacle_remote , " Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0) " ) ;
2006-12-28 12:47:47 -03:00
static int ir_rc5_remote_gap = 885 ;
2006-12-07 21:45:28 -03:00
module_param ( ir_rc5_remote_gap , int , 0644 ) ;
2006-12-28 12:47:47 -03:00
static int ir_rc5_key_timeout = 115 ;
2006-12-07 21:45:28 -03:00
module_param ( ir_rc5_key_timeout , int , 0644 ) ;
2007-10-17 17:58:40 -03:00
static int repeat_delay = 500 ;
module_param ( repeat_delay , int , 0644 ) ;
MODULE_PARM_DESC ( repeat_delay , " delay before key repeat started " ) ;
static int repeat_period = 33 ;
module_param ( repeat_period , int , 0644 ) ;
2007-11-20 09:00:35 -03:00
MODULE_PARM_DESC ( repeat_period , " repeat period between "
2007-10-17 17:58:40 -03:00
" keypresses when key is down " ) ;
2008-01-07 05:17:39 -03:00
static unsigned int disable_other_ir ;
module_param ( disable_other_ir , int , 0644 ) ;
MODULE_PARM_DESC ( disable_other_ir , " disable full codes of "
" alternative remotes from other manufacturers " ) ;
2005-04-16 15:20:36 -07:00
# define dprintk(fmt, arg...) if (ir_debug) \
printk ( KERN_DEBUG " %s/ir: " fmt , dev - > name , # # arg )
2005-11-08 21:37:56 -08:00
# define i2cdprintk(fmt, arg...) if (ir_debug) \
2009-05-13 16:48:07 -03:00
printk ( KERN_DEBUG " %s/ir: " fmt , ir - > name , # # arg )
2005-04-16 15:20:36 -07:00
2008-08-05 10:03:17 -03:00
/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */
2006-12-07 21:45:28 -03:00
static int saa7134_rc5_irq ( struct saa7134_dev * dev ) ;
2008-08-05 10:03:17 -03:00
static int saa7134_nec_irq ( struct saa7134_dev * dev ) ;
static void nec_task ( unsigned long data ) ;
static void saa7134_nec_timer ( unsigned long data ) ;
2006-12-07 21:45:28 -03:00
2005-11-08 21:37:56 -08:00
/* -------------------- GPIO generic keycode builder -------------------- */
2005-04-16 15:20:36 -07:00
static int build_key ( struct saa7134_dev * dev )
{
2006-12-07 21:45:28 -03:00
struct card_ir * ir = dev - > remote ;
2005-04-16 15:20:36 -07:00
u32 gpio , data ;
2007-10-17 17:58:40 -03:00
/* here comes the additional handshake steps for some cards */
switch ( dev - > board ) {
case SAA7134_BOARD_GOTVIEW_7135 :
saa_setb ( SAA7134_GPIO_GPSTATUS1 , 0x80 ) ;
saa_clearb ( SAA7134_GPIO_GPSTATUS1 , 0x80 ) ;
break ;
}
2005-04-16 15:20:36 -07:00
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
saa_setb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
gpio = saa_readl ( SAA7134_GPIO_GPSTATUS0 > > 2 ) ;
2005-11-08 21:37:43 -08:00
if ( ir - > polling ) {
if ( ir - > last_gpio = = gpio )
return 0 ;
ir - > last_gpio = gpio ;
}
2005-04-16 15:20:36 -07:00
2005-11-08 21:37:43 -08:00
data = ir_extract_bits ( gpio , ir - > mask_keycode ) ;
2005-04-16 15:20:36 -07:00
dprintk ( " build_key gpio=0x%x mask=0x%x data=%d \n " ,
gpio , ir - > mask_keycode , data ) ;
2008-12-07 13:19:29 -03:00
switch ( dev - > board ) {
case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG :
if ( data = = ir - > mask_keycode )
ir_input_nokey ( ir - > dev , & ir - > ir ) ;
else
ir_input_keydown ( ir - > dev , & ir - > ir , data , data ) ;
return 0 ;
}
2006-01-09 18:21:23 -02:00
if ( ir - > polling ) {
if ( ( ir - > mask_keydown & & ( 0 ! = ( gpio & ir - > mask_keydown ) ) ) | |
( ir - > mask_keyup & & ( 0 = = ( gpio & ir - > mask_keyup ) ) ) ) {
ir_input_keydown ( ir - > dev , & ir - > ir , data , data ) ;
} else {
ir_input_nokey ( ir - > dev , & ir - > ir ) ;
}
2005-04-16 15:20:36 -07:00
}
2006-01-09 18:21:23 -02:00
else { /* IRQ driven mode - handle key press and release in one go */
if ( ( ir - > mask_keydown & & ( 0 ! = ( gpio & ir - > mask_keydown ) ) ) | |
( ir - > mask_keyup & & ( 0 = = ( gpio & ir - > mask_keyup ) ) ) ) {
ir_input_keydown ( ir - > dev , & ir - > ir , data , data ) ;
ir_input_nokey ( ir - > dev , & ir - > ir ) ;
}
}
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-11-08 21:37:56 -08:00
/* --------------------- Chip specific I2C key builders ----------------- */
2008-10-13 08:37:06 -03:00
static int get_key_msi_tvanywhere_plus ( struct IR_i2c * ir , u32 * ir_key ,
u32 * ir_raw )
{
unsigned char b ;
int gpio ;
/* <dev> is needed to access GPIO. Used by the saa_readl macro. */
2009-05-13 16:48:50 -03:00
struct saa7134_dev * dev = ir - > c - > adapter - > algo_data ;
2008-10-13 08:37:06 -03:00
if ( dev = = NULL ) {
dprintk ( " get_key_msi_tvanywhere_plus: "
2009-05-13 16:48:50 -03:00
" gir->c->adapter->algo_data is NULL! \n " ) ;
2008-10-13 08:37:06 -03:00
return - EIO ;
}
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
saa_setb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
gpio = saa_readl ( SAA7134_GPIO_GPSTATUS0 > > 2 ) ;
/* GPIO&0x40 is pulsed low when a button is pressed. Don't do
I2C receive if gpio & 0x40 is not low . */
if ( gpio & 0x40 )
return 0 ; /* No button press */
/* GPIO says there is a button press. Get it. */
2009-05-13 16:48:50 -03:00
if ( 1 ! = i2c_master_recv ( ir - > c , & b , 1 ) ) {
2008-10-13 08:37:06 -03:00
i2cdprintk ( " read error \n " ) ;
return - EIO ;
}
/* No button press */
if ( b = = 0xff )
return 0 ;
/* Button pressed */
dprintk ( " get_key_msi_tvanywhere_plus: Key = 0x%02X \n " , b ) ;
* ir_key = b ;
* ir_raw = b ;
return 1 ;
}
2005-11-08 21:37:56 -08:00
static int get_key_purpletv ( struct IR_i2c * ir , u32 * ir_key , u32 * ir_raw )
{
unsigned char b ;
/* poll IR chip */
2009-05-13 16:48:50 -03:00
if ( 1 ! = i2c_master_recv ( ir - > c , & b , 1 ) ) {
2005-11-08 21:37:56 -08:00
i2cdprintk ( " read error \n " ) ;
return - EIO ;
}
/* no button press */
if ( b = = 0 )
return 0 ;
/* repeating */
if ( b & 0x80 )
return 1 ;
* ir_key = b ;
* ir_raw = b ;
return 1 ;
}
2006-11-29 21:57:24 -03:00
static int get_key_hvr1110 ( struct IR_i2c * ir , u32 * ir_key , u32 * ir_raw )
{
unsigned char buf [ 5 ] , cod4 , code3 , code4 ;
/* poll IR chip */
2009-05-13 16:48:50 -03:00
if ( 5 ! = i2c_master_recv ( ir - > c , buf , 5 ) )
2006-11-29 21:57:24 -03:00
return - EIO ;
cod4 = buf [ 4 ] ;
code4 = ( cod4 > > 2 ) ;
code3 = buf [ 3 ] ;
if ( code3 = = 0 )
/* no key pressed */
return 0 ;
/* return key */
* ir_key = code4 ;
* ir_raw = code4 ;
return 1 ;
}
2008-01-07 05:17:39 -03:00
static int get_key_beholdm6xx ( struct IR_i2c * ir , u32 * ir_key , u32 * ir_raw )
{
unsigned char data [ 12 ] ;
u32 gpio ;
2009-05-13 16:48:50 -03:00
struct saa7134_dev * dev = ir - > c - > adapter - > algo_data ;
2008-01-07 05:17:39 -03:00
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
saa_setb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
gpio = saa_readl ( SAA7134_GPIO_GPSTATUS0 > > 2 ) ;
2008-01-07 05:18:36 -03:00
if ( 0x400000 & ~ gpio )
2008-01-07 05:17:39 -03:00
return 0 ; /* No button press */
2009-05-13 16:48:50 -03:00
ir - > c - > addr = 0x5a > > 1 ;
2008-01-07 05:17:39 -03:00
2009-05-13 16:48:50 -03:00
if ( 12 ! = i2c_master_recv ( ir - > c , data , 12 ) ) {
2008-01-07 05:17:39 -03:00
i2cdprintk ( " read error \n " ) ;
return - EIO ;
}
/* IR of this card normally decode signals NEC-standard from
* - Sven IHOO MT 5.1 R remote . xxyye718
* - Sven DVD HD - 10 xx remote . xxyyf708
* - BBK . . .
* - mayby others
* So , skip not our , if disable full codes mode .
*/
if ( data [ 10 ] ! = 0x6b & & data [ 11 ] ! = 0x86 & & disable_other_ir )
return 0 ;
* ir_key = data [ 9 ] ;
* ir_raw = data [ 9 ] ;
return 1 ;
}
2008-07-17 22:31:29 -03:00
/* Common (grey or coloured) pinnacle PCTV remote handling
*
*/
static int get_key_pinnacle ( struct IR_i2c * ir , u32 * ir_key , u32 * ir_raw ,
int parity_offset , int marker , int code_modulo )
{
unsigned char b [ 4 ] ;
unsigned int start = 0 , parity = 0 , code = 0 ;
/* poll IR chip */
2009-05-13 16:48:50 -03:00
if ( 4 ! = i2c_master_recv ( ir - > c , b , 4 ) ) {
2008-07-17 22:31:29 -03:00
i2cdprintk ( " read error \n " ) ;
return - EIO ;
}
for ( start = 0 ; start < ARRAY_SIZE ( b ) ; start + + ) {
if ( b [ start ] = = marker ) {
code = b [ ( start + parity_offset + 1 ) % 4 ] ;
parity = b [ ( start + parity_offset ) % 4 ] ;
}
}
/* Empty Request */
if ( parity = = 0 )
return 0 ;
/* Repeating... */
if ( ir - > old = = parity )
return 0 ;
ir - > old = parity ;
/* drop special codes when a key is held down a long time for the grey controller
In this case , the second bit of the code is asserted */
if ( marker = = 0xfe & & ( code & 0x40 ) )
return 0 ;
code % = code_modulo ;
* ir_raw = code ;
* ir_key = code ;
i2cdprintk ( " Pinnacle PCTV key %02x \n " , code ) ;
return 1 ;
}
/* The grey pinnacle PCTV remote
*
* There are one issue with this remote :
* - I2c packet does not change when the same key is pressed quickly . The workaround
* is to hold down each key for about half a second , so that another code is generated
* in the i2c packet , and the function can distinguish key presses .
*
* Sylvain Pasche < sylvain . pasche @ gmail . com >
*/
static int get_key_pinnacle_grey ( struct IR_i2c * ir , u32 * ir_key , u32 * ir_raw )
{
return get_key_pinnacle ( ir , ir_key , ir_raw , 1 , 0xfe , 0xff ) ;
}
/* The new pinnacle PCTV remote (with the colored buttons)
*
* Ricardo Cerqueira < v4l @ cerqueira . org >
*/
static int get_key_pinnacle_color ( struct IR_i2c * ir , u32 * ir_key , u32 * ir_raw )
{
/* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
*
* this is the only value that results in 42 unique
* codes < 128
*/
return get_key_pinnacle ( ir , ir_key , ir_raw , 2 , 0x80 , 0x88 ) ;
}
2005-04-16 15:20:36 -07:00
void saa7134_input_irq ( struct saa7134_dev * dev )
{
2006-12-07 21:45:28 -03:00
struct card_ir * ir = dev - > remote ;
2005-04-16 15:20:36 -07:00
2008-08-05 10:03:17 -03:00
if ( ir - > nec_gpio ) {
saa7134_nec_irq ( dev ) ;
} else if ( ! ir - > polling & & ! ir - > rc5_gpio ) {
2005-04-16 15:20:36 -07:00
build_key ( dev ) ;
2006-12-07 21:45:28 -03:00
} else if ( ir - > rc5_gpio ) {
saa7134_rc5_irq ( dev ) ;
}
2005-04-16 15:20:36 -07:00
}
static void saa7134_input_timer ( unsigned long data )
{
2007-05-21 11:41:02 -03:00
struct saa7134_dev * dev = ( struct saa7134_dev * ) data ;
2006-12-07 21:45:28 -03:00
struct card_ir * ir = dev - > remote ;
2005-04-16 15:20:36 -07:00
build_key ( dev ) ;
2007-05-21 11:41:02 -03:00
mod_timer ( & ir - > timer , jiffies + msecs_to_jiffies ( ir - > polling ) ) ;
2005-04-16 15:20:36 -07:00
}
2007-10-12 00:57:15 -03:00
void saa7134_ir_start ( struct saa7134_dev * dev , struct card_ir * ir )
2006-11-20 10:23:04 -03:00
{
if ( ir - > polling ) {
2007-05-21 11:41:02 -03:00
setup_timer ( & ir - > timer , saa7134_input_timer ,
( unsigned long ) dev ) ;
2006-11-20 10:23:04 -03:00
ir - > timer . expires = jiffies + HZ ;
add_timer ( & ir - > timer ) ;
2006-12-07 21:45:28 -03:00
} else if ( ir - > rc5_gpio ) {
/* set timer_end for code completion */
init_timer ( & ir - > timer_end ) ;
ir - > timer_end . function = ir_rc5_timer_end ;
ir - > timer_end . data = ( unsigned long ) ir ;
init_timer ( & ir - > timer_keyup ) ;
ir - > timer_keyup . function = ir_rc5_timer_keyup ;
ir - > timer_keyup . data = ( unsigned long ) ir ;
ir - > shift_by = 2 ;
ir - > start = 0x2 ;
ir - > addr = 0x17 ;
ir - > rc5_key_timeout = ir_rc5_key_timeout ;
ir - > rc5_remote_gap = ir_rc5_remote_gap ;
2008-08-05 10:03:17 -03:00
} else if ( ir - > nec_gpio ) {
setup_timer ( & ir - > timer_keyup , saa7134_nec_timer ,
( unsigned long ) dev ) ;
tasklet_init ( & ir - > tlet , nec_task , ( unsigned long ) dev ) ;
2006-11-20 10:23:04 -03:00
}
}
2007-10-12 00:57:15 -03:00
void saa7134_ir_stop ( struct saa7134_dev * dev )
2006-11-20 10:23:04 -03:00
{
if ( dev - > remote - > polling )
del_timer_sync ( & dev - > remote - > timer ) ;
}
2005-04-16 15:20:36 -07:00
int saa7134_input_init1 ( struct saa7134_dev * dev )
{
2006-12-07 21:45:28 -03:00
struct card_ir * ir ;
2005-09-15 02:01:53 -05:00
struct input_dev * input_dev ;
2005-04-16 15:20:36 -07:00
IR_KEYTAB_TYPE * ir_codes = NULL ;
u32 mask_keycode = 0 ;
u32 mask_keydown = 0 ;
u32 mask_keyup = 0 ;
int polling = 0 ;
2006-12-07 21:45:28 -03:00
int rc5_gpio = 0 ;
2008-08-05 10:03:17 -03:00
int nec_gpio = 0 ;
2005-04-16 15:20:36 -07:00
int ir_type = IR_TYPE_OTHER ;
2006-11-20 10:23:04 -03:00
int err ;
2005-04-16 15:20:36 -07:00
2005-11-08 21:38:47 -08:00
if ( dev - > has_remote ! = SAA7134_REMOTE_GPIO )
2005-04-16 15:20:36 -07:00
return - ENODEV ;
if ( disable_ir )
return - ENODEV ;
/* detect & configure */
switch ( dev - > board ) {
case SAA7134_BOARD_FLYVIDEO2000 :
case SAA7134_BOARD_FLYVIDEO3000 :
2005-11-08 21:37:43 -08:00
case SAA7134_BOARD_FLYTVPLATINUM_FM :
2005-11-08 21:36:55 -08:00
case SAA7134_BOARD_FLYTVPLATINUM_MINI2 :
2006-01-23 09:42:06 -02:00
ir_codes = ir_codes_flyvideo ;
2005-04-16 15:20:36 -07:00
mask_keycode = 0xEC00000 ;
mask_keydown = 0x0040000 ;
break ;
case SAA7134_BOARD_CINERGY400 :
case SAA7134_BOARD_CINERGY600 :
case SAA7134_BOARD_CINERGY600_MK3 :
2006-01-23 09:42:06 -02:00
ir_codes = ir_codes_cinergy ;
2005-04-16 15:20:36 -07:00
mask_keycode = 0x00003f ;
mask_keyup = 0x040000 ;
break ;
case SAA7134_BOARD_ECS_TVP3XP :
case SAA7134_BOARD_ECS_TVP3XP_4CB5 :
2006-01-23 09:42:06 -02:00
ir_codes = ir_codes_eztv ;
2005-07-12 13:59:01 -07:00
mask_keycode = 0x00017c ;
mask_keyup = 0x000002 ;
2005-04-16 15:20:36 -07:00
polling = 50 ; // ms
2005-07-12 13:59:01 -07:00
break ;
case SAA7134_BOARD_KWORLD_XPERT :
2005-04-16 15:20:36 -07:00
case SAA7134_BOARD_AVACSSMARTTV :
2006-01-23 09:44:10 -02:00
ir_codes = ir_codes_pixelview ;
2005-04-16 15:20:36 -07:00
mask_keycode = 0x00001F ;
mask_keyup = 0x000020 ;
polling = 50 ; // ms
break ;
case SAA7134_BOARD_MD2819 :
2005-06-23 22:05:09 -07:00
case SAA7134_BOARD_KWORLD_VSTREAM_XPERT :
2005-04-16 15:20:36 -07:00
case SAA7134_BOARD_AVERMEDIA_305 :
case SAA7134_BOARD_AVERMEDIA_307 :
2005-06-23 22:05:09 -07:00
case SAA7134_BOARD_AVERMEDIA_STUDIO_305 :
case SAA7134_BOARD_AVERMEDIA_STUDIO_307 :
2006-10-06 20:23:47 -03:00
case SAA7134_BOARD_AVERMEDIA_STUDIO_507 :
2009-04-08 14:01:19 -03:00
case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA :
2005-06-23 22:05:09 -07:00
case SAA7134_BOARD_AVERMEDIA_GO_007_FM :
2007-12-09 09:44:38 -03:00
case SAA7134_BOARD_AVERMEDIA_M102 :
2008-12-30 23:26:09 -03:00
case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS :
2006-01-23 09:44:10 -02:00
ir_codes = ir_codes_avermedia ;
2005-04-16 15:20:36 -07:00
mask_keycode = 0x0007C8 ;
mask_keydown = 0x000010 ;
polling = 50 ; // ms
/* Set GPIO pin2 to high to enable the IR controller */
saa_setb ( SAA7134_GPIO_GPMODE0 , 0x4 ) ;
saa_setb ( SAA7134_GPIO_GPSTATUS0 , 0x4 ) ;
break ;
2008-06-26 17:03:00 -03:00
case SAA7134_BOARD_AVERMEDIA_M135A :
ir_codes = ir_codes_avermedia_m135a ;
mask_keydown = 0x0040000 ;
mask_keycode = 0x00013f ;
nec_gpio = 1 ;
break ;
2006-11-12 14:22:32 -03:00
case SAA7134_BOARD_AVERMEDIA_777 :
2006-11-12 14:23:32 -03:00
case SAA7134_BOARD_AVERMEDIA_A16AR :
2006-11-12 14:22:32 -03:00
ir_codes = ir_codes_avermedia ;
mask_keycode = 0x02F200 ;
mask_keydown = 0x000400 ;
polling = 50 ; // ms
/* Without this we won't receive key up events */
saa_setb ( SAA7134_GPIO_GPMODE1 , 0x1 ) ;
saa_setb ( SAA7134_GPIO_GPSTATUS1 , 0x1 ) ;
2006-11-13 09:50:11 -08:00
break ;
2008-06-15 13:33:42 -03:00
case SAA7134_BOARD_AVERMEDIA_A16D :
ir_codes = ir_codes_avermedia_a16d ;
mask_keycode = 0x02F200 ;
mask_keydown = 0x000400 ;
polling = 50 ; /* ms */
/* Without this we won't receive key up events */
saa_setb ( SAA7134_GPIO_GPMODE1 , 0x1 ) ;
saa_setb ( SAA7134_GPIO_GPSTATUS1 , 0x1 ) ;
break ;
2005-11-08 21:37:43 -08:00
case SAA7134_BOARD_KWORLD_TERMINATOR :
2006-01-23 09:44:10 -02:00
ir_codes = ir_codes_pixelview ;
2005-11-08 21:37:00 -08:00
mask_keycode = 0x00001f ;
mask_keyup = 0x000060 ;
polling = 50 ; // ms
break ;
2005-06-23 22:05:09 -07:00
case SAA7134_BOARD_MANLI_MTV001 :
case SAA7134_BOARD_MANLI_MTV002 :
2008-04-23 14:09:08 -03:00
ir_codes = ir_codes_manli ;
mask_keycode = 0x001f00 ;
mask_keyup = 0x004000 ;
polling = 50 ; /* ms */
break ;
2005-11-08 21:36:16 -08:00
case SAA7134_BOARD_BEHOLD_409FM :
2008-01-07 05:17:39 -03:00
case SAA7134_BOARD_BEHOLD_401 :
case SAA7134_BOARD_BEHOLD_403 :
case SAA7134_BOARD_BEHOLD_403FM :
case SAA7134_BOARD_BEHOLD_405 :
case SAA7134_BOARD_BEHOLD_405FM :
case SAA7134_BOARD_BEHOLD_407 :
case SAA7134_BOARD_BEHOLD_407FM :
case SAA7134_BOARD_BEHOLD_409 :
case SAA7134_BOARD_BEHOLD_505FM :
2009-04-23 02:32:49 -03:00
case SAA7134_BOARD_BEHOLD_505RDS :
2008-01-07 05:17:39 -03:00
case SAA7134_BOARD_BEHOLD_507_9FM :
2009-04-23 02:32:49 -03:00
case SAA7134_BOARD_BEHOLD_507RDS_MK3 :
case SAA7134_BOARD_BEHOLD_507RDS_MK5 :
2006-01-23 09:42:06 -02:00
ir_codes = ir_codes_manli ;
2008-04-23 14:09:08 -03:00
mask_keycode = 0x003f00 ;
mask_keyup = 0x004000 ;
polling = 50 ; /* ms */
break ;
case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM :
ir_codes = ir_codes_behold_columbus ;
mask_keycode = 0x003f00 ;
2005-06-23 22:05:09 -07:00
mask_keyup = 0x004000 ;
polling = 50 ; // ms
break ;
2005-11-08 21:38:47 -08:00
case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS :
2006-01-23 09:42:06 -02:00
ir_codes = ir_codes_pctv_sedna ;
2005-11-08 21:38:43 -08:00
mask_keycode = 0x001f00 ;
mask_keyup = 0x004000 ;
polling = 50 ; // ms
break ;
2005-11-08 21:37:43 -08:00
case SAA7134_BOARD_GOTVIEW_7135 :
2006-01-23 09:42:06 -02:00
ir_codes = ir_codes_gotview7135 ;
2007-10-17 17:58:40 -03:00
mask_keycode = 0x0003CC ;
2005-11-08 21:36:22 -08:00
mask_keydown = 0x000010 ;
2007-10-17 17:58:40 -03:00
polling = 5 ; /* ms */
saa_setb ( SAA7134_GPIO_GPMODE1 , 0x80 ) ;
2005-11-08 21:36:22 -08:00
break ;
2005-04-16 15:20:36 -07:00
case SAA7134_BOARD_VIDEOMATE_TV_PVR :
2006-01-09 15:25:33 -02:00
case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS :
2005-07-12 13:59:01 -07:00
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII :
2006-01-23 09:42:06 -02:00
ir_codes = ir_codes_videomate_tv_pvr ;
2005-04-16 15:20:36 -07:00
mask_keycode = 0x00003F ;
mask_keyup = 0x400000 ;
polling = 50 ; // ms
break ;
2006-09-13 16:42:42 -03:00
case SAA7134_BOARD_PROTEUS_2309 :
ir_codes = ir_codes_proteus_2309 ;
mask_keycode = 0x00007F ;
mask_keyup = 0x000080 ;
polling = 50 ; // ms
break ;
2005-11-08 21:37:43 -08:00
case SAA7134_BOARD_VIDEOMATE_DVBT_300 :
case SAA7134_BOARD_VIDEOMATE_DVBT_200 :
2006-01-23 09:42:06 -02:00
ir_codes = ir_codes_videomate_tv_pvr ;
2005-11-08 21:36:47 -08:00
mask_keycode = 0x003F00 ;
mask_keyup = 0x040000 ;
break ;
2007-07-02 12:53:25 -03:00
case SAA7134_BOARD_FLYDVBS_LR300 :
2006-02-07 06:49:09 -02:00
case SAA7134_BOARD_FLYDVBT_LR301 :
2006-02-27 00:08:46 -03:00
case SAA7134_BOARD_FLYDVBTDUO :
2006-02-07 06:49:09 -02:00
ir_codes = ir_codes_flydvb ;
mask_keycode = 0x0001F00 ;
mask_keydown = 0x0040000 ;
break ;
2006-12-07 21:45:28 -03:00
case SAA7134_BOARD_ASUSTeK_P7131_DUAL :
2007-03-29 18:32:49 -03:00
case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA :
2008-07-12 12:27:59 -03:00
case SAA7134_BOARD_ASUSTeK_P7131_ANALOG :
2006-12-07 21:45:28 -03:00
ir_codes = ir_codes_asus_pc39 ;
mask_keydown = 0x0040000 ;
rc5_gpio = 1 ;
break ;
2006-12-27 12:46:36 -03:00
case SAA7134_BOARD_ENCORE_ENLTV :
case SAA7134_BOARD_ENCORE_ENLTV_FM :
ir_codes = ir_codes_encore_enltv ;
mask_keycode = 0x00007f ;
mask_keyup = 0x040000 ;
polling = 50 ; // ms
break ;
2008-06-26 17:03:00 -03:00
case SAA7134_BOARD_ENCORE_ENLTV_FM53 :
ir_codes = ir_codes_encore_enltv_fm53 ;
mask_keydown = 0x0040000 ;
mask_keycode = 0x00007f ;
nec_gpio = 1 ;
break ;
2007-05-11 11:33:50 -03:00
case SAA7134_BOARD_10MOONSTVMASTER3 :
ir_codes = ir_codes_encore_enltv ;
mask_keycode = 0x5f80000 ;
mask_keyup = 0x8000000 ;
polling = 50 ; //ms
break ;
2008-02-11 12:40:53 -03:00
case SAA7134_BOARD_GENIUS_TVGO_A11MCE :
ir_codes = ir_codes_genius_tvgo_a11mce ;
mask_keycode = 0xff ;
mask_keydown = 0xf00000 ;
polling = 50 ; /* ms */
break ;
2008-06-26 17:03:00 -03:00
case SAA7134_BOARD_REAL_ANGEL_220 :
ir_codes = ir_codes_real_audio_220_32_keys ;
mask_keycode = 0x3f00 ;
mask_keyup = 0x4000 ;
polling = 50 ; /* ms */
break ;
2008-12-07 13:19:29 -03:00
case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG :
ir_codes = ir_codes_kworld_plus_tv_analog ;
mask_keycode = 0x7f ;
polling = 40 ; /* ms */
break ;
2005-04-16 15:20:36 -07:00
}
if ( NULL = = ir_codes ) {
printk ( " %s: Oops: IR config error [card=%d] \n " ,
dev - > name , dev - > board ) ;
return - ENODEV ;
}
2005-09-15 02:01:53 -05:00
ir = kzalloc ( sizeof ( * ir ) , GFP_KERNEL ) ;
input_dev = input_allocate_device ( ) ;
if ( ! ir | | ! input_dev ) {
2006-11-20 10:23:04 -03:00
err = - ENOMEM ;
goto err_out_free ;
2005-09-15 02:01:53 -05:00
}
2005-04-16 15:20:36 -07:00
2005-11-20 00:56:54 -05:00
ir - > dev = input_dev ;
2005-04-16 15:20:36 -07:00
/* init hardware-specific stuff */
ir - > mask_keycode = mask_keycode ;
ir - > mask_keydown = mask_keydown ;
ir - > mask_keyup = mask_keyup ;
2005-11-08 21:37:43 -08:00
ir - > polling = polling ;
2006-12-07 21:45:28 -03:00
ir - > rc5_gpio = rc5_gpio ;
2008-08-05 10:03:17 -03:00
ir - > nec_gpio = nec_gpio ;
2005-04-16 15:20:36 -07:00
/* init input device */
snprintf ( ir - > name , sizeof ( ir - > name ) , " saa7134 IR (%s) " ,
saa7134_boards [ dev - > board ] . name ) ;
snprintf ( ir - > phys , sizeof ( ir - > phys ) , " pci-%s/ir0 " ,
pci_name ( dev - > pci ) ) ;
2005-09-15 02:01:53 -05:00
ir_input_init ( input_dev , & ir - > ir , ir_type , ir_codes ) ;
input_dev - > name = ir - > name ;
input_dev - > phys = ir - > phys ;
input_dev - > id . bustype = BUS_PCI ;
input_dev - > id . version = 1 ;
2005-04-16 15:20:36 -07:00
if ( dev - > pci - > subsystem_vendor ) {
2005-09-15 02:01:53 -05:00
input_dev - > id . vendor = dev - > pci - > subsystem_vendor ;
input_dev - > id . product = dev - > pci - > subsystem_device ;
2005-04-16 15:20:36 -07:00
} else {
2005-09-15 02:01:53 -05:00
input_dev - > id . vendor = dev - > pci - > vendor ;
input_dev - > id . product = dev - > pci - > device ;
2005-04-16 15:20:36 -07:00
}
2007-07-16 09:28:15 -03:00
input_dev - > dev . parent = & dev - > pci - > dev ;
2005-04-16 15:20:36 -07:00
dev - > remote = ir ;
2006-11-20 10:23:04 -03:00
saa7134_ir_start ( dev , ir ) ;
err = input_register_device ( ir - > dev ) ;
if ( err )
goto err_out_stop ;
2005-04-16 15:20:36 -07:00
2007-10-17 17:58:40 -03:00
/* the remote isn't as bouncy as a keyboard */
ir - > dev - > rep [ REP_DELAY ] = repeat_delay ;
ir - > dev - > rep [ REP_PERIOD ] = repeat_period ;
2005-04-16 15:20:36 -07:00
return 0 ;
2006-11-20 10:23:04 -03:00
err_out_stop :
saa7134_ir_stop ( dev ) ;
dev - > remote = NULL ;
err_out_free :
input_free_device ( input_dev ) ;
kfree ( ir ) ;
return err ;
2005-04-16 15:20:36 -07:00
}
void saa7134_input_fini ( struct saa7134_dev * dev )
{
if ( NULL = = dev - > remote )
return ;
2006-11-20 10:23:04 -03:00
saa7134_ir_stop ( dev ) ;
2005-09-15 02:01:53 -05:00
input_unregister_device ( dev - > remote - > dev ) ;
2005-04-16 15:20:36 -07:00
kfree ( dev - > remote ) ;
dev - > remote = NULL ;
}
2009-05-13 16:48:50 -03:00
void saa7134_probe_i2c_ir ( struct saa7134_dev * dev )
2005-11-08 21:37:56 -08:00
{
2009-05-13 16:48:50 -03:00
struct i2c_board_info info ;
2009-05-13 16:49:32 -03:00
struct IR_i2c_init_data init_data ;
2009-05-13 16:48:50 -03:00
const unsigned short addr_list [ ] = {
0x7a , 0x47 , 0x71 , 0x2d ,
I2C_CLIENT_END
} ;
const unsigned short addr_list_msi [ ] = {
0x30 , I2C_CLIENT_END
} ;
struct i2c_msg msg_msi = {
. addr = 0x50 ,
. flags = I2C_M_RD ,
. len = 0 ,
. buf = NULL ,
} ;
unsigned char subaddr , data ;
struct i2c_msg msg_avermedia [ ] = { {
. addr = 0x40 ,
. flags = 0 ,
. len = 1 ,
. buf = & subaddr ,
} , {
. addr = 0x40 ,
. flags = I2C_M_RD ,
. len = 1 ,
. buf = & data ,
} } ;
struct i2c_client * client ;
int rc ;
2005-11-08 21:37:56 -08:00
if ( disable_ir ) {
2009-05-13 16:48:50 -03:00
dprintk ( " IR has been disabled, not probing for i2c remote \n " ) ;
2005-11-08 21:37:56 -08:00
return ;
}
2009-05-13 16:48:50 -03:00
memset ( & info , 0 , sizeof ( struct i2c_board_info ) ) ;
2009-05-13 16:49:32 -03:00
memset ( & init_data , 0 , sizeof ( struct IR_i2c_init_data ) ) ;
2009-05-13 16:48:50 -03:00
strlcpy ( info . type , " ir_video " , I2C_NAME_SIZE ) ;
2005-11-08 21:37:56 -08:00
switch ( dev - > board ) {
case SAA7134_BOARD_PINNACLE_PCTV_110i :
2006-10-12 19:46:16 -03:00
case SAA7134_BOARD_PINNACLE_PCTV_310i :
2009-05-13 16:49:32 -03:00
init_data . name = " Pinnacle PCTV " ;
2006-03-25 23:14:42 -03:00
if ( pinnacle_remote = = 0 ) {
2009-05-13 16:49:32 -03:00
init_data . get_key = get_key_pinnacle_color ;
init_data . ir_codes = ir_codes_pinnacle_color ;
2006-03-25 23:14:42 -03:00
} else {
2009-05-13 16:49:32 -03:00
init_data . get_key = get_key_pinnacle_grey ;
init_data . ir_codes = ir_codes_pinnacle_grey ;
2006-03-25 23:14:42 -03:00
}
2005-11-08 21:37:56 -08:00
break ;
case SAA7134_BOARD_UPMOST_PURPLE_TV :
2009-05-13 16:49:32 -03:00
init_data . name = " Purple TV " ;
init_data . get_key = get_key_purpletv ;
init_data . ir_codes = ir_codes_purpletv ;
2005-11-08 21:37:56 -08:00
break ;
2008-10-13 08:37:06 -03:00
case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS :
2009-05-13 16:49:32 -03:00
init_data . name = " MSI TV@nywhere Plus " ;
init_data . get_key = get_key_msi_tvanywhere_plus ;
init_data . ir_codes = ir_codes_msi_tvanywhere_plus ;
2008-10-13 08:37:06 -03:00
break ;
2006-11-29 21:57:24 -03:00
case SAA7134_BOARD_HAUPPAUGE_HVR1110 :
2009-05-13 16:49:32 -03:00
init_data . name = " HVR 1110 " ;
init_data . get_key = get_key_hvr1110 ;
init_data . ir_codes = ir_codes_hauppauge_new ;
2006-11-29 21:57:24 -03:00
break ;
2009-04-23 02:32:49 -03:00
case SAA7134_BOARD_BEHOLD_607FM_MK3 :
case SAA7134_BOARD_BEHOLD_607FM_MK5 :
case SAA7134_BOARD_BEHOLD_609FM_MK3 :
case SAA7134_BOARD_BEHOLD_609FM_MK5 :
case SAA7134_BOARD_BEHOLD_607RDS_MK3 :
case SAA7134_BOARD_BEHOLD_607RDS_MK5 :
case SAA7134_BOARD_BEHOLD_609RDS_MK3 :
case SAA7134_BOARD_BEHOLD_609RDS_MK5 :
2008-01-07 05:17:39 -03:00
case SAA7134_BOARD_BEHOLD_M6 :
2008-06-10 14:22:00 -03:00
case SAA7134_BOARD_BEHOLD_M63 :
case SAA7134_BOARD_BEHOLD_M6_EXTRA :
2008-04-26 14:53:48 -03:00
case SAA7134_BOARD_BEHOLD_H6 :
2009-05-13 16:49:32 -03:00
init_data . name = " BeholdTV " ;
init_data . get_key = get_key_beholdm6xx ;
init_data . ir_codes = ir_codes_behold ;
2005-11-08 21:37:56 -08:00
break ;
}
2009-05-13 16:49:32 -03:00
if ( init_data . name )
info . platform_data = & init_data ;
client = i2c_new_probed_device ( & dev - > i2c_adap , & info , addr_list ) ;
if ( client )
return ;
/* MSI TV@nywhere Plus controller doesn't seem to
respond to probes unless we read something from
an existing device . Weird . . . */
rc = i2c_transfer ( & dev - > i2c_adap , & msg_msi , 1 ) ;
dprintk ( KERN_DEBUG " probe 0x%02x @ %s: %s \n " ,
msg_msi . addr , dev - > i2c_adap . name ,
( 1 = = rc ) ? " yes " : " no " ) ;
client = i2c_new_probed_device ( & dev - > i2c_adap , & info , addr_list_msi ) ;
if ( client )
return ;
/* Special case for AVerMedia Cardbus remote */
subaddr = 0x0d ;
rc = i2c_transfer ( & dev - > i2c_adap , msg_avermedia , 2 ) ;
dprintk ( KERN_DEBUG " probe 0x%02x/0x%02x @ %s: %s \n " ,
msg_avermedia [ 0 ] . addr , subaddr , dev - > i2c_adap . name ,
( 2 = = rc ) ? " yes " : " no " ) ;
if ( 2 = = rc ) {
info . addr = msg_avermedia [ 0 ] . addr ;
i2c_new_device ( & dev - > i2c_adap , & info ) ;
}
2005-11-08 21:37:56 -08:00
}
2006-12-07 21:45:28 -03:00
static int saa7134_rc5_irq ( struct saa7134_dev * dev )
{
struct card_ir * ir = dev - > remote ;
struct timeval tv ;
u32 gap ;
unsigned long current_jiffies , timeout ;
/* get time of bit */
current_jiffies = jiffies ;
do_gettimeofday ( & tv ) ;
/* avoid overflow with gap >1s */
if ( tv . tv_sec - ir - > base_time . tv_sec > 1 ) {
gap = 200000 ;
} else {
gap = 1000000 * ( tv . tv_sec - ir - > base_time . tv_sec ) +
tv . tv_usec - ir - > base_time . tv_usec ;
}
/* active code => add bit */
if ( ir - > active ) {
/* only if in the code (otherwise spurious IRQ or timer
late ) */
if ( ir - > last_bit < 28 ) {
ir - > last_bit = ( gap - ir_rc5_remote_gap / 2 ) /
ir_rc5_remote_gap ;
ir - > code | = 1 < < ir - > last_bit ;
}
/* starting new code */
} else {
ir - > active = 1 ;
ir - > code = 0 ;
ir - > base_time = tv ;
ir - > last_bit = 0 ;
timeout = current_jiffies + ( 500 + 30 * HZ ) / 1000 ;
mod_timer ( & ir - > timer_end , timeout ) ;
}
return 1 ;
}
2008-08-05 10:03:17 -03:00
/* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms
The first pulse ( start ) has 9 + 4.5 ms
2005-04-16 15:20:36 -07:00
*/
2008-08-05 10:03:17 -03:00
static void saa7134_nec_timer ( unsigned long data )
{
struct saa7134_dev * dev = ( struct saa7134_dev * ) data ;
struct card_ir * ir = dev - > remote ;
dprintk ( " Cancel key repeat \n " ) ;
ir_input_nokey ( ir - > dev , & ir - > ir ) ;
}
static void nec_task ( unsigned long data )
{
struct saa7134_dev * dev = ( struct saa7134_dev * ) data ;
struct card_ir * ir ;
struct timeval tv ;
int count , pulse , oldpulse , gap ;
u32 ircode = 0 , not_code = 0 ;
int ngap = 0 ;
if ( ! data ) {
printk ( KERN_ERR " saa713x/ir: Can't recover dev struct \n " ) ;
/* GPIO will be kept disabled */
return ;
}
ir = dev - > remote ;
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
saa_setb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
oldpulse = saa_readl ( SAA7134_GPIO_GPSTATUS0 > > 2 ) & ir - > mask_keydown ;
pulse = oldpulse ;
do_gettimeofday ( & tv ) ;
ir - > base_time = tv ;
/* Decode NEC pulsecode. This code can take up to 76.5 ms to run.
Unfortunately , using IRQ to decode pulse didn ' t work , since it uses
a pulse train of 38 KHz . This means one pulse on each 52 us
*/
do {
/* Wait until the end of pulse/space or 5 ms */
for ( count = 0 ; count < 500 ; count + + ) {
udelay ( 10 ) ;
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
saa_setb ( SAA7134_GPIO_GPMODE3 , SAA7134_GPIO_GPRESCAN ) ;
pulse = saa_readl ( SAA7134_GPIO_GPSTATUS0 > > 2 )
& ir - > mask_keydown ;
if ( pulse ! = oldpulse )
break ;
}
do_gettimeofday ( & tv ) ;
gap = 1000000 * ( tv . tv_sec - ir - > base_time . tv_sec ) +
tv . tv_usec - ir - > base_time . tv_usec ;
if ( ! pulse ) {
/* Bit 0 has 560 us, while bit 1 has 1120 us.
Do something only if bit = = 1
*/
if ( ngap & & ( gap > 560 + 280 ) ) {
unsigned int shift = ngap - 1 ;
/* Address first, then command */
if ( shift < 8 ) {
shift + = 8 ;
ircode | = 1 < < shift ;
} else if ( shift < 16 ) {
not_code | = 1 < < shift ;
} else if ( shift < 24 ) {
shift - = 16 ;
ircode | = 1 < < shift ;
} else {
shift - = 24 ;
not_code | = 1 < < shift ;
}
}
ngap + + ;
}
ir - > base_time = tv ;
/* TIMEOUT - Long pulse */
if ( gap > = 5000 )
break ;
oldpulse = pulse ;
} while ( ngap < 32 ) ;
if ( ngap = = 32 ) {
/* FIXME: should check if not_code == ~ircode */
ir - > code = ir_extract_bits ( ircode , ir - > mask_keycode ) ;
dprintk ( " scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x) \n " ,
ir - > code , ircode , not_code ) ;
ir_input_keydown ( ir - > dev , & ir - > ir , ir - > code , ir - > code ) ;
} else
dprintk ( " Repeat last key \n " ) ;
/* Keep repeating the last key */
mod_timer ( & ir - > timer_keyup , jiffies + msecs_to_jiffies ( 150 ) ) ;
saa_setl ( SAA7134_IRQ2 , SAA7134_IRQ2_INTE_GPIO18 ) ;
}
static int saa7134_nec_irq ( struct saa7134_dev * dev )
{
struct card_ir * ir = dev - > remote ;
saa_clearl ( SAA7134_IRQ2 , SAA7134_IRQ2_INTE_GPIO18 ) ;
tasklet_schedule ( & ir - > tlet ) ;
return 1 ;
}