2017-12-01 08:47:10 -05:00
// SPDX-License-Identifier: GPL-2.0
// tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices
//
// Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
//
// Copyright (c) 2007 Michel Ludwig <michel.ludwig@gmail.com>
// - DVB-T support
2009-09-14 09:42:41 -03:00
# include <linux/module.h>
# include <linux/kernel.h>
2010-03-30 02:52:33 +09:00
# include <linux/slab.h>
2009-09-14 09:42:41 -03:00
# include <linux/usb.h>
# include <linux/i2c.h>
# include "tm6000.h"
# include "tm6000-regs.h"
# include <media/v4l2-common.h>
# include <media/tuner.h>
2010-10-20 06:34:18 -03:00
# define USB_TIMEOUT (5 * HZ) /* ms */
2009-09-14 09:42:41 -03:00
2010-05-29 13:52:46 -03:00
int tm6000_read_write_usb ( struct tm6000_core * dev , u8 req_type , u8 req ,
u16 value , u16 index , u8 * buf , u16 len )
2009-09-14 09:42:41 -03:00
{
int ret , i ;
unsigned int pipe ;
2010-05-29 13:52:46 -03:00
u8 * data = NULL ;
2011-12-16 14:15:07 -03:00
int delay = 5000 ;
2009-09-14 09:42:41 -03:00
2013-01-30 03:03:43 -03:00
if ( len ) {
2009-09-14 09:42:41 -03:00
data = kzalloc ( len , GFP_KERNEL ) ;
2013-01-30 03:03:43 -03:00
if ( ! data )
return - ENOMEM ;
}
mutex_lock ( & dev - > usb_lock ) ;
2009-09-14 09:42:41 -03:00
if ( req_type & USB_DIR_IN )
2010-05-29 13:52:46 -03:00
pipe = usb_rcvctrlpipe ( dev - > udev , 0 ) ;
2009-09-14 09:42:41 -03:00
else {
2010-05-29 13:52:46 -03:00
pipe = usb_sndctrlpipe ( dev - > udev , 0 ) ;
2009-09-14 09:42:41 -03:00
memcpy ( data , buf , len ) ;
}
2008-11-28 06:42:24 -03:00
if ( tm6000_debug & V4L2_DEBUG_I2C ) {
2011-09-23 09:26:22 -03:00
printk ( KERN_DEBUG " (dev %p, pipe %08x): " , dev - > udev , pipe ) ;
2009-09-14 09:42:41 -03:00
2011-09-23 09:26:22 -03:00
printk ( KERN_CONT " %s: %02x %02x %02x %02x %02x %02x %02x %02x " ,
2010-05-29 13:52:46 -03:00
( req_type & USB_DIR_IN ) ? " IN " : " OUT " ,
req_type , req , value & 0xff , value > > 8 , index & 0xff ,
index > > 8 , len & 0xff , len > > 8 ) ;
2009-09-14 09:42:41 -03:00
2010-05-29 13:52:46 -03:00
if ( ! ( req_type & USB_DIR_IN ) ) {
2011-09-23 09:26:22 -03:00
printk ( KERN_CONT " >>> " ) ;
2010-05-29 13:52:46 -03:00
for ( i = 0 ; i < len ; i + + )
2011-09-23 09:26:22 -03:00
printk ( KERN_CONT " %02x " , buf [ i ] ) ;
printk ( KERN_CONT " \n " ) ;
2009-09-14 09:42:41 -03:00
}
}
2010-05-29 13:52:46 -03:00
ret = usb_control_msg ( dev - > udev , pipe , req , req_type , value , index ,
data , len , USB_TIMEOUT ) ;
2009-09-14 09:42:41 -03:00
if ( req_type & USB_DIR_IN )
memcpy ( buf , data , len ) ;
2008-11-28 06:42:24 -03:00
if ( tm6000_debug & V4L2_DEBUG_I2C ) {
2010-05-29 13:52:46 -03:00
if ( ret < 0 ) {
2009-09-14 09:42:41 -03:00
if ( req_type & USB_DIR_IN )
2011-09-23 09:26:22 -03:00
printk ( KERN_DEBUG " <<< (len=%d) \n " , len ) ;
2009-09-14 09:42:41 -03:00
2011-09-23 09:26:22 -03:00
printk ( KERN_CONT " %s: Error #%d \n " , __func__ , ret ) ;
2009-09-14 09:42:41 -03:00
} else if ( req_type & USB_DIR_IN ) {
2011-09-23 09:26:22 -03:00
printk ( KERN_CONT " <<< " ) ;
2010-05-29 13:52:46 -03:00
for ( i = 0 ; i < len ; i + + )
2011-09-23 09:26:22 -03:00
printk ( KERN_CONT " %02x " , buf [ i ] ) ;
printk ( KERN_CONT " \n " ) ;
2009-09-14 09:42:41 -03:00
}
}
kfree ( data ) ;
2011-12-06 09:05:03 -03:00
2011-12-16 14:15:07 -03:00
if ( dev - > quirks & TM6000_QUIRK_NO_USB_DELAY )
delay = 0 ;
if ( req = = REQ_16_SET_GET_I2C_WR1_RDN & & ! ( req_type & USB_DIR_IN ) ) {
unsigned int tsleep ;
/* Calculate delay time, 14000us for 64 bytes */
tsleep = ( len * 200 ) + 200 ;
if ( tsleep < delay )
tsleep = delay ;
usleep_range ( tsleep , tsleep + 1000 ) ;
}
else if ( delay )
usleep_range ( delay , delay + 1000 ) ;
2007-07-02 20:59:58 -03:00
2011-08-04 04:14:10 -03:00
mutex_unlock ( & dev - > usb_lock ) ;
2009-09-14 09:42:41 -03:00
return ret ;
}
2010-05-29 13:52:46 -03:00
int tm6000_set_reg ( struct tm6000_core * dev , u8 req , u16 value , u16 index )
2009-09-14 09:42:41 -03:00
{
return
2010-05-29 13:52:46 -03:00
tm6000_read_write_usb ( dev , USB_DIR_OUT | USB_TYPE_VENDOR ,
req , value , index , NULL , 0 ) ;
2009-09-14 09:42:41 -03:00
}
2010-02-10 14:53:57 -03:00
EXPORT_SYMBOL_GPL ( tm6000_set_reg ) ;
2009-09-14 09:42:41 -03:00
2010-05-29 13:52:46 -03:00
int tm6000_get_reg ( struct tm6000_core * dev , u8 req , u16 value , u16 index )
2009-09-14 09:42:41 -03:00
{
int rc ;
u8 buf [ 1 ] ;
2010-05-29 13:52:46 -03:00
rc = tm6000_read_write_usb ( dev , USB_DIR_IN | USB_TYPE_VENDOR , req ,
value , index , buf , 1 ) ;
2009-09-14 09:42:41 -03:00
2010-05-29 13:52:46 -03:00
if ( rc < 0 )
2009-09-14 09:42:41 -03:00
return rc ;
return * buf ;
}
2010-02-10 14:53:57 -03:00
EXPORT_SYMBOL_GPL ( tm6000_get_reg ) ;
2009-09-14 09:42:41 -03:00
2011-02-17 22:11:05 -03:00
int tm6000_set_reg_mask ( struct tm6000_core * dev , u8 req , u16 value ,
u16 index , u16 mask )
{
int rc ;
u8 buf [ 1 ] ;
u8 new_index ;
rc = tm6000_read_write_usb ( dev , USB_DIR_IN | USB_TYPE_VENDOR , req ,
2011-11-28 15:46:17 -03:00
value , 0 , buf , 1 ) ;
2011-02-17 22:11:05 -03:00
if ( rc < 0 )
return rc ;
new_index = ( buf [ 0 ] & ~ mask ) | ( index & mask ) ;
2011-11-28 15:46:17 -03:00
if ( new_index = = buf [ 0 ] )
2011-02-17 22:11:05 -03:00
return 0 ;
return tm6000_read_write_usb ( dev , USB_DIR_OUT | USB_TYPE_VENDOR ,
req , value , new_index , NULL , 0 ) ;
}
EXPORT_SYMBOL_GPL ( tm6000_set_reg_mask ) ;
2010-05-29 13:52:46 -03:00
int tm6000_get_reg16 ( struct tm6000_core * dev , u8 req , u16 value , u16 index )
2009-09-14 09:42:41 -03:00
{
int rc ;
u8 buf [ 2 ] ;
2010-05-29 13:52:46 -03:00
rc = tm6000_read_write_usb ( dev , USB_DIR_IN | USB_TYPE_VENDOR , req ,
value , index , buf , 2 ) ;
2009-09-14 09:42:41 -03:00
2010-05-29 13:52:46 -03:00
if ( rc < 0 )
2009-09-14 09:42:41 -03:00
return rc ;
return buf [ 1 ] | buf [ 0 ] < < 8 ;
}
2010-05-29 13:52:46 -03:00
int tm6000_get_reg32 ( struct tm6000_core * dev , u8 req , u16 value , u16 index )
2010-04-02 13:52:49 -03:00
{
int rc ;
u8 buf [ 4 ] ;
2010-05-29 13:52:46 -03:00
rc = tm6000_read_write_usb ( dev , USB_DIR_IN | USB_TYPE_VENDOR , req ,
value , index , buf , 4 ) ;
2010-04-02 13:52:49 -03:00
2010-05-29 13:52:46 -03:00
if ( rc < 0 )
2010-04-02 13:52:49 -03:00
return rc ;
return buf [ 3 ] | buf [ 2 ] < < 8 | buf [ 1 ] < < 16 | buf [ 0 ] < < 24 ;
}
2010-05-18 04:23:29 -03:00
int tm6000_i2c_reset ( struct tm6000_core * dev , u16 tsleep )
{
int rc ;
rc = tm6000_set_reg ( dev , REQ_03_SET_GET_MCU_PIN , TM6000_GPIO_CLK , 0 ) ;
if ( rc < 0 )
return rc ;
msleep ( tsleep ) ;
rc = tm6000_set_reg ( dev , REQ_03_SET_GET_MCU_PIN , TM6000_GPIO_CLK , 1 ) ;
msleep ( tsleep ) ;
return rc ;
}
2009-09-14 09:42:41 -03:00
void tm6000_set_fourcc_format ( struct tm6000_core * dev )
{
2008-10-25 08:56:16 -03:00
if ( dev - > dev_type = = TM6010 ) {
2010-05-03 04:25:59 -03:00
int val ;
2011-08-04 04:14:07 -03:00
val = tm6000_get_reg ( dev , TM6010_REQ07_RCC_ACTIVE_IF , 0 ) & 0xfc ;
2008-10-25 08:56:16 -03:00
if ( dev - > fourcc = = V4L2_PIX_FMT_UYVY )
2011-08-04 04:14:07 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RCC_ACTIVE_IF , val ) ;
2008-10-25 08:56:16 -03:00
else
2011-08-04 04:14:07 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RCC_ACTIVE_IF , val | 1 ) ;
2009-09-14 09:42:41 -03:00
} else {
2008-10-25 08:56:16 -03:00
if ( dev - > fourcc = = V4L2_PIX_FMT_UYVY )
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RC1_TRESHOLD , 0xd0 ) ;
2008-10-25 08:56:16 -03:00
else
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RC1_TRESHOLD , 0x90 ) ;
2009-09-14 09:42:41 -03:00
}
}
2010-10-12 12:11:55 -03:00
static void tm6000_set_vbi ( struct tm6000_core * dev )
2009-09-14 09:42:41 -03:00
{
2010-10-12 12:11:55 -03:00
/*
* FIXME :
* VBI lines and start / end are different between 60 Hz and 50 Hz
* So , it is very likely that we need to change the config to
* something that takes it into account , doing something different
* if ( dev - > norm & V4L2_STD_525_60 )
*/
2010-10-07 09:42:43 -03:00
2008-01-08 11:19:22 -03:00
if ( dev - > dev_type = = TM6010 ) {
2010-04-29 09:24:47 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_R3F_RESET , 0x01 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R41_TELETEXT_VBI_CODE1 , 0x27 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL , 0x55 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7 , 0x66 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8 , 0x66 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22 , 0x66 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23 , 0x00 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES , 0x00 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN , 0x01 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN , 0x00 ) ;
tm6000_set_reg ( dev ,
TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN , 0x02 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R58_VBI_CAPTION_DTO1 , 0x35 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R59_VBI_CAPTION_DTO0 , 0xa0 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R5A_VBI_TELETEXT_DTO1 , 0x11 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R5B_VBI_TELETEXT_DTO0 , 0x4c ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R40_TELETEXT_VBI_CODE0 , 0x01 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R3F_RESET , 0x00 ) ;
2010-10-12 12:11:55 -03:00
}
}
int tm6000_init_analog_mode ( struct tm6000_core * dev )
{
struct v4l2_frequency f ;
if ( dev - > dev_type = = TM6010 ) {
2011-08-04 04:14:08 -03:00
u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE ;
if ( ! dev - > radio )
active | = TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE ;
2011-05-09 16:53:58 -03:00
/* Enable video and audio */
2011-08-04 04:14:07 -03:00
tm6000_set_reg_mask ( dev , TM6010_REQ07_RCC_ACTIVE_IF ,
2011-08-04 04:14:08 -03:00
active , 0x60 ) ;
2011-05-09 16:53:58 -03:00
/* Disable TS input */
2011-02-17 22:11:05 -03:00
tm6000_set_reg_mask ( dev , TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE ,
0x00 , 0x40 ) ;
2009-09-14 09:42:41 -03:00
} else {
2008-01-08 11:19:22 -03:00
/* Enables soft reset */
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_R3F_RESET , 0x01 ) ;
2008-01-08 11:19:22 -03:00
2010-05-29 13:52:46 -03:00
if ( dev - > scaler )
2011-05-09 16:53:58 -03:00
/* Disable Hfilter and Enable TS Drop err */
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE , 0x20 ) ;
2010-05-29 13:52:46 -03:00
else /* Enable Hfilter and disable TS Drop err */
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE , 0x80 ) ;
2009-09-14 09:42:41 -03:00
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RC3_HSTART1 , 0x88 ) ;
2011-01-25 13:40:55 -03:00
tm6000_set_reg ( dev , TM6000_REQ07_RDA_CLK_SEL , 0x23 ) ;
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RD1_ADDR_FOR_REQ1 , 0xc0 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_RD2_ADDR_FOR_REQ2 , 0xd8 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_RD6_ENDP_REQ1_REQ2 , 0x06 ) ;
2011-01-25 13:40:55 -03:00
tm6000_set_reg ( dev , TM6000_REQ07_RDF_PWDOWN_ACLK , 0x1f ) ;
2009-09-14 09:42:41 -03:00
2008-01-08 11:19:22 -03:00
/* AP Software reset */
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RFF_SOFT_RESET , 0x08 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_RFF_SOFT_RESET , 0x00 ) ;
2009-09-14 09:42:41 -03:00
2008-01-08 11:19:22 -03:00
tm6000_set_fourcc_format ( dev ) ;
2009-09-14 09:42:41 -03:00
2008-01-08 11:19:22 -03:00
/* Disables soft reset */
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_R3F_RESET , 0x00 ) ;
2008-01-08 11:19:22 -03:00
}
2009-09-14 09:42:41 -03:00
msleep ( 20 ) ;
2008-01-08 11:19:22 -03:00
/* Tuner firmware can now be loaded */
2010-10-07 09:42:43 -03:00
/*
* FIXME : This is a hack ! xc3028 " sleeps " when no channel is detected
* for more than a few seconds . Not sure why , as this behavior does
* not happen on other devices with xc3028 . So , I suspect that it
2011-08-04 04:14:01 -03:00
* is yet another bug at tm6000 . After start sleeping , decoding
2010-10-07 09:42:43 -03:00
* doesn ' t start automatically . Instead , it requires some
* I2C commands to wake it up . As we want to have image at the
* beginning , we needed to add this hack . The better would be to
* discover some way to make tm6000 to wake up without this hack .
*/
2010-05-29 13:52:46 -03:00
f . frequency = dev - > freq ;
2009-09-14 16:37:13 -03:00
v4l2_device_call_all ( & dev - > v4l2_dev , 0 , tuner , s_frequency , & f ) ;
2009-09-14 09:42:41 -03:00
msleep ( 100 ) ;
2011-05-09 16:53:53 -03:00
tm6000_set_standard ( dev ) ;
2010-10-12 12:11:55 -03:00
tm6000_set_vbi ( dev ) ;
2010-05-29 13:52:46 -03:00
tm6000_set_audio_bitrate ( dev , 48000 ) ;
2009-09-14 09:42:41 -03:00
2010-05-23 15:29:25 -03:00
/* switch dvb led off */
if ( dev - > gpio . dvb_led ) {
tm6000_set_reg ( dev , REQ_03_SET_GET_MCU_PIN ,
dev - > gpio . dvb_led , 0x01 ) ;
}
2009-09-14 09:42:41 -03:00
return 0 ;
}
2010-05-29 13:52:46 -03:00
int tm6000_init_digital_mode ( struct tm6000_core * dev )
2007-08-21 17:37:22 -03:00
{
2010-02-03 17:27:23 -03:00
if ( dev - > dev_type = = TM6010 ) {
2011-05-09 16:53:58 -03:00
/* Disable video and audio */
2011-08-04 04:14:07 -03:00
tm6000_set_reg_mask ( dev , TM6010_REQ07_RCC_ACTIVE_IF ,
2011-05-09 16:53:58 -03:00
0x00 , 0x60 ) ;
/* Enable TS input */
tm6000_set_reg_mask ( dev , TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE ,
0x40 , 0x40 ) ;
/* all power down, but not the digital data port */
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RFE_POWER_DOWN , 0x28 ) ;
tm6000_set_reg ( dev , TM6010_REQ08_RE2_POWER_DOWN_CTRL1 , 0xfc ) ;
tm6000_set_reg ( dev , TM6010_REQ08_RE6_POWER_DOWN_CTRL2 , 0xff ) ;
2010-02-03 17:27:23 -03:00
} else {
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RFF_SOFT_RESET , 0x08 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_RFF_SOFT_RESET , 0x00 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_R3F_RESET , 0x01 ) ;
2011-01-25 13:40:55 -03:00
tm6000_set_reg ( dev , TM6000_REQ07_RDF_PWDOWN_ACLK , 0x08 ) ;
tm6000_set_reg ( dev , TM6000_REQ07_RE2_VADC_STATUS_CTL , 0x0c ) ;
tm6000_set_reg ( dev , TM6000_REQ07_RE8_VADC_PWDOWN_CTL , 0xff ) ;
tm6000_set_reg ( dev , TM6000_REQ07_REB_VADC_AADC_MODE , 0xd8 ) ;
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE , 0x40 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_RC1_TRESHOLD , 0xd0 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_RC3_HSTART1 , 0x09 ) ;
2011-01-25 13:40:55 -03:00
tm6000_set_reg ( dev , TM6000_REQ07_RDA_CLK_SEL , 0x37 ) ;
2010-03-11 10:26:46 -03:00
tm6000_set_reg ( dev , TM6010_REQ07_RD1_ADDR_FOR_REQ1 , 0xd8 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_RD2_ADDR_FOR_REQ2 , 0xc0 ) ;
tm6000_set_reg ( dev , TM6010_REQ07_RD6_ENDP_REQ1_REQ2 , 0x60 ) ;
2011-01-25 13:40:55 -03:00
tm6000_set_reg ( dev , TM6000_REQ07_RE2_VADC_STATUS_CTL , 0x0c ) ;
tm6000_set_reg ( dev , TM6000_REQ07_RE8_VADC_PWDOWN_CTL , 0xff ) ;
tm6000_set_reg ( dev , TM6000_REQ07_REB_VADC_AADC_MODE , 0x08 ) ;
2010-02-03 17:27:23 -03:00
msleep ( 50 ) ;
2010-05-29 13:52:46 -03:00
tm6000_set_reg ( dev , REQ_04_EN_DISABLE_MCU_INT , 0x0020 , 0x00 ) ;
2010-02-03 17:27:23 -03:00
msleep ( 50 ) ;
2010-05-29 13:52:46 -03:00
tm6000_set_reg ( dev , REQ_04_EN_DISABLE_MCU_INT , 0x0020 , 0x01 ) ;
2010-02-03 17:27:23 -03:00
msleep ( 50 ) ;
2010-05-29 13:52:46 -03:00
tm6000_set_reg ( dev , REQ_04_EN_DISABLE_MCU_INT , 0x0020 , 0x00 ) ;
2010-02-03 17:27:23 -03:00
msleep ( 100 ) ;
}
2010-05-23 15:29:25 -03:00
/* switch dvb led on */
if ( dev - > gpio . dvb_led ) {
tm6000_set_reg ( dev , REQ_03_SET_GET_MCU_PIN ,
dev - > gpio . dvb_led , 0x00 ) ;
}
2007-08-21 17:37:22 -03:00
return 0 ;
}
2010-05-30 09:19:04 -03:00
EXPORT_SYMBOL ( tm6000_init_digital_mode ) ;
2009-09-14 09:42:41 -03:00
2008-01-08 11:19:22 -03:00
struct reg_init {
u8 req ;
u8 reg ;
u8 val ;
} ;
2009-09-14 09:42:41 -03:00
/* The meaning of those initializations are unknown */
2011-08-04 04:14:01 -03:00
static struct reg_init tm6000_init_tab [ ] = {
2009-09-14 09:42:41 -03:00
/* REG VALUE */
2011-01-25 13:40:55 -03:00
{ TM6000_REQ07_RDF_PWDOWN_ACLK , 0x1f } ,
2010-03-11 10:26:46 -03:00
{ TM6010_REQ07_RFF_SOFT_RESET , 0x08 } ,
{ TM6010_REQ07_RFF_SOFT_RESET , 0x00 } ,
{ TM6010_REQ07_RD5_POWERSAVE , 0x4f } ,
2011-01-25 13:40:55 -03:00
{ TM6000_REQ07_RDA_CLK_SEL , 0x23 } ,
{ TM6000_REQ07_RDB_OUT_SEL , 0x08 } ,
{ TM6000_REQ07_RE2_VADC_STATUS_CTL , 0x00 } ,
{ TM6000_REQ07_RE3_VADC_INP_LPF_SEL1 , 0x10 } ,
{ TM6000_REQ07_RE5_VADC_INP_LPF_SEL2 , 0x00 } ,
{ TM6000_REQ07_RE8_VADC_PWDOWN_CTL , 0x00 } ,
{ TM6000_REQ07_REB_VADC_AADC_MODE , 0x64 } , /* 48000 bits/sample, external input */
{ TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL , 0xc2 } ,
2010-03-11 10:26:46 -03:00
{ TM6010_REQ07_R3F_RESET , 0x01 } , /* Start of soft reset */
{ TM6010_REQ07_R00_VIDEO_CONTROL0 , 0x00 } ,
{ TM6010_REQ07_R01_VIDEO_CONTROL1 , 0x07 } ,
{ TM6010_REQ07_R02_VIDEO_CONTROL2 , 0x5f } ,
{ TM6010_REQ07_R03_YC_SEP_CONTROL , 0x00 } ,
{ TM6010_REQ07_R05_NOISE_THRESHOLD , 0x64 } ,
{ TM6010_REQ07_R07_OUTPUT_CONTROL , 0x01 } ,
{ TM6010_REQ07_R08_LUMA_CONTRAST_ADJ , 0x82 } ,
{ TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ , 0x36 } ,
{ TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ , 0x50 } ,
{ TM6010_REQ07_R0C_CHROMA_AGC_CONTROL , 0x6a } ,
{ TM6010_REQ07_R11_AGC_PEAK_CONTROL , 0xc9 } ,
{ TM6010_REQ07_R12_AGC_GATE_STARTH , 0x07 } ,
{ TM6010_REQ07_R13_AGC_GATE_STARTL , 0x3b } ,
{ TM6010_REQ07_R14_AGC_GATE_WIDTH , 0x47 } ,
{ TM6010_REQ07_R15_AGC_BP_DELAY , 0x6f } ,
{ TM6010_REQ07_R17_HLOOP_MAXSTATE , 0xcd } ,
{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3 , 0x1e } ,
{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2 , 0x8b } ,
{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1 , 0xa2 } ,
{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0 , 0xe9 } ,
{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3 , 0x1c } ,
{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2 , 0xcc } ,
{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1 , 0xcc } ,
{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0 , 0xcd } ,
{ TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME , 0x3c } ,
{ TM6010_REQ07_R21_HSYNC_PHASE_OFFSET , 0x3c } ,
{ TM6010_REQ07_R2D_CHROMA_BURST_END , 0x48 } ,
{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART , 0x88 } ,
{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART , 0x22 } ,
{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT , 0x61 } ,
{ TM6010_REQ07_R32_VSYNC_HLOCK_MIN , 0x74 } ,
{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX , 0x1c } ,
{ TM6010_REQ07_R34_VSYNC_AGC_MIN , 0x74 } ,
{ TM6010_REQ07_R35_VSYNC_AGC_MAX , 0x1c } ,
{ TM6010_REQ07_R36_VSYNC_VBI_MIN , 0x7a } ,
{ TM6010_REQ07_R37_VSYNC_VBI_MAX , 0x26 } ,
{ TM6010_REQ07_R38_VSYNC_THRESHOLD , 0x40 } ,
{ TM6010_REQ07_R39_VSYNC_TIME_CONSTANT , 0x0a } ,
{ TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL , 0x55 } ,
{ TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21 , 0x11 } ,
{ TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN , 0x01 } ,
{ TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN , 0x02 } ,
{ TM6010_REQ07_R58_VBI_CAPTION_DTO1 , 0x35 } ,
{ TM6010_REQ07_R59_VBI_CAPTION_DTO0 , 0xa0 } ,
{ TM6010_REQ07_R80_COMB_FILTER_TRESHOLD , 0x15 } ,
{ TM6010_REQ07_R82_COMB_FILTER_CONFIG , 0x42 } ,
{ TM6010_REQ07_RC1_TRESHOLD , 0xd0 } ,
{ TM6010_REQ07_RC3_HSTART1 , 0x88 } ,
{ TM6010_REQ07_R3F_RESET , 0x00 } , /* End of the soft reset */
2010-03-11 10:26:45 -03:00
{ TM6010_REQ05_R18_IMASK7 , 0x00 } ,
2008-01-08 11:19:22 -03:00
} ;
2011-08-04 04:14:01 -03:00
static struct reg_init tm6010_init_tab [ ] = {
2010-03-11 10:26:46 -03:00
{ TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE , 0x00 } ,
{ TM6010_REQ07_RC4_HSTART0 , 0xa0 } ,
{ TM6010_REQ07_RC6_HEND0 , 0x40 } ,
{ TM6010_REQ07_RCA_VEND0 , 0x31 } ,
2011-08-04 04:14:07 -03:00
{ TM6010_REQ07_RCC_ACTIVE_IF , 0xe1 } ,
2010-03-11 10:26:46 -03:00
{ TM6010_REQ07_RE0_DVIDEO_SOURCE , 0x03 } ,
{ TM6010_REQ07_RFE_POWER_DOWN , 0x7f } ,
{ TM6010_REQ08_RE2_POWER_DOWN_CTRL1 , 0xf0 } ,
{ TM6010_REQ08_RE3_ADC_IN1_SEL , 0xf4 } ,
{ TM6010_REQ08_RE4_ADC_IN2_SEL , 0xf8 } ,
{ TM6010_REQ08_RE6_POWER_DOWN_CTRL2 , 0x00 } ,
{ TM6010_REQ08_REA_BUFF_DRV_CTRL , 0xf2 } ,
{ TM6010_REQ08_REB_SIF_GAIN_CTRL , 0xf0 } ,
{ TM6010_REQ08_REC_REVERSE_YC_CTRL , 0xc2 } ,
{ TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG , 0x60 } ,
{ TM6010_REQ08_RF1_AADC_POWER_DOWN , 0xfc } ,
{ TM6010_REQ07_R3F_RESET , 0x01 } ,
{ TM6010_REQ07_R00_VIDEO_CONTROL0 , 0x00 } ,
{ TM6010_REQ07_R01_VIDEO_CONTROL1 , 0x07 } ,
{ TM6010_REQ07_R02_VIDEO_CONTROL2 , 0x5f } ,
{ TM6010_REQ07_R03_YC_SEP_CONTROL , 0x00 } ,
{ TM6010_REQ07_R05_NOISE_THRESHOLD , 0x64 } ,
{ TM6010_REQ07_R07_OUTPUT_CONTROL , 0x01 } ,
{ TM6010_REQ07_R08_LUMA_CONTRAST_ADJ , 0x82 } ,
{ TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ , 0x36 } ,
{ TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ , 0x50 } ,
{ TM6010_REQ07_R0C_CHROMA_AGC_CONTROL , 0x6a } ,
{ TM6010_REQ07_R11_AGC_PEAK_CONTROL , 0xc9 } ,
{ TM6010_REQ07_R12_AGC_GATE_STARTH , 0x07 } ,
{ TM6010_REQ07_R13_AGC_GATE_STARTL , 0x3b } ,
{ TM6010_REQ07_R14_AGC_GATE_WIDTH , 0x47 } ,
{ TM6010_REQ07_R15_AGC_BP_DELAY , 0x6f } ,
{ TM6010_REQ07_R17_HLOOP_MAXSTATE , 0xcd } ,
{ TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3 , 0x1e } ,
{ TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2 , 0x8b } ,
{ TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1 , 0xa2 } ,
{ TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0 , 0xe9 } ,
{ TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3 , 0x1c } ,
{ TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2 , 0xcc } ,
{ TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1 , 0xcc } ,
{ TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0 , 0xcd } ,
{ TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME , 0x3c } ,
{ TM6010_REQ07_R21_HSYNC_PHASE_OFFSET , 0x3c } ,
{ TM6010_REQ07_R2D_CHROMA_BURST_END , 0x48 } ,
{ TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART , 0x88 } ,
{ TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART , 0x22 } ,
{ TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT , 0x61 } ,
{ TM6010_REQ07_R32_VSYNC_HLOCK_MIN , 0x74 } ,
{ TM6010_REQ07_R33_VSYNC_HLOCK_MAX , 0x1c } ,
{ TM6010_REQ07_R34_VSYNC_AGC_MIN , 0x74 } ,
{ TM6010_REQ07_R35_VSYNC_AGC_MAX , 0x1c } ,
{ TM6010_REQ07_R36_VSYNC_VBI_MIN , 0x7a } ,
{ TM6010_REQ07_R37_VSYNC_VBI_MAX , 0x26 } ,
{ TM6010_REQ07_R38_VSYNC_THRESHOLD , 0x40 } ,
{ TM6010_REQ07_R39_VSYNC_TIME_CONSTANT , 0x0a } ,
{ TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL , 0x55 } ,
{ TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21 , 0x11 } ,
{ TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN , 0x01 } ,
{ TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN , 0x02 } ,
{ TM6010_REQ07_R58_VBI_CAPTION_DTO1 , 0x35 } ,
{ TM6010_REQ07_R59_VBI_CAPTION_DTO0 , 0xa0 } ,
{ TM6010_REQ07_R80_COMB_FILTER_TRESHOLD , 0x15 } ,
{ TM6010_REQ07_R82_COMB_FILTER_CONFIG , 0x42 } ,
{ TM6010_REQ07_RC1_TRESHOLD , 0xd0 } ,
{ TM6010_REQ07_RC3_HSTART1 , 0x88 } ,
{ TM6010_REQ07_R3F_RESET , 0x00 } ,
2008-01-08 11:19:22 -03:00
2010-03-11 10:26:45 -03:00
{ TM6010_REQ05_R18_IMASK7 , 0x00 } ,
2008-01-08 11:19:22 -03:00
2011-11-29 11:35:55 -03:00
{ TM6010_REQ07_RDC_IR_LEADER1 , 0xaa } ,
{ TM6010_REQ07_RDD_IR_LEADER0 , 0x30 } ,
{ TM6010_REQ07_RDE_IR_PULSE_CNT1 , 0x20 } ,
{ TM6010_REQ07_RDF_IR_PULSE_CNT0 , 0xd0 } ,
2010-02-15 14:37:16 -03:00
{ REQ_04_EN_DISABLE_MCU_INT , 0x02 , 0x00 } ,
2011-11-29 11:30:30 -03:00
{ TM6010_REQ07_RD8_IR , 0x0f } ,
2010-02-15 14:37:16 -03:00
2008-01-08 11:19:22 -03:00
/* set remote wakeup key:any key wakeup */
2010-03-11 10:26:46 -03:00
{ TM6010_REQ07_RE5_REMOTE_WAKEUP , 0xfe } ,
2011-11-29 11:35:55 -03:00
{ TM6010_REQ07_RDA_IR_WAKEUP_SEL , 0xff } ,
2009-09-14 09:42:41 -03:00
} ;
2010-05-29 13:52:46 -03:00
int tm6000_init ( struct tm6000_core * dev )
2009-09-14 09:42:41 -03:00
{
2010-05-29 13:52:46 -03:00
int board , rc = 0 , i , size ;
2008-01-08 11:19:22 -03:00
struct reg_init * tab ;
2010-11-09 13:50:28 -03:00
/* Check board revision */
board = tm6000_get_reg32 ( dev , REQ_40_GET_VERSION , 0 , 0 ) ;
if ( board > = 0 ) {
switch ( board & 0xff ) {
case 0xf3 :
printk ( KERN_INFO " Found tm6000 \n " ) ;
if ( dev - > dev_type ! = TM6000 )
dev - > dev_type = TM6000 ;
break ;
case 0xf4 :
printk ( KERN_INFO " Found tm6010 \n " ) ;
if ( dev - > dev_type ! = TM6010 )
dev - > dev_type = TM6010 ;
break ;
default :
printk ( KERN_INFO " Unknown board version = 0x%08x \n " , board ) ;
}
} else
printk ( KERN_ERR " Error %i while retrieving board version \n " , board ) ;
2008-01-08 11:19:22 -03:00
if ( dev - > dev_type = = TM6010 ) {
tab = tm6010_init_tab ;
size = ARRAY_SIZE ( tm6010_init_tab ) ;
} else {
tab = tm6000_init_tab ;
size = ARRAY_SIZE ( tm6000_init_tab ) ;
}
2009-09-14 09:42:41 -03:00
/* Load board's initialization table */
2010-05-29 13:52:46 -03:00
for ( i = 0 ; i < size ; i + + ) {
rc = tm6000_set_reg ( dev , tab [ i ] . req , tab [ i ] . reg , tab [ i ] . val ) ;
if ( rc < 0 ) {
[media] tm6000: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:19 -02:00
printk ( KERN_ERR " Error %i while setting req %d, reg %d to value %d \n " ,
rc ,
2010-05-29 13:52:46 -03:00
tab [ i ] . req , tab [ i ] . reg , tab [ i ] . val ) ;
2009-09-14 09:42:41 -03:00
return rc ;
}
}
2008-01-08 11:19:22 -03:00
msleep ( 5 ) ; /* Just to be conservative */
2010-02-08 08:43:41 -02:00
rc = tm6000_cards_setup ( dev ) ;
2007-07-02 20:59:58 -03:00
2010-02-08 08:43:41 -02:00
return rc ;
2009-09-14 09:42:41 -03:00
}
2011-08-04 04:14:13 -03:00
2008-01-11 13:19:45 -03:00
int tm6000_set_audio_bitrate ( struct tm6000_core * dev , int bitrate )
2009-09-14 09:42:41 -03:00
{
2011-02-17 22:11:05 -03:00
int val = 0 ;
u8 areg_f0 = 0x60 ; /* ADC MCLK = 250 Fs */
u8 areg_0a = 0x91 ; /* SIF 48KHz */
switch ( bitrate ) {
case 48000 :
areg_f0 = 0x60 ; /* ADC MCLK = 250 Fs */
areg_0a = 0x91 ; /* SIF 48KHz */
dev - > audio_bitrate = bitrate ;
break ;
case 32000 :
areg_f0 = 0x00 ; /* ADC MCLK = 375 Fs */
areg_0a = 0x90 ; /* SIF 32KHz */
dev - > audio_bitrate = bitrate ;
break ;
default :
return - EINVAL ;
}
2009-09-14 09:42:41 -03:00
2011-01-25 13:40:55 -03:00
/* enable I2S, if we use sif or external I2S device */
2010-06-07 11:57:01 -03:00
if ( dev - > dev_type = = TM6010 ) {
2011-02-17 22:11:05 -03:00
val = tm6000_set_reg ( dev , TM6010_REQ08_R0A_A_I2S_MOD , areg_0a ) ;
2010-06-07 11:57:01 -03:00
if ( val < 0 )
return val ;
2011-02-17 22:11:05 -03:00
val = tm6000_set_reg_mask ( dev , TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG ,
areg_f0 , 0xf0 ) ;
2011-01-25 13:40:55 -03:00
if ( val < 0 )
return val ;
} else {
2011-02-17 22:11:05 -03:00
val = tm6000_set_reg_mask ( dev , TM6000_REQ07_REB_VADC_AADC_MODE ,
areg_f0 , 0xf0 ) ;
2011-01-25 13:40:55 -03:00
if ( val < 0 )
return val ;
}
2011-02-17 22:11:05 -03:00
return 0 ;
}
EXPORT_SYMBOL_GPL ( tm6000_set_audio_bitrate ) ;
2009-09-14 09:42:41 -03:00
2011-05-09 16:53:53 -03:00
int tm6000_set_audio_rinput ( struct tm6000_core * dev )
2011-02-17 22:11:05 -03:00
{
if ( dev - > dev_type = = TM6010 ) {
/* Audio crossbar setting, default SIF1 */
2011-05-09 16:53:51 -03:00
u8 areg_f0 ;
2011-11-24 12:20:12 -03:00
u8 areg_07 = 0x10 ;
2011-02-17 22:11:05 -03:00
2011-05-09 16:53:51 -03:00
switch ( dev - > rinput . amux ) {
case TM6000_AMUX_SIF1 :
case TM6000_AMUX_SIF2 :
2011-02-17 22:11:05 -03:00
areg_f0 = 0x03 ;
2011-11-24 12:20:12 -03:00
areg_07 = 0x30 ;
2011-02-17 22:11:05 -03:00
break ;
2011-05-09 16:53:51 -03:00
case TM6000_AMUX_ADC1 :
2011-02-17 22:11:05 -03:00
areg_f0 = 0x00 ;
break ;
2011-05-09 16:53:51 -03:00
case TM6000_AMUX_ADC2 :
2011-02-17 22:11:05 -03:00
areg_f0 = 0x08 ;
break ;
2011-05-09 16:53:51 -03:00
case TM6000_AMUX_I2S :
areg_f0 = 0x04 ;
break ;
2011-02-17 22:11:05 -03:00
default :
2011-05-09 16:53:51 -03:00
printk ( KERN_INFO " %s: audio input dosn't support \n " ,
dev - > name ) ;
2011-02-17 22:11:05 -03:00
return 0 ;
break ;
}
/* Set audio input crossbar */
tm6000_set_reg_mask ( dev , TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG ,
areg_f0 , 0x0f ) ;
2011-11-24 12:20:12 -03:00
/* Mux overflow workaround */
tm6000_set_reg_mask ( dev , TM6010_REQ07_R07_OUTPUT_CONTROL ,
areg_07 , 0xf0 ) ;
2011-02-17 22:11:05 -03:00
} else {
2011-05-09 16:53:51 -03:00
u8 areg_eb ;
2011-02-17 22:11:05 -03:00
/* Audio setting, default LINE1 */
2011-05-09 16:53:51 -03:00
switch ( dev - > rinput . amux ) {
case TM6000_AMUX_ADC1 :
2011-02-17 22:11:05 -03:00
areg_eb = 0x00 ;
break ;
2011-05-09 16:53:51 -03:00
case TM6000_AMUX_ADC2 :
2011-02-17 22:11:05 -03:00
areg_eb = 0x04 ;
break ;
default :
2011-05-09 16:53:51 -03:00
printk ( KERN_INFO " %s: audio input dosn't support \n " ,
dev - > name ) ;
2011-02-17 22:11:05 -03:00
return 0 ;
break ;
}
/* Set audio input */
tm6000_set_reg_mask ( dev , TM6000_REQ07_REB_VADC_AADC_MODE ,
areg_eb , 0x0f ) ;
}
return 0 ;
}
2011-08-04 04:14:01 -03:00
static void tm6010_set_mute_sif ( struct tm6000_core * dev , u8 mute )
2011-02-17 22:11:05 -03:00
{
u8 mute_reg = 0 ;
if ( mute )
mute_reg = 0x08 ;
tm6000_set_reg_mask ( dev , TM6010_REQ08_R0A_A_I2S_MOD , mute_reg , 0x08 ) ;
}
2011-08-04 04:14:01 -03:00
static void tm6010_set_mute_adc ( struct tm6000_core * dev , u8 mute )
2011-02-17 22:11:05 -03:00
{
u8 mute_reg = 0 ;
if ( mute )
mute_reg = 0x20 ;
if ( dev - > dev_type = = TM6010 ) {
tm6000_set_reg_mask ( dev , TM6010_REQ08_RF2_LEFT_CHANNEL_VOL ,
mute_reg , 0x20 ) ;
tm6000_set_reg_mask ( dev , TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL ,
mute_reg , 0x20 ) ;
} else {
tm6000_set_reg_mask ( dev , TM6000_REQ07_REC_VADC_AADC_LVOL ,
mute_reg , 0x20 ) ;
tm6000_set_reg_mask ( dev , TM6000_REQ07_RED_VADC_AADC_RVOL ,
mute_reg , 0x20 ) ;
}
}
int tm6000_tvaudio_set_mute ( struct tm6000_core * dev , u8 mute )
{
2011-05-09 16:53:51 -03:00
enum tm6000_mux mux ;
2011-02-17 22:11:05 -03:00
if ( dev - > radio )
2011-05-09 16:53:51 -03:00
mux = dev - > rinput . amux ;
2011-02-17 22:11:05 -03:00
else
2011-05-09 16:53:51 -03:00
mux = dev - > vinput [ dev - > input ] . amux ;
2011-02-17 22:11:05 -03:00
2011-05-09 16:53:51 -03:00
switch ( mux ) {
case TM6000_AMUX_SIF1 :
case TM6000_AMUX_SIF2 :
2011-02-17 22:11:05 -03:00
if ( dev - > dev_type = = TM6010 )
tm6010_set_mute_sif ( dev , mute ) ;
else {
[media] tm6000: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:19 -02:00
printk ( KERN_INFO " ERROR: TM5600 and TM6000 don't has SIF audio inputs. Please check the %s configuration. \n " ,
dev - > name ) ;
2011-02-17 22:11:05 -03:00
return - EINVAL ;
}
2009-09-14 09:42:41 -03:00
break ;
2011-05-09 16:53:51 -03:00
case TM6000_AMUX_ADC1 :
case TM6000_AMUX_ADC2 :
2011-02-17 22:11:05 -03:00
tm6010_set_mute_adc ( dev , mute ) ;
break ;
default :
return - EINVAL ;
2009-09-14 09:42:41 -03:00
break ;
}
2011-02-17 22:11:05 -03:00
return 0 ;
}
2011-08-04 04:14:01 -03:00
static void tm6010_set_volume_sif ( struct tm6000_core * dev , int vol )
2011-02-17 22:11:05 -03:00
{
u8 vol_reg ;
2009-09-14 09:42:41 -03:00
2011-02-17 22:11:05 -03:00
vol_reg = vol & 0x0F ;
if ( vol < 0 )
vol_reg | = 0x40 ;
tm6000_set_reg ( dev , TM6010_REQ08_R07_A_LEFT_VOL , vol_reg ) ;
tm6000_set_reg ( dev , TM6010_REQ08_R08_A_RIGHT_VOL , vol_reg ) ;
2009-09-14 09:42:41 -03:00
}
2011-02-17 22:11:05 -03:00
2011-08-04 04:14:01 -03:00
static void tm6010_set_volume_adc ( struct tm6000_core * dev , int vol )
2011-02-17 22:11:05 -03:00
{
u8 vol_reg ;
vol_reg = ( vol + 0x10 ) & 0x1f ;
if ( dev - > dev_type = = TM6010 ) {
tm6000_set_reg ( dev , TM6010_REQ08_RF2_LEFT_CHANNEL_VOL , vol_reg ) ;
tm6000_set_reg ( dev , TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL , vol_reg ) ;
} else {
tm6000_set_reg ( dev , TM6000_REQ07_REC_VADC_AADC_LVOL , vol_reg ) ;
tm6000_set_reg ( dev , TM6000_REQ07_RED_VADC_AADC_RVOL , vol_reg ) ;
}
}
void tm6000_set_volume ( struct tm6000_core * dev , int vol )
{
2011-05-09 16:53:51 -03:00
enum tm6000_mux mux ;
2011-02-17 22:11:05 -03:00
if ( dev - > radio ) {
2011-05-09 16:53:51 -03:00
mux = dev - > rinput . amux ;
2011-02-17 22:11:05 -03:00
vol + = 8 ; /* Offset to 0 dB */
} else
2011-05-09 16:53:51 -03:00
mux = dev - > vinput [ dev - > input ] . amux ;
2011-02-17 22:11:05 -03:00
2011-05-09 16:53:51 -03:00
switch ( mux ) {
case TM6000_AMUX_SIF1 :
case TM6000_AMUX_SIF2 :
2011-02-17 22:11:05 -03:00
if ( dev - > dev_type = = TM6010 )
tm6010_set_volume_sif ( dev , vol ) ;
else
[media] tm6000: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:19 -02:00
printk ( KERN_INFO " ERROR: TM5600 and TM6000 don't has SIF audio inputs. Please check the %s configuration. \n " ,
dev - > name ) ;
2011-02-17 22:11:05 -03:00
break ;
2011-05-09 16:53:51 -03:00
case TM6000_AMUX_ADC1 :
case TM6000_AMUX_ADC2 :
2011-02-17 22:11:05 -03:00
tm6010_set_volume_adc ( dev , vol ) ;
break ;
default :
break ;
}
}
2010-05-10 13:22:51 -03:00
static LIST_HEAD ( tm6000_devlist ) ;
static DEFINE_MUTEX ( tm6000_devlist_mutex ) ;
/*
* tm6000_realease_resource ( )
*/
void tm6000_remove_from_devlist ( struct tm6000_core * dev )
{
mutex_lock ( & tm6000_devlist_mutex ) ;
list_del ( & dev - > devlist ) ;
mutex_unlock ( & tm6000_devlist_mutex ) ;
} ;
void tm6000_add_into_devlist ( struct tm6000_core * dev )
{
mutex_lock ( & tm6000_devlist_mutex ) ;
list_add_tail ( & dev - > devlist , & tm6000_devlist ) ;
mutex_unlock ( & tm6000_devlist_mutex ) ;
} ;
/*
* Extension interface
*/
static LIST_HEAD ( tm6000_extension_devlist ) ;
2010-06-03 17:16:28 -03:00
int tm6000_call_fillbuf ( struct tm6000_core * dev , enum tm6000_ops_type type ,
char * buf , int size )
{
struct tm6000_ops * ops = NULL ;
/* FIXME: tm6000_extension_devlist_lock should be a spinlock */
if ( ! list_empty ( & tm6000_extension_devlist ) ) {
list_for_each_entry ( ops , & tm6000_extension_devlist , next ) {
if ( ops - > fillbuf & & ops - > type = = type )
ops - > fillbuf ( dev , buf , size ) ;
}
}
return 0 ;
}
2010-05-10 13:22:51 -03:00
int tm6000_register_extension ( struct tm6000_ops * ops )
{
struct tm6000_core * dev = NULL ;
mutex_lock ( & tm6000_devlist_mutex ) ;
list_add_tail ( & ops - > next , & tm6000_extension_devlist ) ;
list_for_each_entry ( dev , & tm6000_devlist , devlist ) {
2010-06-05 15:10:36 -03:00
ops - > init ( dev ) ;
printk ( KERN_INFO " %s: Initialized (%s) extension \n " ,
dev - > name , ops - > name ) ;
2010-05-10 13:22:51 -03:00
}
mutex_unlock ( & tm6000_devlist_mutex ) ;
return 0 ;
}
EXPORT_SYMBOL ( tm6000_register_extension ) ;
void tm6000_unregister_extension ( struct tm6000_ops * ops )
{
struct tm6000_core * dev = NULL ;
mutex_lock ( & tm6000_devlist_mutex ) ;
2010-08-03 23:34:36 +02:00
list_for_each_entry ( dev , & tm6000_devlist , devlist )
ops - > fini ( dev ) ;
2010-05-10 13:22:51 -03:00
printk ( KERN_INFO " tm6000: Remove (%s) extension \n " , ops - > name ) ;
list_del ( & ops - > next ) ;
mutex_unlock ( & tm6000_devlist_mutex ) ;
}
EXPORT_SYMBOL ( tm6000_unregister_extension ) ;
void tm6000_init_extension ( struct tm6000_core * dev )
{
struct tm6000_ops * ops = NULL ;
2010-10-11 09:57:34 -03:00
mutex_lock ( & tm6000_devlist_mutex ) ;
2010-05-10 13:22:51 -03:00
if ( ! list_empty ( & tm6000_extension_devlist ) ) {
list_for_each_entry ( ops , & tm6000_extension_devlist , next ) {
if ( ops - > init )
ops - > init ( dev ) ;
}
}
2010-10-11 09:57:34 -03:00
mutex_unlock ( & tm6000_devlist_mutex ) ;
2010-05-10 13:22:51 -03:00
}
void tm6000_close_extension ( struct tm6000_core * dev )
{
struct tm6000_ops * ops = NULL ;
2010-10-11 09:57:34 -03:00
mutex_lock ( & tm6000_devlist_mutex ) ;
2010-05-10 13:22:51 -03:00
if ( ! list_empty ( & tm6000_extension_devlist ) ) {
list_for_each_entry ( ops , & tm6000_extension_devlist , next ) {
if ( ops - > fini )
ops - > fini ( dev ) ;
}
}
2010-12-28 21:49:07 -03:00
mutex_unlock ( & tm6000_devlist_mutex ) ;
2010-05-10 13:22:51 -03:00
}