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