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