root/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. netup_ci_interrupt
  2. netup_unidvb_ci_slot_ts_ctl
  3. netup_unidvb_ci_slot_shutdown
  4. netup_unidvb_ci_slot_reset
  5. netup_unidvb_poll_ci_slot_status
  6. netup_unidvb_ci_read_attribute_mem
  7. netup_unidvb_ci_write_attribute_mem
  8. netup_unidvb_ci_read_cam_ctl
  9. netup_unidvb_ci_write_cam_ctl
  10. netup_unidvb_ci_register
  11. netup_unidvb_ci_unregister

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * netup_unidvb_ci.c
   4  *
   5  * DVB CAM support for NetUP Universal Dual DVB-CI
   6  *
   7  * Copyright (C) 2014 NetUP Inc.
   8  * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
   9  * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
  10  */
  11 
  12 #include <linux/init.h>
  13 #include <linux/module.h>
  14 #include <linux/moduleparam.h>
  15 #include <linux/kmod.h>
  16 #include <linux/kernel.h>
  17 #include <linux/slab.h>
  18 #include <linux/interrupt.h>
  19 #include <linux/delay.h>
  20 #include "netup_unidvb.h"
  21 
  22 /* CI slot 0 base address */
  23 #define CAM0_CONFIG             0x0
  24 #define CAM0_IO                 0x8000
  25 #define CAM0_MEM                0x10000
  26 #define CAM0_SZ                 32
  27 /* CI slot 1 base address */
  28 #define CAM1_CONFIG             0x20000
  29 #define CAM1_IO                 0x28000
  30 #define CAM1_MEM                0x30000
  31 #define CAM1_SZ                 32
  32 /* ctrlstat registers */
  33 #define CAM_CTRLSTAT_READ_SET   0x4980
  34 #define CAM_CTRLSTAT_CLR        0x4982
  35 /* register bits */
  36 #define BIT_CAM_STCHG           (1<<0)
  37 #define BIT_CAM_PRESENT         (1<<1)
  38 #define BIT_CAM_RESET           (1<<2)
  39 #define BIT_CAM_BYPASS          (1<<3)
  40 #define BIT_CAM_READY           (1<<4)
  41 #define BIT_CAM_ERROR           (1<<5)
  42 #define BIT_CAM_OVERCURR        (1<<6)
  43 /* BIT_CAM_BYPASS bit shift for SLOT 1 */
  44 #define CAM1_SHIFT 8
  45 
  46 irqreturn_t netup_ci_interrupt(struct netup_unidvb_dev *ndev)
  47 {
  48         writew(0x101, ndev->bmmio0 + CAM_CTRLSTAT_CLR);
  49         return IRQ_HANDLED;
  50 }
  51 
  52 static int netup_unidvb_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221,
  53                                        int slot)
  54 {
  55         struct netup_ci_state *state = en50221->data;
  56         struct netup_unidvb_dev *dev = state->dev;
  57         u16 shift = (state->nr == 1) ? CAM1_SHIFT : 0;
  58 
  59         dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT=0x%x\n",
  60                 __func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
  61         if (slot != 0)
  62                 return -EINVAL;
  63         /* pass data to CAM module */
  64         writew(BIT_CAM_BYPASS << shift, dev->bmmio0 + CAM_CTRLSTAT_CLR);
  65         dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT=0x%x done\n",
  66                 __func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
  67         return 0;
  68 }
  69 
  70 static int netup_unidvb_ci_slot_shutdown(struct dvb_ca_en50221 *en50221,
  71                                          int slot)
  72 {
  73         struct netup_ci_state *state = en50221->data;
  74         struct netup_unidvb_dev *dev = state->dev;
  75 
  76         dev_dbg(&dev->pci_dev->dev, "%s()\n", __func__);
  77         return 0;
  78 }
  79 
  80 static int netup_unidvb_ci_slot_reset(struct dvb_ca_en50221 *en50221,
  81                                       int slot)
  82 {
  83         struct netup_ci_state *state = en50221->data;
  84         struct netup_unidvb_dev *dev = state->dev;
  85         unsigned long timeout = 0;
  86         u16 shift = (state->nr == 1) ? CAM1_SHIFT : 0;
  87         u16 ci_stat = 0;
  88         int reset_counter = 3;
  89 
  90         dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT_READ_SET=0x%x\n",
  91                 __func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
  92 reset:
  93         timeout = jiffies + msecs_to_jiffies(5000);
  94         /* start reset */
  95         writew(BIT_CAM_RESET << shift, dev->bmmio0 + CAM_CTRLSTAT_READ_SET);
  96         dev_dbg(&dev->pci_dev->dev, "%s(): waiting for reset\n", __func__);
  97         /* wait until reset done */
  98         while (time_before(jiffies, timeout)) {
  99                 ci_stat = readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET);
 100                 if (ci_stat & (BIT_CAM_READY << shift))
 101                         break;
 102                 udelay(1000);
 103         }
 104         if (!(ci_stat & (BIT_CAM_READY << shift)) && reset_counter > 0) {
 105                 dev_dbg(&dev->pci_dev->dev,
 106                         "%s(): CAMP reset timeout! Will try again..\n",
 107                          __func__);
 108                 reset_counter--;
 109                 goto reset;
 110         }
 111         return 0;
 112 }
 113 
 114 static int netup_unidvb_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
 115                                             int slot, int open)
 116 {
 117         struct netup_ci_state *state = en50221->data;
 118         struct netup_unidvb_dev *dev = state->dev;
 119         u16 shift = (state->nr == 1) ? CAM1_SHIFT : 0;
 120         u16 ci_stat = 0;
 121 
 122         dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT_READ_SET=0x%x\n",
 123                 __func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
 124         ci_stat = readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET);
 125         if (ci_stat & (BIT_CAM_READY << shift)) {
 126                 state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
 127                         DVB_CA_EN50221_POLL_CAM_READY;
 128         } else if (ci_stat & (BIT_CAM_PRESENT << shift)) {
 129                 state->status = DVB_CA_EN50221_POLL_CAM_PRESENT;
 130         } else {
 131                 state->status = 0;
 132         }
 133         return state->status;
 134 }
 135 
 136 static int netup_unidvb_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
 137                                               int slot, int addr)
 138 {
 139         struct netup_ci_state *state = en50221->data;
 140         struct netup_unidvb_dev *dev = state->dev;
 141         u8 val = *((u8 __force *)state->membase8_config + addr);
 142 
 143         dev_dbg(&dev->pci_dev->dev,
 144                 "%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
 145         return val;
 146 }
 147 
 148 static int netup_unidvb_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
 149                                                int slot, int addr, u8 data)
 150 {
 151         struct netup_ci_state *state = en50221->data;
 152         struct netup_unidvb_dev *dev = state->dev;
 153 
 154         dev_dbg(&dev->pci_dev->dev,
 155                 "%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
 156         *((u8 __force *)state->membase8_config + addr) = data;
 157         return 0;
 158 }
 159 
 160 static int netup_unidvb_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,
 161                                         int slot, u8 addr)
 162 {
 163         struct netup_ci_state *state = en50221->data;
 164         struct netup_unidvb_dev *dev = state->dev;
 165         u8 val = *((u8 __force *)state->membase8_io + addr);
 166 
 167         dev_dbg(&dev->pci_dev->dev,
 168                 "%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
 169         return val;
 170 }
 171 
 172 static int netup_unidvb_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221,
 173                                          int slot, u8 addr, u8 data)
 174 {
 175         struct netup_ci_state *state = en50221->data;
 176         struct netup_unidvb_dev *dev = state->dev;
 177 
 178         dev_dbg(&dev->pci_dev->dev,
 179                 "%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
 180         *((u8 __force *)state->membase8_io + addr) = data;
 181         return 0;
 182 }
 183 
 184 int netup_unidvb_ci_register(struct netup_unidvb_dev *dev,
 185                              int num, struct pci_dev *pci_dev)
 186 {
 187         int result;
 188         struct netup_ci_state *state;
 189 
 190         if (num < 0 || num > 1) {
 191                 dev_err(&pci_dev->dev, "%s(): invalid CI adapter %d\n",
 192                         __func__, num);
 193                 return -EINVAL;
 194         }
 195         state = &dev->ci[num];
 196         state->nr = num;
 197         state->membase8_config = dev->bmmio1 +
 198                 ((num == 0) ? CAM0_CONFIG : CAM1_CONFIG);
 199         state->membase8_io = dev->bmmio1 +
 200                 ((num == 0) ? CAM0_IO : CAM1_IO);
 201         state->dev = dev;
 202         state->ca.owner = THIS_MODULE;
 203         state->ca.read_attribute_mem = netup_unidvb_ci_read_attribute_mem;
 204         state->ca.write_attribute_mem = netup_unidvb_ci_write_attribute_mem;
 205         state->ca.read_cam_control = netup_unidvb_ci_read_cam_ctl;
 206         state->ca.write_cam_control = netup_unidvb_ci_write_cam_ctl;
 207         state->ca.slot_reset = netup_unidvb_ci_slot_reset;
 208         state->ca.slot_shutdown = netup_unidvb_ci_slot_shutdown;
 209         state->ca.slot_ts_enable = netup_unidvb_ci_slot_ts_ctl;
 210         state->ca.poll_slot_status = netup_unidvb_poll_ci_slot_status;
 211         state->ca.data = state;
 212         result = dvb_ca_en50221_init(&dev->frontends[num].adapter,
 213                 &state->ca, 0, 1);
 214         if (result < 0) {
 215                 dev_err(&pci_dev->dev,
 216                         "%s(): dvb_ca_en50221_init result %d\n",
 217                         __func__, result);
 218                 return result;
 219         }
 220         writew(NETUP_UNIDVB_IRQ_CI, dev->bmmio0 + REG_IMASK_SET);
 221         dev_info(&pci_dev->dev,
 222                 "%s(): CI adapter %d init done\n", __func__, num);
 223         return 0;
 224 }
 225 
 226 void netup_unidvb_ci_unregister(struct netup_unidvb_dev *dev, int num)
 227 {
 228         struct netup_ci_state *state;
 229 
 230         dev_dbg(&dev->pci_dev->dev, "%s()\n", __func__);
 231         if (num < 0 || num > 1) {
 232                 dev_err(&dev->pci_dev->dev, "%s(): invalid CI adapter %d\n",
 233                                 __func__, num);
 234                 return;
 235         }
 236         state = &dev->ci[num];
 237         dvb_ca_en50221_release(&state->ca);
 238 }
 239 

/* [<][>][^][v][top][bottom][index][help] */