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