linux/drivers/media/pci/mantis/mantis_ca.c
<<
>>
Prefs
   1/*
   2        Mantis PCI bridge driver
   3
   4        Copyright (C) Manu Abraham (abraham.manu@gmail.com)
   5
   6        This program is free software; you can redistribute it and/or modify
   7        it under the terms of the GNU General Public License as published by
   8        the Free Software Foundation; either version 2 of the License, or
   9        (at your option) any later version.
  10
  11        This program is distributed in the hope that it will be useful,
  12        but WITHOUT ANY WARRANTY; without even the implied warranty of
  13        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14        GNU General Public License for more details.
  15
  16        You should have received a copy of the GNU General Public License
  17        along with this program; if not, write to the Free Software
  18        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19*/
  20
  21#include <linux/signal.h>
  22#include <linux/slab.h>
  23#include <linux/sched.h>
  24#include <linux/interrupt.h>
  25#include <asm/io.h>
  26
  27#include <media/dmxdev.h>
  28#include <media/dvbdev.h>
  29#include <media/dvb_demux.h>
  30#include <media/dvb_frontend.h>
  31#include <media/dvb_net.h>
  32
  33#include "mantis_common.h"
  34#include "mantis_link.h"
  35#include "mantis_hif.h"
  36#include "mantis_reg.h"
  37
  38#include "mantis_ca.h"
  39
  40static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr)
  41{
  42        struct mantis_ca *ca = en50221->data;
  43        struct mantis_pci *mantis = ca->ca_priv;
  44
  45        dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot);
  46
  47        if (slot != 0)
  48                return -EINVAL;
  49
  50        return mantis_hif_read_mem(ca, addr);
  51}
  52
  53static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data)
  54{
  55        struct mantis_ca *ca = en50221->data;
  56        struct mantis_pci *mantis = ca->ca_priv;
  57
  58        dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot);
  59
  60        if (slot != 0)
  61                return -EINVAL;
  62
  63        return mantis_hif_write_mem(ca, addr, data);
  64}
  65
  66static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
  67{
  68        struct mantis_ca *ca = en50221->data;
  69        struct mantis_pci *mantis = ca->ca_priv;
  70
  71        dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot);
  72
  73        if (slot != 0)
  74                return -EINVAL;
  75
  76        return mantis_hif_read_iom(ca, addr);
  77}
  78
  79static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data)
  80{
  81        struct mantis_ca *ca = en50221->data;
  82        struct mantis_pci *mantis = ca->ca_priv;
  83
  84        dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot);
  85
  86        if (slot != 0)
  87                return -EINVAL;
  88
  89        return mantis_hif_write_iom(ca, addr, data);
  90}
  91
  92static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
  93{
  94        struct mantis_ca *ca = en50221->data;
  95        struct mantis_pci *mantis = ca->ca_priv;
  96
  97        dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot);
  98        udelay(500); /* Wait.. */
  99        mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */
 100        udelay(500);
 101        mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */
 102        msleep(1000);
 103        dvb_ca_en50221_camready_irq(&ca->en50221, 0);
 104
 105        return 0;
 106}
 107
 108static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
 109{
 110        struct mantis_ca *ca = en50221->data;
 111        struct mantis_pci *mantis = ca->ca_priv;
 112
 113        dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot);
 114
 115        return 0;
 116}
 117
 118static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot)
 119{
 120        struct mantis_ca *ca = en50221->data;
 121        struct mantis_pci *mantis = ca->ca_priv;
 122
 123        dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot);
 124/*      mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */
 125
 126        return 0;
 127}
 128
 129static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
 130{
 131        struct mantis_ca *ca = en50221->data;
 132        struct mantis_pci *mantis = ca->ca_priv;
 133
 134        dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot);
 135
 136        if (ca->slot_state == MODULE_INSERTED) {
 137                dprintk(MANTIS_DEBUG, 1, "CA Module present and ready");
 138                return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
 139        } else {
 140                dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready");
 141        }
 142
 143        return 0;
 144}
 145
 146int mantis_ca_init(struct mantis_pci *mantis)
 147{
 148        struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter;
 149        struct mantis_ca *ca;
 150        int ca_flags = 0, result;
 151
 152        dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA");
 153        ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL);
 154        if (!ca) {
 155                dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting ..");
 156                result = -ENOMEM;
 157                goto err;
 158        }
 159
 160        ca->ca_priv             = mantis;
 161        mantis->mantis_ca       = ca;
 162        ca_flags                = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE;
 163        /* register CA interface */
 164        ca->en50221.owner               = THIS_MODULE;
 165        ca->en50221.read_attribute_mem  = mantis_ca_read_attr_mem;
 166        ca->en50221.write_attribute_mem = mantis_ca_write_attr_mem;
 167        ca->en50221.read_cam_control    = mantis_ca_read_cam_ctl;
 168        ca->en50221.write_cam_control   = mantis_ca_write_cam_ctl;
 169        ca->en50221.slot_reset          = mantis_ca_slot_reset;
 170        ca->en50221.slot_shutdown       = mantis_ca_slot_shutdown;
 171        ca->en50221.slot_ts_enable      = mantis_ts_control;
 172        ca->en50221.poll_slot_status    = mantis_slot_status;
 173        ca->en50221.data                = ca;
 174
 175        mutex_init(&ca->ca_lock);
 176
 177        init_waitqueue_head(&ca->hif_data_wq);
 178        init_waitqueue_head(&ca->hif_opdone_wq);
 179        init_waitqueue_head(&ca->hif_write_wq);
 180
 181        dprintk(MANTIS_ERROR, 1, "Registering EN50221 device");
 182        result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1);
 183        if (result != 0) {
 184                dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result);
 185                goto err;
 186        }
 187        dprintk(MANTIS_ERROR, 1, "Registered EN50221 device");
 188        mantis_evmgr_init(ca);
 189        return 0;
 190err:
 191        kfree(ca);
 192        return result;
 193}
 194EXPORT_SYMBOL_GPL(mantis_ca_init);
 195
 196void mantis_ca_exit(struct mantis_pci *mantis)
 197{
 198        struct mantis_ca *ca = mantis->mantis_ca;
 199
 200        dprintk(MANTIS_DEBUG, 1, "Mantis CA exit");
 201        if (!ca)
 202                return;
 203
 204        mantis_evmgr_exit(ca);
 205        dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device");
 206        dvb_ca_en50221_release(&ca->en50221);
 207
 208        kfree(ca);
 209}
 210EXPORT_SYMBOL_GPL(mantis_ca_exit);
 211