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
 113        return 0;
 114}
 115
 116static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
 117{
 118        struct mantis_ca *ca = en50221->data;
 119        struct mantis_pci *mantis = ca->ca_priv;
 120
 121        dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot);
 122
 123        if (ca->slot_state == MODULE_INSERTED) {
 124                dprintk(MANTIS_DEBUG, 1, "CA Module present and ready");
 125                return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
 126        } else {
 127                dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready");
 128        }
 129
 130        return 0;
 131}
 132
 133int mantis_ca_init(struct mantis_pci *mantis)
 134{
 135        struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter;
 136        struct mantis_ca *ca;
 137        int ca_flags = 0, result;
 138
 139        dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA");
 140        ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL);
 141        if (!ca) {
 142                dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting ..");
 143                result = -ENOMEM;
 144                goto err;
 145        }
 146
 147        ca->ca_priv             = mantis;
 148        mantis->mantis_ca       = ca;
 149        ca_flags                = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE;
 150        /* register CA interface */
 151        ca->en50221.owner               = THIS_MODULE;
 152        ca->en50221.read_attribute_mem  = mantis_ca_read_attr_mem;
 153        ca->en50221.write_attribute_mem = mantis_ca_write_attr_mem;
 154        ca->en50221.read_cam_control    = mantis_ca_read_cam_ctl;
 155        ca->en50221.write_cam_control   = mantis_ca_write_cam_ctl;
 156        ca->en50221.slot_reset          = mantis_ca_slot_reset;
 157        ca->en50221.slot_shutdown       = mantis_ca_slot_shutdown;
 158        ca->en50221.slot_ts_enable      = mantis_ts_control;
 159        ca->en50221.poll_slot_status    = mantis_slot_status;
 160        ca->en50221.data                = ca;
 161
 162        mutex_init(&ca->ca_lock);
 163
 164        init_waitqueue_head(&ca->hif_data_wq);
 165        init_waitqueue_head(&ca->hif_opdone_wq);
 166        init_waitqueue_head(&ca->hif_write_wq);
 167
 168        dprintk(MANTIS_ERROR, 1, "Registering EN50221 device");
 169        result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1);
 170        if (result != 0) {
 171                dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result);
 172                goto err;
 173        }
 174        dprintk(MANTIS_ERROR, 1, "Registered EN50221 device");
 175        mantis_evmgr_init(ca);
 176        return 0;
 177err:
 178        kfree(ca);
 179        return result;
 180}
 181EXPORT_SYMBOL_GPL(mantis_ca_init);
 182
 183void mantis_ca_exit(struct mantis_pci *mantis)
 184{
 185        struct mantis_ca *ca = mantis->mantis_ca;
 186
 187        dprintk(MANTIS_DEBUG, 1, "Mantis CA exit");
 188        if (!ca)
 189                return;
 190
 191        mantis_evmgr_exit(ca);
 192        dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device");
 193        dvb_ca_en50221_release(&ca->en50221);
 194
 195        kfree(ca);
 196}
 197EXPORT_SYMBOL_GPL(mantis_ca_exit);
 198