2009-12-02 21:57:10 -03:00
/*
Mantis PCI bridge driver
2009-12-15 09:13:49 -03:00
Copyright ( C ) Manu Abraham ( abraham . manu @ gmail . com )
2009-12-02 21:57:10 -03:00
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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2009-12-04 05:41:11 -03:00
# include <linux/kernel.h>
2009-12-02 21:57:10 -03:00
# include <linux/bitops.h>
2009-12-04 05:41:11 -03:00
# include <linux/signal.h>
# include <linux/sched.h>
# include <linux/interrupt.h>
# include <linux/pci.h>
# include <linux/i2c.h>
2009-12-02 21:57:10 -03:00
# include "dmxdev.h"
# include "dvbdev.h"
# include "dvb_demux.h"
# include "dvb_frontend.h"
2009-12-04 05:41:11 -03:00
# include "dvb_net.h"
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
# include "mantis_common.h"
# include "mantis_dma.h"
# include "mantis_ca.h"
# include "mantis_ioc.h"
# include "mantis_dvb.h"
2009-12-04 05:33:56 -03:00
2009-12-04 05:41:11 -03:00
DVB_DEFINE_MOD_OPT_ADAPTER_NR ( adapter_nr ) ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
int mantis_frontend_power ( struct mantis_pci * mantis , enum mantis_power power )
2009-12-02 21:57:10 -03:00
{
2009-12-04 05:41:11 -03:00
struct mantis_hwconfig * config = mantis - > hwconfig ;
switch ( power ) {
case POWER_ON :
dprintk ( MANTIS_DEBUG , 1 , " Power ON " ) ;
2010-11-14 14:56:00 -03:00
mantis_gpio_set_bits ( mantis , config - > power , POWER_ON ) ;
2009-12-04 05:41:11 -03:00
msleep ( 100 ) ;
2010-11-14 14:56:00 -03:00
mantis_gpio_set_bits ( mantis , config - > power , POWER_ON ) ;
2009-12-04 05:41:11 -03:00
msleep ( 100 ) ;
break ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
case POWER_OFF :
dprintk ( MANTIS_DEBUG , 1 , " Power OFF " ) ;
2010-11-14 14:56:00 -03:00
mantis_gpio_set_bits ( mantis , config - > power , POWER_OFF ) ;
2009-12-04 05:41:11 -03:00
msleep ( 100 ) ;
break ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
default :
dprintk ( MANTIS_DEBUG , 1 , " Unknown state <%02x> " , power ) ;
return - 1 ;
}
2009-12-02 21:57:10 -03:00
return 0 ;
}
2009-12-04 05:41:11 -03:00
EXPORT_SYMBOL_GPL ( mantis_frontend_power ) ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
void mantis_frontend_soft_reset ( struct mantis_pci * mantis )
2009-12-02 21:57:10 -03:00
{
2009-12-04 05:41:11 -03:00
struct mantis_hwconfig * config = mantis - > hwconfig ;
dprintk ( MANTIS_DEBUG , 1 , " Frontend RESET " ) ;
2010-11-14 14:56:00 -03:00
mantis_gpio_set_bits ( mantis , config - > reset , 0 ) ;
2009-12-04 05:41:11 -03:00
msleep ( 100 ) ;
2010-11-14 14:56:00 -03:00
mantis_gpio_set_bits ( mantis , config - > reset , 0 ) ;
2009-12-04 05:41:11 -03:00
msleep ( 100 ) ;
2010-11-14 14:56:00 -03:00
mantis_gpio_set_bits ( mantis , config - > reset , 1 ) ;
2009-12-04 05:41:11 -03:00
msleep ( 100 ) ;
2010-11-14 14:56:00 -03:00
mantis_gpio_set_bits ( mantis , config - > reset , 1 ) ;
2009-12-04 05:41:11 -03:00
msleep ( 100 ) ;
return ;
}
EXPORT_SYMBOL_GPL ( mantis_frontend_soft_reset ) ;
static int mantis_frontend_shutdown ( struct mantis_pci * mantis )
{
int err ;
mantis_frontend_soft_reset ( mantis ) ;
err = mantis_frontend_power ( mantis , POWER_OFF ) ;
if ( err ! = 0 ) {
dprintk ( MANTIS_ERROR , 1 , " Frontend POWER OFF failed! <%d> " , err ) ;
return 1 ;
}
2009-12-02 21:57:10 -03:00
return 0 ;
}
static int mantis_dvb_start_feed ( struct dvb_demux_feed * dvbdmxfeed )
{
struct dvb_demux * dvbdmx = dvbdmxfeed - > demux ;
struct mantis_pci * mantis = dvbdmx - > priv ;
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " Mantis DVB Start feed " ) ;
2009-12-02 21:57:10 -03:00
if ( ! dvbdmx - > dmx . frontend ) {
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " no frontend ? " ) ;
2009-12-02 21:57:10 -03:00
return - EINVAL ;
}
2009-12-04 05:41:11 -03:00
2009-12-02 21:57:10 -03:00
mantis - > feeds + + ;
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " mantis start feed, feeds=%d " , mantis - > feeds ) ;
2009-12-02 21:57:10 -03:00
if ( mantis - > feeds = = 1 ) {
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " mantis start feed & dma " ) ;
2009-12-02 21:57:10 -03:00
mantis_dma_start ( mantis ) ;
2010-11-14 14:09:04 -03:00
tasklet_enable ( & mantis - > tasklet ) ;
2009-12-02 21:57:10 -03:00
}
return mantis - > feeds ;
}
static int mantis_dvb_stop_feed ( struct dvb_demux_feed * dvbdmxfeed )
{
struct dvb_demux * dvbdmx = dvbdmxfeed - > demux ;
struct mantis_pci * mantis = dvbdmx - > priv ;
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " Mantis DVB Stop feed " ) ;
2009-12-02 21:57:10 -03:00
if ( ! dvbdmx - > dmx . frontend ) {
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " no frontend ? " ) ;
2009-12-02 21:57:10 -03:00
return - EINVAL ;
}
2009-12-04 05:41:11 -03:00
2009-12-02 21:57:10 -03:00
mantis - > feeds - - ;
if ( mantis - > feeds = = 0 ) {
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " mantis stop feed and dma " ) ;
2010-11-14 14:09:04 -03:00
tasklet_disable ( & mantis - > tasklet ) ;
2009-12-02 21:57:10 -03:00
mantis_dma_stop ( mantis ) ;
}
2009-12-04 05:41:11 -03:00
2009-12-02 21:57:10 -03:00
return 0 ;
}
int __devinit mantis_dvb_init ( struct mantis_pci * mantis )
{
2009-12-04 05:41:11 -03:00
struct mantis_hwconfig * config = mantis - > hwconfig ;
int result = - 1 ;
dprintk ( MANTIS_DEBUG , 1 , " dvb_register_adapter " ) ;
result = dvb_register_adapter ( & mantis - > dvb_adapter ,
" Mantis DVB adapter " ,
THIS_MODULE ,
& mantis - > pdev - > dev ,
adapter_nr ) ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
if ( result < 0 ) {
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_ERROR , 1 , " Error registering adapter " ) ;
2009-12-02 21:57:10 -03:00
return - ENODEV ;
}
2009-12-04 05:41:11 -03:00
mantis - > dvb_adapter . priv = mantis ;
mantis - > demux . dmx . capabilities = DMX_TS_FILTERING |
2009-12-02 21:57:10 -03:00
DMX_SECTION_FILTERING |
DMX_MEMORY_BASED_FILTERING ;
2009-12-04 05:41:11 -03:00
mantis - > demux . priv = mantis ;
mantis - > demux . filternum = 256 ;
mantis - > demux . feednum = 256 ;
mantis - > demux . start_feed = mantis_dvb_start_feed ;
mantis - > demux . stop_feed = mantis_dvb_stop_feed ;
mantis - > demux . write_to_decoder = NULL ;
dprintk ( MANTIS_DEBUG , 1 , " dvb_dmx_init " ) ;
result = dvb_dmx_init ( & mantis - > demux ) ;
if ( result < 0 ) {
dprintk ( MANTIS_ERROR , 1 , " dvb_dmx_init failed, ERROR=%d " , result ) ;
2009-12-02 21:57:10 -03:00
goto err0 ;
}
2009-12-04 05:41:11 -03:00
mantis - > dmxdev . filternum = 256 ;
mantis - > dmxdev . demux = & mantis - > demux . dmx ;
mantis - > dmxdev . capabilities = 0 ;
dprintk ( MANTIS_DEBUG , 1 , " dvb_dmxdev_init " ) ;
result = dvb_dmxdev_init ( & mantis - > dmxdev , & mantis - > dvb_adapter ) ;
if ( result < 0 ) {
dprintk ( MANTIS_ERROR , 1 , " dvb_dmxdev_init failed, ERROR=%d " , result ) ;
2009-12-02 21:57:10 -03:00
goto err1 ;
}
2009-12-04 05:41:11 -03:00
mantis - > fe_hw . source = DMX_FRONTEND_0 ;
result = mantis - > demux . dmx . add_frontend ( & mantis - > demux . dmx , & mantis - > fe_hw ) ;
if ( result < 0 ) {
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_ERROR , 1 , " dvb_dmx_init failed, ERROR=%d " , result ) ;
2009-12-02 21:57:10 -03:00
goto err2 ;
}
2009-12-04 05:41:11 -03:00
mantis - > fe_mem . source = DMX_MEMORY_FE ;
2009-12-15 08:47:21 -03:00
result = mantis - > demux . dmx . add_frontend ( & mantis - > demux . dmx , & mantis - > fe_mem ) ;
2009-12-04 05:41:11 -03:00
if ( result < 0 ) {
2009-12-15 08:47:21 -03:00
dprintk ( MANTIS_ERROR , 1 , " dvb_dmx_init failed, ERROR=%d " , result ) ;
2009-12-02 21:57:10 -03:00
goto err3 ;
}
2009-12-04 05:41:11 -03:00
result = mantis - > demux . dmx . connect_frontend ( & mantis - > demux . dmx , & mantis - > fe_hw ) ;
if ( result < 0 ) {
dprintk ( MANTIS_ERROR , 1 , " dvb_dmx_init failed, ERROR=%d " , result ) ;
2009-12-02 21:57:10 -03:00
goto err4 ;
}
2009-12-04 05:41:11 -03:00
2009-12-02 21:57:10 -03:00
dvb_net_init ( & mantis - > dvb_adapter , & mantis - > dvbnet , & mantis - > demux . dmx ) ;
tasklet_init ( & mantis - > tasklet , mantis_dma_xfer , ( unsigned long ) mantis ) ;
2010-11-14 14:09:04 -03:00
tasklet_disable ( & mantis - > tasklet ) ;
2009-12-04 05:41:11 -03:00
if ( mantis - > hwconfig ) {
result = config - > frontend_init ( mantis , mantis - > fe ) ;
if ( result < 0 ) {
dprintk ( MANTIS_ERROR , 1 , " !!! NO Frontends found !!! " ) ;
goto err5 ;
} else {
if ( mantis - > fe = = NULL ) {
dprintk ( MANTIS_ERROR , 1 , " FE <NULL> " ) ;
goto err5 ;
}
if ( dvb_register_frontend ( & mantis - > dvb_adapter , mantis - > fe ) ) {
dprintk ( MANTIS_ERROR , 1 , " ERROR: Frontend registration failed " ) ;
if ( mantis - > fe - > ops . release )
mantis - > fe - > ops . release ( mantis - > fe ) ;
mantis - > fe = NULL ;
goto err5 ;
}
}
}
2009-12-04 05:07:41 -03:00
2009-12-02 21:57:10 -03:00
return 0 ;
2009-12-04 05:41:11 -03:00
/* Error conditions .. */
err5 :
tasklet_kill ( & mantis - > tasklet ) ;
dvb_net_release ( & mantis - > dvbnet ) ;
2009-12-04 09:01:35 -03:00
dvb_unregister_frontend ( mantis - > fe ) ;
dvb_frontend_detach ( mantis - > fe ) ;
2009-12-02 21:57:10 -03:00
err4 :
mantis - > demux . dmx . remove_frontend ( & mantis - > demux . dmx , & mantis - > fe_mem ) ;
2009-12-04 05:56:35 -03:00
2009-12-02 21:57:10 -03:00
err3 :
mantis - > demux . dmx . remove_frontend ( & mantis - > demux . dmx , & mantis - > fe_hw ) ;
2009-12-04 05:56:35 -03:00
2009-12-02 21:57:10 -03:00
err2 :
dvb_dmxdev_release ( & mantis - > dmxdev ) ;
2009-12-04 05:56:35 -03:00
2009-12-02 21:57:10 -03:00
err1 :
dvb_dmx_release ( & mantis - > demux ) ;
2009-12-04 05:56:35 -03:00
2009-12-02 21:57:10 -03:00
err0 :
dvb_unregister_adapter ( & mantis - > dvb_adapter ) ;
return result ;
}
2009-12-04 05:41:11 -03:00
EXPORT_SYMBOL_GPL ( mantis_dvb_init ) ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
int __devexit mantis_dvb_exit ( struct mantis_pci * mantis )
2009-12-02 21:57:10 -03:00
{
2009-12-04 05:41:11 -03:00
int err ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:56:35 -03:00
if ( mantis - > fe ) {
2009-12-15 08:47:21 -03:00
/* mantis_ca_exit(mantis); */
2009-12-04 05:56:35 -03:00
err = mantis_frontend_shutdown ( mantis ) ;
if ( err ! = 0 )
dprintk ( MANTIS_ERROR , 1 , " Frontend exit while POWER ON! <%d> " , err ) ;
dvb_unregister_frontend ( mantis - > fe ) ;
2009-12-09 19:59:26 -03:00
dvb_frontend_detach ( mantis - > fe ) ;
2009-12-04 05:56:35 -03:00
}
2009-12-02 21:57:10 -03:00
tasklet_kill ( & mantis - > tasklet ) ;
dvb_net_release ( & mantis - > dvbnet ) ;
2009-12-04 05:56:35 -03:00
2009-12-02 21:57:10 -03:00
mantis - > demux . dmx . remove_frontend ( & mantis - > demux . dmx , & mantis - > fe_mem ) ;
mantis - > demux . dmx . remove_frontend ( & mantis - > demux . dmx , & mantis - > fe_hw ) ;
2009-12-04 05:56:35 -03:00
2009-12-02 21:57:10 -03:00
dvb_dmxdev_release ( & mantis - > dmxdev ) ;
dvb_dmx_release ( & mantis - > demux ) ;
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " dvb_unregister_adapter " ) ;
2009-12-02 21:57:10 -03:00
dvb_unregister_adapter ( & mantis - > dvb_adapter ) ;
return 0 ;
}
2009-12-04 05:41:11 -03:00
EXPORT_SYMBOL_GPL ( mantis_dvb_exit ) ;