2012-01-16 11:58:15 +04:00
/*
* radio - aztech . c - Aztech radio card driver
2005-04-17 02:20:36 +04:00
*
2012-01-16 11:58:15 +04:00
* Converted to the radio - isa framework by Hans Verkuil < hans . verkuil @ xs4all . nl >
2006-08-08 16:10:01 +04:00
* Converted to V4L2 API by Mauro Carvalho Chehab < mchehab @ infradead . org >
2006-04-08 23:06:16 +04:00
* Adapted to support the Video for Linux API by
2005-04-17 02:20:36 +04:00
* Russell Kroll < rkroll @ exploits . org > . Based on original tuner code by :
*
* Quay Ly
* Donald Song
2006-04-08 23:06:16 +04:00
* Jason Lewis ( jlewis @ twilight . vtc . vsc . edu )
2005-04-17 02:20:36 +04:00
* Scott McGrath ( smcgrath @ twilight . vtc . vsc . edu )
* William McGrath ( wmcgrath @ twilight . vtc . vsc . edu )
*
2012-01-16 11:58:15 +04:00
* Fully tested with the Keene USB FM Transmitter and the v4l2 - compliance tool .
2005-04-17 02:20:36 +04:00
*/
# include <linux/module.h> /* Modules */
# include <linux/init.h> /* Initdata */
2005-09-13 12:25:15 +04:00
# include <linux/ioport.h> /* request_region */
2005-04-17 02:20:36 +04:00
# include <linux/delay.h> /* udelay */
2006-08-08 16:10:01 +04:00
# include <linux/videodev2.h> /* kernel radio structs */
2009-03-06 19:48:18 +03:00
# include <linux/io.h> /* outb, outb_p */
2012-02-29 12:50:27 +04:00
# include <linux/slab.h>
2009-03-06 19:48:18 +03:00
# include <media/v4l2-device.h>
2008-07-20 15:12:02 +04:00
# include <media/v4l2-ioctl.h>
2012-01-16 11:58:15 +04:00
# include <media/v4l2-ctrls.h>
# include "radio-isa.h"
2013-07-19 20:46:17 +04:00
# include "lm7000.h"
2005-04-17 02:20:36 +04:00
2009-03-06 19:48:18 +03:00
MODULE_AUTHOR ( " Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath " ) ;
MODULE_DESCRIPTION ( " A driver for the Aztech radio card. " ) ;
MODULE_LICENSE ( " GPL " ) ;
2012-01-16 11:58:15 +04:00
MODULE_VERSION ( " 1.0.0 " ) ;
2006-08-08 16:10:01 +04:00
2005-04-17 02:20:36 +04:00
/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
# ifndef CONFIG_RADIO_AZTECH_PORT
# define CONFIG_RADIO_AZTECH_PORT -1
# endif
2012-01-16 11:58:15 +04:00
# define AZTECH_MAX 2
2005-04-17 02:20:36 +04:00
2012-01-16 11:58:15 +04:00
static int io [ AZTECH_MAX ] = { [ 0 ] = CONFIG_RADIO_AZTECH_PORT ,
[ 1 . . . ( AZTECH_MAX - 1 ) ] = - 1 } ;
static int radio_nr [ AZTECH_MAX ] = { [ 0 . . . ( AZTECH_MAX - 1 ) ] = - 1 } ;
static const int radio_wait_time = 1000 ;
2009-03-06 19:48:18 +03:00
2012-01-16 11:58:15 +04:00
module_param_array ( io , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( io , " I/O addresses of the Aztech card (0x350 or 0x358) " ) ;
module_param_array ( radio_nr , int , NULL , 0444 ) ;
MODULE_PARM_DESC ( radio_nr , " Radio device numbers " ) ;
struct aztech {
struct radio_isa_card isa ;
2005-04-17 02:20:36 +04:00
int curvol ;
} ;
2013-07-19 20:46:17 +04:00
/* bit definitions for register read */
# define AZTECH_BIT_NOT_TUNED (1 << 0)
# define AZTECH_BIT_MONO (1 << 1)
/* bit definitions for register write */
# define AZTECH_BIT_TUN_CE (1 << 1)
# define AZTECH_BIT_TUN_CLK (1 << 6)
# define AZTECH_BIT_TUN_DATA (1 << 7)
/* bits 0 and 2 are volume control, bits 3..5 are not connected */
2005-04-17 02:20:36 +04:00
2013-07-19 20:46:17 +04:00
static void aztech_set_pins ( void * handle , u8 pins )
2005-04-17 02:20:36 +04:00
{
2013-07-19 20:46:17 +04:00
struct radio_isa_card * isa = handle ;
struct aztech * az = container_of ( isa , struct aztech , isa ) ;
u8 bits = az - > curvol ;
if ( pins & LM7000_DATA )
bits | = AZTECH_BIT_TUN_DATA ;
if ( pins & LM7000_CLK )
bits | = AZTECH_BIT_TUN_CLK ;
if ( pins & LM7000_CE )
bits | = AZTECH_BIT_TUN_CE ;
outb_p ( bits , az - > isa . io ) ;
2005-04-17 02:20:36 +04:00
}
2012-01-16 11:58:15 +04:00
static struct radio_isa_card * aztech_alloc ( void )
2005-04-17 02:20:36 +04:00
{
2012-01-16 11:58:15 +04:00
struct aztech * az = kzalloc ( sizeof ( * az ) , GFP_KERNEL ) ;
2009-03-06 19:48:18 +03:00
2012-01-16 11:58:15 +04:00
return az ? & az - > isa : NULL ;
2005-04-17 02:20:36 +04:00
}
2012-01-16 11:58:15 +04:00
static int aztech_s_frequency ( struct radio_isa_card * isa , u32 freq )
2005-04-17 02:20:36 +04:00
{
2013-07-19 20:46:17 +04:00
lm7000_set_freq ( freq , isa , aztech_set_pins ) ;
2007-01-25 21:10:31 +03:00
2007-01-25 22:48:13 +03:00
return 0 ;
}
2012-01-16 11:58:15 +04:00
static u32 aztech_g_rxsubchans ( struct radio_isa_card * isa )
2009-03-06 19:48:18 +03:00
{
2013-07-19 20:46:18 +04:00
if ( inb ( isa - > io ) & AZTECH_BIT_MONO )
2012-01-16 11:58:15 +04:00
return V4L2_TUNER_SUB_MONO ;
return V4L2_TUNER_SUB_STEREO ;
2009-03-06 19:48:18 +03:00
}
2013-07-19 20:46:18 +04:00
static u32 aztech_g_signal ( struct radio_isa_card * isa )
2007-01-25 14:09:32 +03:00
{
2013-07-19 20:46:18 +04:00
return ( inb ( isa - > io ) & AZTECH_BIT_NOT_TUNED ) ? 0 : 0xffff ;
2007-01-25 14:09:32 +03:00
}
2012-01-16 11:58:15 +04:00
static int aztech_s_mute_volume ( struct radio_isa_card * isa , bool mute , int vol )
2007-01-25 14:09:32 +03:00
{
2012-01-16 11:58:15 +04:00
struct aztech * az = container_of ( isa , struct aztech , isa ) ;
2007-01-25 14:09:32 +03:00
2012-01-16 11:58:15 +04:00
if ( mute )
vol = 0 ;
az - > curvol = ( vol & 1 ) + ( ( vol & 2 ) < < 1 ) ;
outb ( az - > curvol , isa - > io ) ;
2007-01-25 14:09:32 +03:00
return 0 ;
}
2012-01-16 11:58:15 +04:00
static const struct radio_isa_ops aztech_ops = {
. alloc = aztech_alloc ,
. s_mute_volume = aztech_s_mute_volume ,
. s_frequency = aztech_s_frequency ,
. g_rxsubchans = aztech_g_rxsubchans ,
2013-07-19 20:46:18 +04:00
. g_signal = aztech_g_signal ,
2005-04-17 02:20:36 +04:00
} ;
2012-01-16 11:58:15 +04:00
static const int aztech_ioports [ ] = { 0x350 , 0x358 } ;
static struct radio_isa_driver aztech_driver = {
. driver = {
. match = radio_isa_match ,
. probe = radio_isa_probe ,
. remove = radio_isa_remove ,
. driver = {
. name = " radio-aztech " ,
} ,
} ,
. io_params = io ,
. radio_nr_params = radio_nr ,
. io_ports = aztech_ioports ,
. num_of_io_ports = ARRAY_SIZE ( aztech_ioports ) ,
2013-07-19 20:46:17 +04:00
. region_size = 8 ,
2012-01-16 11:58:15 +04:00
. card = " Aztech Radio " ,
. ops = & aztech_ops ,
. has_stereo = true ,
. max_volume = 3 ,
2005-04-17 02:20:36 +04:00
} ;
static int __init aztech_init ( void )
{
2012-01-16 11:58:15 +04:00
return isa_register_driver ( & aztech_driver . driver , AZTECH_MAX ) ;
2005-04-17 02:20:36 +04:00
}
2009-03-06 19:48:18 +03:00
static void __exit aztech_exit ( void )
2005-04-17 02:20:36 +04:00
{
2012-01-16 11:58:15 +04:00
isa_unregister_driver ( & aztech_driver . driver ) ;
2005-04-17 02:20:36 +04:00
}
module_init ( aztech_init ) ;
2009-03-06 19:48:18 +03:00
module_exit ( aztech_exit ) ;