| |
| |
| |
| |
| |
| |
| |
| #include <linux/kernel.h> |
| #include <linux/bitops.h> |
| |
| #include <linux/signal.h> |
| #include <linux/sched.h> |
| #include <linux/interrupt.h> |
| #include <linux/pci.h> |
| #include <linux/i2c.h> |
| |
| #include <media/dmxdev.h> |
| #include <media/dvbdev.h> |
| #include <media/dvb_demux.h> |
| #include <media/dvb_frontend.h> |
| #include <media/dvb_net.h> |
| |
| #include "mantis_common.h" |
| #include "mantis_dma.h" |
| #include "mantis_ca.h" |
| #include "mantis_ioc.h" |
| #include "mantis_dvb.h" |
| |
| DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| |
| int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power) |
| { |
| <------>struct mantis_hwconfig *config = mantis->hwconfig; |
| |
| <------>switch (power) { |
| <------>case POWER_ON: |
| <------><------>dprintk(MANTIS_DEBUG, 1, "Power ON"); |
| <------><------>mantis_gpio_set_bits(mantis, config->power, POWER_ON); |
| <------><------>msleep(100); |
| <------><------>mantis_gpio_set_bits(mantis, config->power, POWER_ON); |
| <------><------>msleep(100); |
| <------><------>break; |
| |
| <------>case POWER_OFF: |
| <------><------>dprintk(MANTIS_DEBUG, 1, "Power OFF"); |
| <------><------>mantis_gpio_set_bits(mantis, config->power, POWER_OFF); |
| <------><------>msleep(100); |
| <------><------>break; |
| |
| <------>default: |
| <------><------>dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power); |
| <------><------>return -1; |
| <------>} |
| |
| <------>return 0; |
| } |
| EXPORT_SYMBOL_GPL(mantis_frontend_power); |
| |
| void mantis_frontend_soft_reset(struct mantis_pci *mantis) |
| { |
| <------>struct mantis_hwconfig *config = mantis->hwconfig; |
| |
| <------>dprintk(MANTIS_DEBUG, 1, "Frontend RESET"); |
| <------>mantis_gpio_set_bits(mantis, config->reset, 0); |
| <------>msleep(100); |
| <------>mantis_gpio_set_bits(mantis, config->reset, 0); |
| <------>msleep(100); |
| <------>mantis_gpio_set_bits(mantis, config->reset, 1); |
| <------>msleep(100); |
| <------>mantis_gpio_set_bits(mantis, config->reset, 1); |
| <------>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; |
| <------>} |
| |
| <------>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; |
| |
| <------>dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed"); |
| <------>if (!dvbdmx->dmx.frontend) { |
| <------><------>dprintk(MANTIS_DEBUG, 1, "no frontend ?"); |
| <------><------>return -EINVAL; |
| <------>} |
| |
| <------>mantis->feeds++; |
| <------>dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds); |
| |
| <------>if (mantis->feeds == 1) { |
| <------><------>dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); |
| <------><------>mantis_dma_start(mantis); |
| <------><------>tasklet_enable(&mantis->tasklet); |
| <------>} |
| |
| <------>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; |
| |
| <------>dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); |
| <------>if (!dvbdmx->dmx.frontend) { |
| <------><------>dprintk(MANTIS_DEBUG, 1, "no frontend ?"); |
| <------><------>return -EINVAL; |
| <------>} |
| |
| <------>mantis->feeds--; |
| <------>if (mantis->feeds == 0) { |
| <------><------>dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); |
| <------><------>tasklet_disable(&mantis->tasklet); |
| <------><------>mantis_dma_stop(mantis); |
| <------>} |
| |
| <------>return 0; |
| } |
| |
| int mantis_dvb_init(struct mantis_pci *mantis) |
| { |
| <------>struct mantis_hwconfig *config = mantis->hwconfig; |
| <------>int result; |
| |
| <------>dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter"); |
| |
| <------>result = dvb_register_adapter(&mantis->dvb_adapter, |
| <------><------><------><------> "Mantis DVB adapter", |
| <------><------><------><------> THIS_MODULE, |
| <------><------><------><------> &mantis->pdev->dev, |
| <------><------><------><------> adapter_nr); |
| |
| <------>if (result < 0) { |
| |
| <------><------>dprintk(MANTIS_ERROR, 1, "Error registering adapter"); |
| <------><------>return -ENODEV; |
| <------>} |
| |
| <------>mantis->dvb_adapter.priv = mantis; |
| <------>mantis->demux.dmx.capabilities = DMX_TS_FILTERING | |
| <------><------><------><------><------> DMX_SECTION_FILTERING | |
| <------><------><------><------><------> DMX_MEMORY_BASED_FILTERING; |
| |
| <------>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); |
| |
| <------><------>goto err0; |
| <------>} |
| |
| <------>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); |
| <------><------>goto err1; |
| <------>} |
| |
| <------>mantis->fe_hw.source = DMX_FRONTEND_0; |
| <------>result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw); |
| <------>if (result < 0) { |
| |
| <------><------>dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); |
| <------><------>goto err2; |
| <------>} |
| |
| <------>mantis->fe_mem.source = DMX_MEMORY_FE; |
| <------>result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem); |
| <------>if (result < 0) { |
| <------><------>dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); |
| <------><------>goto err3; |
| <------>} |
| |
| <------>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); |
| <------><------>goto err4; |
| <------>} |
| |
| <------>dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); |
| <------>tasklet_setup(&mantis->tasklet, mantis_dma_xfer); |
| <------>tasklet_disable(&mantis->tasklet); |
| <------>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) { |
| <------><------><------><------>result = -ENOMEM; |
| <------><------><------><------>dprintk(MANTIS_ERROR, 1, "FE <NULL>"); |
| <------><------><------><------>goto err5; |
| <------><------><------>} |
| <------><------><------>result = dvb_register_frontend(&mantis->dvb_adapter, mantis->fe); |
| <------><------><------>if (result) { |
| <------><------><------><------>dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed"); |
| |
| <------><------><------><------>if (mantis->fe->ops.release) |
| <------><------><------><------><------>mantis->fe->ops.release(mantis->fe); |
| |
| <------><------><------><------>mantis->fe = NULL; |
| <------><------><------><------>goto err5; |
| <------><------><------>} |
| <------><------>} |
| <------>} |
| |
| <------>return 0; |
| |
| <------> |
| err5: |
| <------>tasklet_kill(&mantis->tasklet); |
| <------>dvb_net_release(&mantis->dvbnet); |
| <------>if (mantis->fe) { |
| <------><------>dvb_unregister_frontend(mantis->fe); |
| <------><------>dvb_frontend_detach(mantis->fe); |
| <------>} |
| err4: |
| <------>mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); |
| |
| err3: |
| <------>mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); |
| |
| err2: |
| <------>dvb_dmxdev_release(&mantis->dmxdev); |
| |
| err1: |
| <------>dvb_dmx_release(&mantis->demux); |
| |
| err0: |
| <------>dvb_unregister_adapter(&mantis->dvb_adapter); |
| |
| <------>return result; |
| } |
| EXPORT_SYMBOL_GPL(mantis_dvb_init); |
| |
| int mantis_dvb_exit(struct mantis_pci *mantis) |
| { |
| <------>int err; |
| |
| <------>if (mantis->fe) { |
| <------><------> |
| <------><------>err = mantis_frontend_shutdown(mantis); |
| <------><------>if (err != 0) |
| <------><------><------>dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); |
| <------><------>dvb_unregister_frontend(mantis->fe); |
| <------><------>dvb_frontend_detach(mantis->fe); |
| <------>} |
| |
| <------>tasklet_kill(&mantis->tasklet); |
| <------>dvb_net_release(&mantis->dvbnet); |
| |
| <------>mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); |
| <------>mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); |
| |
| <------>dvb_dmxdev_release(&mantis->dmxdev); |
| <------>dvb_dmx_release(&mantis->demux); |
| |
| <------>dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter"); |
| <------>dvb_unregister_adapter(&mantis->dvb_adapter); |
| |
| <------>return 0; |
| } |
| EXPORT_SYMBOL_GPL(mantis_dvb_exit); |
| |