2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2008-04-29 03:24:33 +04:00
/*
* cx18 functions for DVB support
*
2008-09-04 00:12:12 +04:00
* Copyright ( c ) 2008 Steven Toth < stoth @ linuxtv . org >
2010-05-24 01:53:35 +04:00
* Copyright ( C ) 2008 Andy Walls < awalls @ md . metrocast . net >
2008-04-29 03:24:33 +04:00
*/
# include "cx18-version.h"
# include "cx18-dvb.h"
2008-08-30 23:03:44 +04:00
# include "cx18-io.h"
2009-04-16 03:45:10 +04:00
# include "cx18-queue.h"
2008-04-29 03:24:33 +04:00
# include "cx18-streams.h"
# include "cx18-cards.h"
2009-06-10 03:47:21 +04:00
# include "cx18-gpio.h"
2008-04-29 03:24:33 +04:00
# include "s5h1409.h"
2008-05-01 14:23:23 +04:00
# include "mxl5005s.h"
2011-02-26 08:44:38 +03:00
# include "s5h1411.h"
# include "tda18271.h"
2009-06-10 03:47:21 +04:00
# include "zl10353.h"
2009-07-03 18:54:40 +04:00
# include <linux/firmware.h>
# include "mt352.h"
# include "mt352_priv.h"
2009-06-10 03:47:21 +04:00
# include "tuner-xc2028.h"
2008-04-29 03:24:33 +04:00
DVB_DEFINE_MOD_OPT_ADAPTER_NR ( adapter_nr ) ;
2012-07-27 19:45:21 +04:00
# define FWFILE "dvb-cx18-mpc718-mt352.fw"
2008-04-29 03:24:33 +04:00
# define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
2009-06-10 03:47:21 +04:00
# define CX18_CLOCK_ENABLE2 0xc71024
# define CX18_DMUX_CLK_MASK 0x0080
2008-04-29 03:24:33 +04:00
2009-07-03 18:54:40 +04:00
/*
* CX18_CARD_HVR_1600_ESMT
* CX18_CARD_HVR_1600_SAMSUNG
*/
2008-05-01 14:23:23 +04:00
static struct mxl5005s_config hauppauge_hvr1600_tuner = {
. i2c_address = 0xC6 > > 1 ,
. if_freq = IF_FREQ_5380000HZ ,
. xtal_freq = CRYSTAL_FREQ_16000000HZ ,
. agc_mode = MXL_SINGLE_AGC ,
. tracking_filter = MXL_TF_C_H ,
. rssi_enable = MXL_RSSI_ENABLE ,
. cap_select = MXL_CAP_SEL_ENABLE ,
. div_out = MXL_DIV_OUT_4 ,
. clock_out = MXL_CLOCK_OUT_DISABLE ,
. output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM ,
. top = MXL5005S_TOP_25P2 ,
. mod_mode = MXL_DIGITAL_MODE ,
. if_mode = MXL_ZERO_IF ,
2009-10-29 05:10:16 +03:00
. qam_gain = 0x02 ,
2008-05-01 14:23:23 +04:00
. AgcMasterByte = 0x00 ,
2008-04-29 03:24:33 +04:00
} ;
static struct s5h1409_config hauppauge_hvr1600_config = {
. demod_address = 0x32 > > 1 ,
. output_mode = S5H1409_SERIAL_OUTPUT ,
. gpio = S5H1409_GPIO_ON ,
. qam_if = 44000 ,
. inversion = S5H1409_INVERSION_OFF ,
. status_mode = S5H1409_DEMODLOCKING ,
2018-03-03 17:53:32 +03:00
. mpeg_timing = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK ,
2009-10-28 05:33:21 +03:00
. hvr1600_opt = S5H1409_HVR1600_OPTIMIZE
2009-06-10 03:47:21 +04:00
} ;
2008-04-29 03:24:33 +04:00
2011-02-26 08:44:38 +03:00
/*
* CX18_CARD_HVR_1600_S5H1411
*/
static struct s5h1411_config hcw_s5h1411_config = {
. output_mode = S5H1411_SERIAL_OUTPUT ,
. gpio = S5H1411_GPIO_OFF ,
. vsb_if = S5H1411_IF_44000 ,
. qam_if = S5H1411_IF_4000 ,
. inversion = S5H1411_INVERSION_ON ,
. status_mode = S5H1411_DEMODLOCKING ,
2018-03-03 17:53:32 +03:00
. mpeg_timing = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK ,
2011-02-26 08:44:38 +03:00
} ;
static struct tda18271_std_map hauppauge_tda18271_std_map = {
. atsc_6 = { . if_freq = 5380 , . agc_mode = 3 , . std = 3 ,
. if_lvl = 6 , . rfagc_top = 0x37 } ,
. qam_6 = { . if_freq = 4000 , . agc_mode = 3 , . std = 0 ,
. if_lvl = 6 , . rfagc_top = 0x37 } ,
} ;
static struct tda18271_config hauppauge_tda18271_config = {
. std_map = & hauppauge_tda18271_std_map ,
. gate = TDA18271_GATE_DIGITAL ,
. output_opt = TDA18271_OUTPUT_LT_OFF ,
} ;
2009-07-03 18:54:40 +04:00
/*
* CX18_CARD_LEADTEK_DVR3100H
*/
2009-06-10 03:47:21 +04:00
/* Information/confirmation of proper config values provided by Terry Wu */
static struct zl10353_config leadtek_dvr3100h_demod = {
. demod_address = 0x1e > > 1 , /* Datasheet suggested straps */
. if2 = 45600 , /* 4.560 MHz IF from the XC3028 */
. parallel_ts = 1 , /* Not a serial TS */
. no_tuner = 1 , /* XC3028 is not behind the gate */
. disable_i2c_gate_ctrl = 1 , /* Disable the I2C gate */
2008-04-29 03:24:33 +04:00
} ;
2009-07-03 18:54:40 +04:00
/*
* CX18_CARD_YUAN_MPC718
*/
/*
* Due to
*
2019-02-18 22:28:59 +03:00
* 1. an absence of information on how to program the MT352
* 2. the Linux mt352 module pushing MT352 initialization off onto us here
2009-07-03 18:54:40 +04:00
*
* We have to use an init sequence that * you * must extract from the Windows
* driver ( yuanrap . sys ) and which we load as a firmware .
*
* If someone can provide me with a Zarlink MT352 ( Intel CE6352 ? ) Design Manual
* with chip programming details , then I can remove this annoyance .
*/
static int yuan_mpc718_mt352_reqfw ( struct cx18_stream * stream ,
const struct firmware * * fw )
{
struct cx18 * cx = stream - > cx ;
2012-07-27 19:45:21 +04:00
const char * fn = FWFILE ;
2009-07-03 18:54:40 +04:00
int ret ;
ret = request_firmware ( fw , fn , & cx - > pci_dev - > dev ) ;
if ( ret )
CX18_ERR ( " Unable to open firmware file %s \n " , fn ) ;
else {
size_t sz = ( * fw ) - > size ;
if ( sz < 2 | | sz > 64 | | ( sz % 2 ) ! = 0 ) {
CX18_ERR ( " Firmware %s has a bad size: %lu bytes \n " ,
fn , ( unsigned long ) sz ) ;
ret = - EILSEQ ;
release_firmware ( * fw ) ;
* fw = NULL ;
}
}
if ( ret ) {
2017-04-26 00:32:23 +03:00
CX18_ERR ( " The MPC718 board variant with the MT352 DVB-T demodulator will not work without it \n " ) ;
2018-05-09 00:10:05 +03:00
CX18_ERR ( " Run 'linux/scripts/get_dvb_firmware mpc718' if you need the firmware \n " ) ;
2009-07-03 18:54:40 +04:00
}
return ret ;
}
static int yuan_mpc718_mt352_init ( struct dvb_frontend * fe )
{
struct cx18_dvb * dvb = container_of ( fe - > dvb ,
struct cx18_dvb , dvb_adapter ) ;
2010-12-12 02:38:20 +03:00
struct cx18_stream * stream = dvb - > stream ;
2009-07-03 18:54:40 +04:00
const struct firmware * fw = NULL ;
int ret ;
int i ;
u8 buf [ 3 ] ;
ret = yuan_mpc718_mt352_reqfw ( stream , & fw ) ;
if ( ret )
return ret ;
/* Loop through all the register-value pairs in the firmware file */
for ( i = 0 ; i < fw - > size ; i + = 2 ) {
buf [ 0 ] = fw - > data [ i ] ;
/* Intercept a few registers we want to set ourselves */
switch ( buf [ 0 ] ) {
case TRL_NOMINAL_RATE_0 :
/* Set our custom OFDM bandwidth in the case below */
break ;
case TRL_NOMINAL_RATE_1 :
/* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */
/* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */
/* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */
buf [ 1 ] = 0x72 ;
buf [ 2 ] = 0x49 ;
mt352_write ( fe , buf , 3 ) ;
break ;
case INPUT_FREQ_0 :
/* Set our custom IF in the case below */
break ;
case INPUT_FREQ_1 :
/* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */
buf [ 1 ] = 0x31 ;
buf [ 2 ] = 0xc0 ;
mt352_write ( fe , buf , 3 ) ;
break ;
default :
/* Pass through the register-value pair from the fw */
buf [ 1 ] = fw - > data [ i + 1 ] ;
mt352_write ( fe , buf , 2 ) ;
break ;
}
}
buf [ 0 ] = ( u8 ) TUNER_GO ;
buf [ 1 ] = 0x01 ; /* Go */
mt352_write ( fe , buf , 2 ) ;
release_firmware ( fw ) ;
return 0 ;
}
static struct mt352_config yuan_mpc718_mt352_demod = {
. demod_address = 0x1e > > 1 ,
. adc_clock = 20480 , /* 20.480 MHz */
. if2 = 4560 , /* 4.560 MHz */
. no_tuner = 1 , /* XC3028 is not behind the gate */
. demod_init = yuan_mpc718_mt352_init ,
} ;
static struct zl10353_config yuan_mpc718_zl10353_demod = {
. demod_address = 0x1e > > 1 , /* Datasheet suggested straps */
. if2 = 45600 , /* 4.560 MHz IF from the XC3028 */
. parallel_ts = 1 , /* Not a serial TS */
. no_tuner = 1 , /* XC3028 is not behind the gate */
. disable_i2c_gate_ctrl = 1 , /* Disable the I2C gate */
} ;
2010-10-29 01:12:02 +04:00
static struct zl10353_config gotview_dvd3_zl10353_demod = {
. demod_address = 0x1e > > 1 , /* Datasheet suggested straps */
. if2 = 45600 , /* 4.560 MHz IF from the XC3028 */
. parallel_ts = 1 , /* Not a serial TS */
. no_tuner = 1 , /* XC3028 is not behind the gate */
. disable_i2c_gate_ctrl = 1 , /* Disable the I2C gate */
} ;
2008-04-29 03:24:33 +04:00
static int dvb_register ( struct cx18_stream * stream ) ;
/* Kernel DVB framework calls this when the feed needs to start.
* The CX18 framework should enable the transport DMA handling
* and queue processing .
*/
static int cx18_dvb_start_feed ( struct dvb_demux_feed * feed )
{
struct dvb_demux * demux = feed - > demux ;
struct cx18_stream * stream = ( struct cx18_stream * ) demux - > priv ;
2010-01-10 11:56:46 +03:00
struct cx18 * cx ;
2008-06-22 07:04:21 +04:00
int ret ;
2008-04-29 03:24:33 +04:00
u32 v ;
2010-01-10 11:56:46 +03:00
if ( ! stream )
return - EINVAL ;
cx = stream - > cx ;
2008-04-29 03:24:33 +04:00
CX18_DEBUG_INFO ( " Start feed: pid = 0x%x index = %d \n " ,
feed - > pid , feed - > index ) ;
2008-06-22 07:04:21 +04:00
mutex_lock ( & cx - > serialize_lock ) ;
ret = cx18_init_on_first_open ( cx ) ;
mutex_unlock ( & cx - > serialize_lock ) ;
if ( ret ) {
CX18_ERR ( " Failed to initialize firmware starting DVB feed \n " ) ;
return ret ;
}
ret = - EINVAL ;
2008-04-29 03:24:33 +04:00
switch ( cx - > card - > type ) {
case CX18_CARD_HVR_1600_ESMT :
case CX18_CARD_HVR_1600_SAMSUNG :
2011-02-26 08:44:38 +03:00
case CX18_CARD_HVR_1600_S5H1411 :
2008-08-30 23:03:44 +04:00
v = cx18_read_reg ( cx , CX18_REG_DMUX_NUM_PORT_0_CONTROL ) ;
2008-04-29 03:24:33 +04:00
v | = 0x00400000 ; /* Serial Mode */
v | = 0x00002000 ; /* Data Length - Byte */
v | = 0x00010000 ; /* Error - Polarity */
v | = 0x00020000 ; /* Error - Passthru */
v | = 0x000c0000 ; /* Error - Ignore */
2008-08-30 23:03:44 +04:00
cx18_write_reg ( cx , v , CX18_REG_DMUX_NUM_PORT_0_CONTROL ) ;
2008-04-29 03:24:33 +04:00
break ;
2009-06-10 03:47:21 +04:00
case CX18_CARD_LEADTEK_DVR3100H :
2009-07-03 18:54:40 +04:00
case CX18_CARD_YUAN_MPC718 :
2010-10-29 01:12:02 +04:00
case CX18_CARD_GOTVIEW_PCI_DVD3 :
2008-04-29 03:24:33 +04:00
default :
/* Assumption - Parallel transport - Signalling
* undefined or default .
*/
break ;
}
if ( ! demux - > dmx . frontend )
return - EINVAL ;
2010-12-12 02:38:20 +03:00
mutex_lock ( & stream - > dvb - > feedlock ) ;
if ( stream - > dvb - > feeding + + = = 0 ) {
2008-11-06 03:19:15 +03:00
CX18_DEBUG_INFO ( " Starting Transport DMA \n " ) ;
2010-01-30 22:20:27 +03:00
mutex_lock ( & cx - > serialize_lock ) ;
2008-11-06 03:19:15 +03:00
set_bit ( CX18_F_S_STREAMING , & stream - > s_flags ) ;
ret = cx18_start_v4l2_encode_stream ( stream ) ;
if ( ret < 0 ) {
CX18_DEBUG_INFO ( " Failed to start Transport DMA \n " ) ;
2010-12-12 02:38:20 +03:00
stream - > dvb - > feeding - - ;
if ( stream - > dvb - > feeding = = 0 )
2008-11-06 03:19:15 +03:00
clear_bit ( CX18_F_S_STREAMING , & stream - > s_flags ) ;
}
2010-01-30 22:20:27 +03:00
mutex_unlock ( & cx - > serialize_lock ) ;
2008-11-06 03:19:15 +03:00
} else
ret = 0 ;
2010-12-12 02:38:20 +03:00
mutex_unlock ( & stream - > dvb - > feedlock ) ;
2008-04-29 03:24:33 +04:00
return ret ;
}
/* Kernel DVB framework calls this when the feed needs to stop. */
static int cx18_dvb_stop_feed ( struct dvb_demux_feed * feed )
{
struct dvb_demux * demux = feed - > demux ;
struct cx18_stream * stream = ( struct cx18_stream * ) demux - > priv ;
2010-01-10 11:56:46 +03:00
struct cx18 * cx ;
2008-04-29 03:24:33 +04:00
int ret = - EINVAL ;
if ( stream ) {
2010-01-10 11:56:46 +03:00
cx = stream - > cx ;
CX18_DEBUG_INFO ( " Stop feed: pid = 0x%x index = %d \n " ,
feed - > pid , feed - > index ) ;
2010-12-12 02:38:20 +03:00
mutex_lock ( & stream - > dvb - > feedlock ) ;
if ( - - stream - > dvb - > feeding = = 0 ) {
2008-04-29 03:24:33 +04:00
CX18_DEBUG_INFO ( " Stopping Transport DMA \n " ) ;
2010-01-30 22:20:27 +03:00
mutex_lock ( & cx - > serialize_lock ) ;
2008-04-29 03:24:33 +04:00
ret = cx18_stop_v4l2_encode_stream ( stream , 0 ) ;
2010-01-30 22:20:27 +03:00
mutex_unlock ( & cx - > serialize_lock ) ;
2008-04-29 03:24:33 +04:00
} else
ret = 0 ;
2010-12-12 02:38:20 +03:00
mutex_unlock ( & stream - > dvb - > feedlock ) ;
2008-04-29 03:24:33 +04:00
}
return ret ;
}
int cx18_dvb_register ( struct cx18_stream * stream )
{
struct cx18 * cx = stream - > cx ;
2010-12-12 02:38:20 +03:00
struct cx18_dvb * dvb = stream - > dvb ;
2008-04-29 03:24:33 +04:00
struct dvb_adapter * dvb_adapter ;
struct dvb_demux * dvbdemux ;
struct dmx_demux * dmx ;
int ret ;
if ( ! dvb )
return - EINVAL ;
2010-12-12 02:38:20 +03:00
dvb - > enabled = 0 ;
dvb - > stream = stream ;
2008-04-29 03:24:33 +04:00
ret = dvb_register_adapter ( & dvb - > dvb_adapter ,
CX18_DRIVER_NAME ,
2009-01-11 03:54:39 +03:00
THIS_MODULE , & cx - > pci_dev - > dev , adapter_nr ) ;
2008-04-29 03:24:33 +04:00
if ( ret < 0 )
goto err_out ;
dvb_adapter = & dvb - > dvb_adapter ;
dvbdemux = & dvb - > demux ;
dvbdemux - > priv = ( void * ) stream ;
dvbdemux - > filternum = 256 ;
dvbdemux - > feednum = 256 ;
dvbdemux - > start_feed = cx18_dvb_start_feed ;
dvbdemux - > stop_feed = cx18_dvb_stop_feed ;
dvbdemux - > dmx . capabilities = ( DMX_TS_FILTERING |
DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING ) ;
ret = dvb_dmx_init ( dvbdemux ) ;
if ( ret < 0 )
goto err_dvb_unregister_adapter ;
dmx = & dvbdemux - > dmx ;
dvb - > hw_frontend . source = DMX_FRONTEND_0 ;
dvb - > mem_frontend . source = DMX_MEMORY_FE ;
dvb - > dmxdev . filternum = 256 ;
dvb - > dmxdev . demux = dmx ;
ret = dvb_dmxdev_init ( & dvb - > dmxdev , dvb_adapter ) ;
if ( ret < 0 )
goto err_dvb_dmx_release ;
ret = dmx - > add_frontend ( dmx , & dvb - > hw_frontend ) ;
if ( ret < 0 )
goto err_dvb_dmxdev_release ;
ret = dmx - > add_frontend ( dmx , & dvb - > mem_frontend ) ;
if ( ret < 0 )
goto err_remove_hw_frontend ;
ret = dmx - > connect_frontend ( dmx , & dvb - > hw_frontend ) ;
if ( ret < 0 )
goto err_remove_mem_frontend ;
ret = dvb_register ( stream ) ;
if ( ret < 0 )
goto err_disconnect_frontend ;
dvb_net_init ( dvb_adapter , & dvb - > dvbnet , dmx ) ;
CX18_INFO ( " DVB Frontend registered \n " ) ;
2009-11-10 05:55:30 +03:00
CX18_INFO ( " Registered DVB adapter%d for %s (%d x %d.%02d kB) \n " ,
2010-12-12 02:38:20 +03:00
stream - > dvb - > dvb_adapter . num , stream - > name ,
2009-11-10 05:55:30 +03:00
stream - > buffers , stream - > buf_size / 1024 ,
( stream - > buf_size * 100 / 1024 ) % 100 ) ;
2008-12-08 05:30:17 +03:00
2008-04-29 03:24:33 +04:00
mutex_init ( & dvb - > feedlock ) ;
dvb - > enabled = 1 ;
return ret ;
err_disconnect_frontend :
dmx - > disconnect_frontend ( dmx ) ;
err_remove_mem_frontend :
dmx - > remove_frontend ( dmx , & dvb - > mem_frontend ) ;
err_remove_hw_frontend :
dmx - > remove_frontend ( dmx , & dvb - > hw_frontend ) ;
err_dvb_dmxdev_release :
dvb_dmxdev_release ( & dvb - > dmxdev ) ;
err_dvb_dmx_release :
dvb_dmx_release ( dvbdemux ) ;
err_dvb_unregister_adapter :
dvb_unregister_adapter ( dvb_adapter ) ;
err_out :
return ret ;
}
void cx18_dvb_unregister ( struct cx18_stream * stream )
{
struct cx18 * cx = stream - > cx ;
2010-12-12 02:38:20 +03:00
struct cx18_dvb * dvb = stream - > dvb ;
2008-04-29 03:24:33 +04:00
struct dvb_adapter * dvb_adapter ;
struct dvb_demux * dvbdemux ;
struct dmx_demux * dmx ;
CX18_INFO ( " unregister DVB \n " ) ;
2010-12-12 02:38:20 +03:00
if ( dvb = = NULL | | ! dvb - > enabled )
return ;
2008-04-29 03:24:33 +04:00
dvb_adapter = & dvb - > dvb_adapter ;
dvbdemux = & dvb - > demux ;
dmx = & dvbdemux - > dmx ;
dmx - > close ( dmx ) ;
dvb_net_release ( & dvb - > dvbnet ) ;
dmx - > remove_frontend ( dmx , & dvb - > mem_frontend ) ;
dmx - > remove_frontend ( dmx , & dvb - > hw_frontend ) ;
dvb_dmxdev_release ( & dvb - > dmxdev ) ;
dvb_dmx_release ( dvbdemux ) ;
dvb_unregister_frontend ( dvb - > fe ) ;
dvb_frontend_detach ( dvb - > fe ) ;
dvb_unregister_adapter ( dvb_adapter ) ;
}
2019-03-01 18:01:58 +03:00
/* All the DVB attach calls go here, this function gets modified
2009-06-10 03:47:21 +04:00
* for each new card . cx18_dvb_start_feed ( ) will also need changes .
2008-04-29 03:24:33 +04:00
*/
static int dvb_register ( struct cx18_stream * stream )
{
2010-12-12 02:38:20 +03:00
struct cx18_dvb * dvb = stream - > dvb ;
2008-04-29 03:24:33 +04:00
struct cx18 * cx = stream - > cx ;
int ret = 0 ;
switch ( cx - > card - > type ) {
case CX18_CARD_HVR_1600_ESMT :
case CX18_CARD_HVR_1600_SAMSUNG :
dvb - > fe = dvb_attach ( s5h1409_attach ,
& hauppauge_hvr1600_config ,
& cx - > i2c_adap [ 0 ] ) ;
if ( dvb - > fe ! = NULL ) {
2008-05-01 14:23:23 +04:00
dvb_attach ( mxl5005s_attach , dvb - > fe ,
& cx - > i2c_adap [ 0 ] ,
& hauppauge_hvr1600_tuner ) ;
2008-04-29 03:24:33 +04:00
ret = 0 ;
}
break ;
2011-02-26 08:44:38 +03:00
case CX18_CARD_HVR_1600_S5H1411 :
dvb - > fe = dvb_attach ( s5h1411_attach ,
& hcw_s5h1411_config ,
& cx - > i2c_adap [ 0 ] ) ;
if ( dvb - > fe ! = NULL )
dvb_attach ( tda18271_attach , dvb - > fe ,
0x60 , & cx - > i2c_adap [ 0 ] ,
& hauppauge_tda18271_config ) ;
break ;
2009-06-10 03:47:21 +04:00
case CX18_CARD_LEADTEK_DVR3100H :
dvb - > fe = dvb_attach ( zl10353_attach ,
& leadtek_dvr3100h_demod ,
& cx - > i2c_adap [ 1 ] ) ;
if ( dvb - > fe ! = NULL ) {
struct dvb_frontend * fe ;
struct xc2028_config cfg = {
. i2c_adap = & cx - > i2c_adap [ 1 ] ,
. i2c_addr = 0xc2 > > 1 ,
. ctrl = NULL ,
} ;
static struct xc2028_ctrl ctrl = {
. fname = XC2028_DEFAULT_FIRMWARE ,
2009-07-03 18:54:40 +04:00
. max_len = 64 ,
. demod = XC3028_FE_ZARLINK456 ,
. type = XC2028_AUTO ,
} ;
fe = dvb_attach ( xc2028_attach , dvb - > fe , & cfg ) ;
if ( fe ! = NULL & & fe - > ops . tuner_ops . set_config ! = NULL )
fe - > ops . tuner_ops . set_config ( fe , & ctrl ) ;
}
break ;
case CX18_CARD_YUAN_MPC718 :
/*
* TODO
* Apparently , these cards also could instead have a
* DiBcom demod supported by one of the db7000 drivers
*/
dvb - > fe = dvb_attach ( mt352_attach ,
& yuan_mpc718_mt352_demod ,
& cx - > i2c_adap [ 1 ] ) ;
if ( dvb - > fe = = NULL )
dvb - > fe = dvb_attach ( zl10353_attach ,
& yuan_mpc718_zl10353_demod ,
& cx - > i2c_adap [ 1 ] ) ;
if ( dvb - > fe ! = NULL ) {
struct dvb_frontend * fe ;
struct xc2028_config cfg = {
. i2c_adap = & cx - > i2c_adap [ 1 ] ,
. i2c_addr = 0xc2 > > 1 ,
. ctrl = NULL ,
} ;
static struct xc2028_ctrl ctrl = {
. fname = XC2028_DEFAULT_FIRMWARE ,
2010-10-29 01:12:02 +04:00
. max_len = 64 ,
. demod = XC3028_FE_ZARLINK456 ,
. type = XC2028_AUTO ,
} ;
fe = dvb_attach ( xc2028_attach , dvb - > fe , & cfg ) ;
if ( fe ! = NULL & & fe - > ops . tuner_ops . set_config ! = NULL )
fe - > ops . tuner_ops . set_config ( fe , & ctrl ) ;
}
break ;
case CX18_CARD_GOTVIEW_PCI_DVD3 :
dvb - > fe = dvb_attach ( zl10353_attach ,
& gotview_dvd3_zl10353_demod ,
& cx - > i2c_adap [ 1 ] ) ;
if ( dvb - > fe ! = NULL ) {
struct dvb_frontend * fe ;
struct xc2028_config cfg = {
. i2c_adap = & cx - > i2c_adap [ 1 ] ,
. i2c_addr = 0xc2 > > 1 ,
. ctrl = NULL ,
} ;
static struct xc2028_ctrl ctrl = {
. fname = XC2028_DEFAULT_FIRMWARE ,
2009-06-10 03:47:21 +04:00
. max_len = 64 ,
. demod = XC3028_FE_ZARLINK456 ,
. type = XC2028_AUTO ,
} ;
fe = dvb_attach ( xc2028_attach , dvb - > fe , & cfg ) ;
if ( fe ! = NULL & & fe - > ops . tuner_ops . set_config ! = NULL )
fe - > ops . tuner_ops . set_config ( fe , & ctrl ) ;
}
break ;
2008-04-29 03:24:33 +04:00
default :
/* No Digital Tv Support */
break ;
}
if ( dvb - > fe = = NULL ) {
CX18_ERR ( " frontend initialization failed \n " ) ;
return - 1 ;
}
2009-06-10 03:47:21 +04:00
dvb - > fe - > callback = cx18_reset_tuner_gpio ;
2008-04-29 03:24:33 +04:00
ret = dvb_register_frontend ( & dvb - > dvb_adapter , dvb - > fe ) ;
if ( ret < 0 ) {
if ( dvb - > fe - > ops . release )
dvb - > fe - > ops . release ( dvb - > fe ) ;
return ret ;
}
2009-06-10 03:47:21 +04:00
/*
* The firmware seems to enable the TS DMUX clock
* under various circumstances . However , since we know we
* might use it , let ' s just turn it on ourselves here .
*/
cx18_write_reg_expect ( cx ,
( CX18_DMUX_CLK_MASK < < 16 ) | CX18_DMUX_CLK_MASK ,
CX18_CLOCK_ENABLE2 ,
CX18_DMUX_CLK_MASK ,
( CX18_DMUX_CLK_MASK < < 16 ) | CX18_DMUX_CLK_MASK ) ;
2008-04-29 03:24:33 +04:00
return ret ;
}
2012-07-27 19:45:21 +04:00
MODULE_FIRMWARE ( FWFILE ) ;