2005-04-16 15:20:36 -07:00
/*
*
* Copyright ( c ) 2003 Gerd Knorr
* Copyright ( c ) 2003 Pavel Machek
*
* 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/moduleparam.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/interrupt.h>
# include <linux/input.h>
# include "bttv.h"
2006-01-09 15:25:25 -02:00
# include "bttvp.h"
2005-04-16 15:20:36 -07:00
2005-11-13 16:07:52 -08:00
2005-04-16 15:20:36 -07:00
static int debug ;
module_param ( debug , int , 0644 ) ; /* debug level (0,1,2) */
2005-11-13 16:07:52 -08:00
static int repeat_delay = 500 ;
module_param ( repeat_delay , int , 0644 ) ;
static int repeat_period = 33 ;
module_param ( repeat_period , int , 0644 ) ;
2005-04-16 15:20:36 -07:00
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 = 200 ;
2006-12-07 21:45:28 -03:00
module_param ( ir_rc5_key_timeout , int , 0644 ) ;
2006-01-09 15:25:25 -02:00
# define DEVNAME "bttv-input"
2005-04-16 15:20:36 -07:00
/* ---------------------------------------------------------------------- */
2006-01-09 15:25:25 -02:00
static void ir_handle_key ( struct bttv * btv )
2005-04-16 15:20:36 -07:00
{
2006-12-07 21:45:28 -03:00
struct card_ir * ir = btv - > remote ;
2005-04-16 15:20:36 -07:00
u32 gpio , data ;
/* read gpio value */
2006-01-09 15:25:25 -02:00
gpio = bttv_gpio_read ( & btv - > c ) ;
2005-04-16 15:20:36 -07:00
if ( ir - > polling ) {
if ( ir - > last_gpio = = gpio )
return ;
ir - > last_gpio = gpio ;
}
/* extract data */
data = ir_extract_bits ( gpio , ir - > mask_keycode ) ;
2006-01-09 15:25:25 -02:00
dprintk ( KERN_INFO DEVNAME " : irq gpio=0x%x code=%d | %s%s%s \n " ,
2005-04-16 15:20:36 -07:00
gpio , data ,
ir - > polling ? " poll " : " irq " ,
( gpio & ir - > mask_keydown ) ? " down " : " " ,
( gpio & ir - > mask_keyup ) ? " up " : " " ) ;
2006-01-09 15:25:25 -02:00
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 ) ;
2005-04-16 15:20:36 -07:00
} else {
2006-01-09 15:25:25 -02:00
ir_input_nokey ( ir - > dev , & ir - > ir ) ;
2005-04-16 15:20:36 -07:00
}
}
2006-01-09 15:25:25 -02:00
void bttv_input_irq ( struct bttv * btv )
2005-04-16 15:20:36 -07:00
{
2006-12-07 21:45:28 -03:00
struct card_ir * ir = btv - > remote ;
2005-04-16 15:20:36 -07:00
2006-01-09 15:25:25 -02:00
if ( ! ir - > polling )
ir_handle_key ( btv ) ;
2005-04-16 15:20:36 -07:00
}
2006-01-09 15:25:25 -02:00
static void bttv_input_timer ( unsigned long data )
2005-04-16 15:20:36 -07:00
{
2006-01-09 15:25:25 -02:00
struct bttv * btv = ( struct bttv * ) data ;
2006-12-07 21:45:28 -03:00
struct card_ir * ir = btv - > remote ;
2005-04-16 15:20:36 -07:00
2006-01-09 15:25:25 -02:00
ir_handle_key ( btv ) ;
2007-01-02 03:29:48 -03:00
mod_timer ( & ir - > timer , jiffies + msecs_to_jiffies ( ir - > polling ) ) ;
2005-04-16 15:20:36 -07:00
}
2005-11-13 16:07:52 -08:00
/* ---------------------------------------------------------------*/
2006-01-09 15:25:25 -02:00
static int bttv_rc5_irq ( struct bttv * btv )
2005-11-13 16:07:52 -08:00
{
2006-12-07 21:45:28 -03:00
struct card_ir * ir = btv - > remote ;
2005-11-13 16:07:52 -08:00
struct timeval tv ;
u32 gpio ;
u32 gap ;
2007-01-02 03:29:48 -03:00
unsigned long current_jiffies ;
2005-11-13 16:07:52 -08:00
/* read gpio port */
2006-01-09 15:25:25 -02:00
gpio = bttv_gpio_read ( & btv - > c ) ;
2005-11-13 16:07:52 -08:00
/* remote IRQ? */
if ( ! ( gpio & 0x20 ) )
return 0 ;
/* 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 ) {
2006-12-07 21:45:28 -03:00
ir - > last_bit = ( gap - ir_rc5_remote_gap / 2 ) /
ir_rc5_remote_gap ;
2005-11-13 16:07:52 -08:00
ir - > code | = 1 < < ir - > last_bit ;
}
/* starting new code */
} else {
ir - > active = 1 ;
ir - > code = 0 ;
ir - > base_time = tv ;
ir - > last_bit = 0 ;
2007-01-02 03:29:48 -03:00
mod_timer ( & ir - > timer_end ,
current_jiffies + msecs_to_jiffies ( 30 ) ) ;
2005-11-13 16:07:52 -08:00
}
/* toggle GPIO pin 4 to reset the irq */
2006-01-09 15:25:25 -02:00
bttv_gpio_write ( & btv - > c , gpio & ~ ( 1 < < 4 ) ) ;
bttv_gpio_write ( & btv - > c , gpio | ( 1 < < 4 ) ) ;
2005-11-13 16:07:52 -08:00
return 1 ;
}
2005-04-16 15:20:36 -07:00
/* ---------------------------------------------------------------------- */
2006-12-07 21:45:28 -03:00
static void bttv_ir_start ( struct bttv * btv , struct card_ir * ir )
2006-11-20 10:23:04 -03:00
{
if ( ir - > polling ) {
2007-01-02 03:29:48 -03:00
setup_timer ( & ir - > timer , bttv_input_timer , ( unsigned long ) btv ) ;
2007-07-17 16:36:20 -03:00
ir - > timer . expires = jiffies + msecs_to_jiffies ( 1000 ) ;
2006-11-20 10:23:04 -03:00
add_timer ( & ir - > timer ) ;
} else if ( ir - > rc5_gpio ) {
/* set timer_end for code completion */
init_timer ( & ir - > timer_end ) ;
2006-12-07 21:45:28 -03:00
ir - > timer_end . function = ir_rc5_timer_end ;
2006-11-20 10:23:04 -03:00
ir - > timer_end . data = ( unsigned long ) ir ;
init_timer ( & ir - > timer_keyup ) ;
2006-12-07 21:45:28 -03:00
ir - > timer_keyup . function = ir_rc5_timer_keyup ;
2006-11-20 10:23:04 -03:00
ir - > timer_keyup . data = ( unsigned long ) ir ;
2006-12-07 21:45:28 -03:00
ir - > shift_by = 1 ;
ir - > start = 3 ;
ir - > addr = 0x0 ;
ir - > rc5_key_timeout = ir_rc5_key_timeout ;
ir - > rc5_remote_gap = ir_rc5_remote_gap ;
2006-11-20 10:23:04 -03:00
}
}
static void bttv_ir_stop ( struct bttv * btv )
{
if ( btv - > remote - > polling ) {
del_timer_sync ( & btv - > remote - > timer ) ;
flush_scheduled_work ( ) ;
}
if ( btv - > remote - > rc5_gpio ) {
u32 gpio ;
del_timer_sync ( & btv - > remote - > timer_end ) ;
flush_scheduled_work ( ) ;
gpio = bttv_gpio_read ( & btv - > c ) ;
bttv_gpio_write ( & btv - > c , gpio & ~ ( 1 < < 4 ) ) ;
}
}
2006-01-09 15:25:25 -02:00
int bttv_input_init ( struct bttv * btv )
2005-04-16 15:20:36 -07:00
{
2006-12-07 21:45:28 -03:00
struct card_ir * ir ;
2005-04-16 15:20:36 -07:00
IR_KEYTAB_TYPE * ir_codes = NULL ;
2006-01-09 15:25:25 -02:00
struct input_dev * input_dev ;
2005-04-16 15:20:36 -07:00
int ir_type = IR_TYPE_OTHER ;
2006-11-20 10:23:04 -03:00
int err = - ENOMEM ;
2005-04-16 15:20:36 -07:00
2006-01-09 15:25:25 -02:00
if ( ! btv - > has_remote )
return - ENODEV ;
ir = kzalloc ( sizeof ( * ir ) , GFP_KERNEL ) ;
2005-09-15 02:01:53 -05:00
input_dev = input_allocate_device ( ) ;
2006-11-20 10:23:04 -03:00
if ( ! ir | | ! input_dev )
goto err_out_free ;
2005-04-16 15:20:36 -07:00
/* detect & configure */
2006-01-09 15:25:25 -02:00
switch ( btv - > c . type ) {
2005-11-08 21:36:52 -08:00
case BTTV_BOARD_AVERMEDIA :
case BTTV_BOARD_AVPHONE98 :
case BTTV_BOARD_AVERMEDIA98 :
2005-04-16 15:20:36 -07:00
ir_codes = ir_codes_avermedia ;
ir - > mask_keycode = 0xf88000 ;
ir - > mask_keydown = 0x010000 ;
ir - > polling = 50 ; // ms
break ;
2005-11-08 21:36:52 -08:00
case BTTV_BOARD_AVDVBT_761 :
case BTTV_BOARD_AVDVBT_771 :
2005-04-16 15:20:36 -07:00
ir_codes = ir_codes_avermedia_dvbt ;
ir - > mask_keycode = 0x0f00c0 ;
ir - > mask_keydown = 0x000020 ;
ir - > polling = 50 ; // ms
break ;
2005-11-08 21:36:52 -08:00
case BTTV_BOARD_PXELVWPLTVPAK :
2005-04-16 15:20:36 -07:00
ir_codes = ir_codes_pixelview ;
ir - > mask_keycode = 0x003e00 ;
ir - > mask_keyup = 0x010000 ;
ir - > polling = 50 ; // ms
2005-11-08 21:37:43 -08:00
break ;
2006-08-23 11:17:30 -03:00
case BTTV_BOARD_PV_M4900 :
2005-11-08 21:36:52 -08:00
case BTTV_BOARD_PV_BT878P_9B :
case BTTV_BOARD_PV_BT878P_PLUS :
2005-04-16 15:20:36 -07:00
ir_codes = ir_codes_pixelview ;
ir - > mask_keycode = 0x001f00 ;
ir - > mask_keyup = 0x008000 ;
ir - > polling = 50 ; // ms
2005-11-08 21:37:43 -08:00
break ;
2005-04-16 15:20:36 -07:00
2005-11-08 21:36:52 -08:00
case BTTV_BOARD_WINFAST2000 :
2005-04-16 15:20:36 -07:00
ir_codes = ir_codes_winfast ;
ir - > mask_keycode = 0x1f8 ;
break ;
2005-11-08 21:36:52 -08:00
case BTTV_BOARD_MAGICTVIEW061 :
case BTTV_BOARD_MAGICTVIEW063 :
2005-04-16 15:20:36 -07:00
ir_codes = ir_codes_winfast ;
ir - > mask_keycode = 0x0008e000 ;
ir - > mask_keydown = 0x00200000 ;
break ;
2005-11-08 21:36:52 -08:00
case BTTV_BOARD_APAC_VIEWCOMP :
2005-04-16 15:20:36 -07:00
ir_codes = ir_codes_apac_viewcomp ;
ir - > mask_keycode = 0x001f00 ;
ir - > mask_keyup = 0x008000 ;
ir - > polling = 50 ; // ms
break ;
2005-11-08 21:36:52 -08:00
case BTTV_BOARD_CONCEPTRONIC_CTVFMI2 :
2006-02-27 00:08:15 -03:00
case BTTV_BOARD_CONTVFMI :
2006-01-23 09:44:10 -02:00
ir_codes = ir_codes_pixelview ;
2005-11-08 21:36:20 -08:00
ir - > mask_keycode = 0x001F00 ;
ir - > mask_keyup = 0x006000 ;
ir - > polling = 50 ; // ms
break ;
2005-11-13 16:07:52 -08:00
case BTTV_BOARD_NEBULA_DIGITV :
ir_codes = ir_codes_nebula ;
2006-01-09 15:25:25 -02:00
btv - > custom_irq = bttv_rc5_irq ;
2005-11-13 16:07:52 -08:00
ir - > rc5_gpio = 1 ;
2005-12-12 00:37:28 -08:00
break ;
2006-01-11 19:40:09 -02:00
case BTTV_BOARD_MACHTV_MAGICTV :
ir_codes = ir_codes_apac_viewcomp ;
ir - > mask_keycode = 0x001F00 ;
ir - > mask_keyup = 0x004000 ;
ir - > polling = 50 ; /* ms */
break ;
2005-04-16 15:20:36 -07:00
}
if ( NULL = = ir_codes ) {
2006-11-20 10:23:04 -03:00
dprintk ( KERN_INFO " Ooops: IR config error [card=%d] \n " , btv - > c . type ) ;
err = - ENODEV ;
goto err_out_free ;
2005-04-16 15:20:36 -07:00
}
2005-11-13 16:07:52 -08:00
if ( ir - > rc5_gpio ) {
u32 gpio ;
2006-06-20 00:30:57 -03:00
/* enable remote irq */
2006-01-09 15:25:25 -02:00
bttv_gpio_inout ( & btv - > c , ( 1 < < 4 ) , 1 < < 4 ) ;
gpio = bttv_gpio_read ( & btv - > c ) ;
bttv_gpio_write ( & btv - > c , gpio & ~ ( 1 < < 4 ) ) ;
bttv_gpio_write ( & btv - > c , gpio | ( 1 < < 4 ) ) ;
2005-11-13 16:07:52 -08:00
} else {
/* init hardware-specific stuff */
2006-01-09 15:25:25 -02:00
bttv_gpio_inout ( & btv - > c , ir - > mask_keycode | ir - > mask_keydown , 0 ) ;
2005-11-13 16:07:52 -08:00
}
2005-04-16 15:20:36 -07:00
/* init input device */
2006-01-09 15:25:25 -02:00
ir - > dev = input_dev ;
2005-04-16 15:20:36 -07:00
snprintf ( ir - > name , sizeof ( ir - > name ) , " bttv IR (card=%d) " ,
2006-01-09 15:25:25 -02:00
btv - > c . type ) ;
2005-04-16 15:20:36 -07:00
snprintf ( ir - > phys , sizeof ( ir - > phys ) , " pci-%s/ir0 " ,
2006-01-09 15:25:25 -02:00
pci_name ( btv - > c . pci ) ) ;
2005-04-16 15:20:36 -07:00
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 ;
2006-01-09 15:25:25 -02:00
if ( btv - > c . pci - > subsystem_vendor ) {
input_dev - > id . vendor = btv - > c . pci - > subsystem_vendor ;
input_dev - > id . product = btv - > c . pci - > subsystem_device ;
2005-04-16 15:20:36 -07:00
} else {
2006-01-09 15:25:25 -02:00
input_dev - > id . vendor = btv - > c . pci - > vendor ;
input_dev - > id . product = btv - > c . pci - > device ;
2005-04-16 15:20:36 -07:00
}
2007-07-16 09:28:15 -03:00
input_dev - > dev . parent = & btv - > c . pci - > dev ;
2005-04-16 15:20:36 -07:00
2006-01-09 15:25:25 -02:00
btv - > remote = ir ;
2006-11-20 10:23:04 -03:00
bttv_ir_start ( btv , ir ) ;
2005-04-16 15:20:36 -07:00
/* all done */
2006-11-20 10:23:04 -03:00
err = input_register_device ( btv - > remote - > dev ) ;
if ( err )
goto err_out_stop ;
2005-11-13 16:07:52 -08:00
/* the remote isn't as bouncy as a keyboard */
2006-01-09 15:25:25 -02:00
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 :
bttv_ir_stop ( btv ) ;
btv - > remote = NULL ;
err_out_free :
input_free_device ( input_dev ) ;
kfree ( ir ) ;
return err ;
2005-04-16 15:20:36 -07:00
}
2006-01-09 15:25:25 -02:00
void bttv_input_fini ( struct bttv * btv )
2005-04-16 15:20:36 -07:00
{
2006-01-09 15:25:25 -02:00
if ( btv - > remote = = NULL )
return ;
2005-04-16 15:20:36 -07:00
2006-11-20 10:23:04 -03:00
bttv_ir_stop ( btv ) ;
2006-01-09 15:25:25 -02:00
input_unregister_device ( btv - > remote - > dev ) ;
kfree ( btv - > remote ) ;
btv - > remote = NULL ;
2005-04-16 15:20:36 -07:00
}
/*
* Local variables :
* c - basic - offset : 8
* End :
*/