linux/drivers/media/pci/mantis/mantis_dvb.c
<<
>>
Prefs
   1/*
   2        Mantis PCI bridge driver
   3        Copyright (C) Manu Abraham (abraham.manu@gmail.com)
   4
   5        This program is free software; you can redistribute it and/or modify
   6        it under the terms of the GNU General Public License as published by
   7        the Free Software Foundation; either version 2 of the License, or
   8        (at your option) any later version.
   9
  10        This program is distributed in the hope that it will be useful,
  11        but WITHOUT ANY WARRANTY; without even the implied warranty of
  12        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13        GNU General Public License for more details.
  14
  15        You should have received a copy of the GNU General Public License
  16        along with this program; if not, write to the Free Software
  17        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18*/
  19
  20#include <linux/kernel.h>
  21#include <linux/bitops.h>
  22
  23#include <linux/signal.h>
  24#include <linux/sched.h>
  25#include <linux/interrupt.h>
  26#include <linux/pci.h>
  27#include <linux/i2c.h>
  28
  29#include "dmxdev.h"
  30#include "dvbdev.h"
  31#include "dvb_demux.h"
  32#include "dvb_frontend.h"
  33#include "dvb_net.h"
  34
  35#include "mantis_common.h"
  36#include "mantis_dma.h"
  37#include "mantis_ca.h"
  38#include "mantis_ioc.h"
  39#include "mantis_dvb.h"
  40
  41DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  42
  43int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)
  44{
  45        struct mantis_hwconfig *config = mantis->hwconfig;
  46
  47        switch (power) {
  48        case POWER_ON:
  49                dprintk(MANTIS_DEBUG, 1, "Power ON");
  50                mantis_gpio_set_bits(mantis, config->power, POWER_ON);
  51                msleep(100);
  52                mantis_gpio_set_bits(mantis, config->power, POWER_ON);
  53                msleep(100);
  54                break;
  55
  56        case POWER_OFF:
  57                dprintk(MANTIS_DEBUG, 1, "Power OFF");
  58                mantis_gpio_set_bits(mantis, config->power, POWER_OFF);
  59                msleep(100);
  60                break;
  61
  62        default:
  63                dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power);
  64                return -1;
  65        }
  66
  67        return 0;
  68}
  69EXPORT_SYMBOL_GPL(mantis_frontend_power);
  70
  71void mantis_frontend_soft_reset(struct mantis_pci *mantis)
  72{
  73        struct mantis_hwconfig *config = mantis->hwconfig;
  74
  75        dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
  76        mantis_gpio_set_bits(mantis, config->reset, 0);
  77        msleep(100);
  78        mantis_gpio_set_bits(mantis, config->reset, 0);
  79        msleep(100);
  80        mantis_gpio_set_bits(mantis, config->reset, 1);
  81        msleep(100);
  82        mantis_gpio_set_bits(mantis, config->reset, 1);
  83        msleep(100);
  84
  85        return;
  86}
  87EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset);
  88
  89static int mantis_frontend_shutdown(struct mantis_pci *mantis)
  90{
  91        int err;
  92
  93        mantis_frontend_soft_reset(mantis);
  94        err = mantis_frontend_power(mantis, POWER_OFF);
  95        if (err != 0) {
  96                dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err);
  97                return 1;
  98        }
  99
 100        return 0;
 101}
 102
 103static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 104{
 105        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 106        struct mantis_pci *mantis = dvbdmx->priv;
 107
 108        dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed");
 109        if (!dvbdmx->dmx.frontend) {
 110                dprintk(MANTIS_DEBUG, 1, "no frontend ?");
 111                return -EINVAL;
 112        }
 113
 114        mantis->feeds++;
 115        dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds);
 116
 117        if (mantis->feeds == 1)  {
 118                dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
 119                mantis_dma_start(mantis);
 120                tasklet_enable(&mantis->tasklet);
 121        }
 122
 123        return mantis->feeds;
 124}
 125
 126static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 127{
 128        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 129        struct mantis_pci *mantis = dvbdmx->priv;
 130
 131        dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");
 132        if (!dvbdmx->dmx.frontend) {
 133                dprintk(MANTIS_DEBUG, 1, "no frontend ?");
 134                return -EINVAL;
 135        }
 136
 137        mantis->feeds--;
 138        if (mantis->feeds == 0) {
 139                dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
 140                tasklet_disable(&mantis->tasklet);
 141                mantis_dma_stop(mantis);
 142        }
 143
 144        return 0;
 145}
 146
 147int mantis_dvb_init(struct mantis_pci *mantis)
 148{
 149        struct mantis_hwconfig *config = mantis->hwconfig;
 150        int result = -1;
 151
 152        dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");
 153
 154        result = dvb_register_adapter(&mantis->dvb_adapter,
 155                                      "Mantis DVB adapter",
 156                                      THIS_MODULE,
 157                                      &mantis->pdev->dev,
 158                                      adapter_nr);
 159
 160        if (result < 0) {
 161
 162                dprintk(MANTIS_ERROR, 1, "Error registering adapter");
 163                return -ENODEV;
 164        }
 165
 166        mantis->dvb_adapter.priv        = mantis;
 167        mantis->demux.dmx.capabilities  = DMX_TS_FILTERING      |
 168                                         DMX_SECTION_FILTERING  |
 169                                         DMX_MEMORY_BASED_FILTERING;
 170
 171        mantis->demux.priv              = mantis;
 172        mantis->demux.filternum         = 256;
 173        mantis->demux.feednum           = 256;
 174        mantis->demux.start_feed        = mantis_dvb_start_feed;
 175        mantis->demux.stop_feed         = mantis_dvb_stop_feed;
 176        mantis->demux.write_to_decoder  = NULL;
 177
 178        dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
 179        result = dvb_dmx_init(&mantis->demux);
 180        if (result < 0) {
 181                dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
 182
 183                goto err0;
 184        }
 185
 186        mantis->dmxdev.filternum        = 256;
 187        mantis->dmxdev.demux            = &mantis->demux.dmx;
 188        mantis->dmxdev.capabilities     = 0;
 189        dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");
 190
 191        result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
 192        if (result < 0) {
 193
 194                dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
 195                goto err1;
 196        }
 197
 198        mantis->fe_hw.source            = DMX_FRONTEND_0;
 199        result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
 200        if (result < 0) {
 201
 202                dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
 203                goto err2;
 204        }
 205
 206        mantis->fe_mem.source           = DMX_MEMORY_FE;
 207        result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
 208        if (result < 0) {
 209                dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
 210                goto err3;
 211        }
 212
 213        result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
 214        if (result < 0) {
 215                dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
 216                goto err4;
 217        }
 218
 219        dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
 220        tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
 221        tasklet_disable(&mantis->tasklet);
 222        if (mantis->hwconfig) {
 223                result = config->frontend_init(mantis, mantis->fe);
 224                if (result < 0) {
 225                        dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
 226                        goto err5;
 227                } else {
 228                        if (mantis->fe == NULL) {
 229                                dprintk(MANTIS_ERROR, 1, "FE <NULL>");
 230                                goto err5;
 231                        }
 232
 233                        if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) {
 234                                dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");
 235
 236                                if (mantis->fe->ops.release)
 237                                        mantis->fe->ops.release(mantis->fe);
 238
 239                                mantis->fe = NULL;
 240                                goto err5;
 241                        }
 242                }
 243        }
 244
 245        return 0;
 246
 247        /* Error conditions ..  */
 248err5:
 249        tasklet_kill(&mantis->tasklet);
 250        dvb_net_release(&mantis->dvbnet);
 251        if (mantis->fe) {
 252                dvb_unregister_frontend(mantis->fe);
 253                dvb_frontend_detach(mantis->fe);
 254        }
 255err4:
 256        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
 257
 258err3:
 259        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
 260
 261err2:
 262        dvb_dmxdev_release(&mantis->dmxdev);
 263
 264err1:
 265        dvb_dmx_release(&mantis->demux);
 266
 267err0:
 268        dvb_unregister_adapter(&mantis->dvb_adapter);
 269
 270        return result;
 271}
 272EXPORT_SYMBOL_GPL(mantis_dvb_init);
 273
 274int mantis_dvb_exit(struct mantis_pci *mantis)
 275{
 276        int err;
 277
 278        if (mantis->fe) {
 279                /* mantis_ca_exit(mantis); */
 280                err = mantis_frontend_shutdown(mantis);
 281                if (err != 0)
 282                        dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
 283                dvb_unregister_frontend(mantis->fe);
 284                dvb_frontend_detach(mantis->fe);
 285        }
 286
 287        tasklet_kill(&mantis->tasklet);
 288        dvb_net_release(&mantis->dvbnet);
 289
 290        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
 291        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
 292
 293        dvb_dmxdev_release(&mantis->dmxdev);
 294        dvb_dmx_release(&mantis->demux);
 295
 296        dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
 297        dvb_unregister_adapter(&mantis->dvb_adapter);
 298
 299        return 0;
 300}
 301EXPORT_SYMBOL_GPL(mantis_dvb_exit);
 302