linux/drivers/media/pci/mantis/mantis_cards.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/module.h>
  22#include <linux/moduleparam.h>
  23#include <linux/kernel.h>
  24#include <linux/pci.h>
  25#include <linux/slab.h>
  26#include <asm/irq.h>
  27#include <linux/interrupt.h>
  28#include <media/rc-map.h>
  29
  30#include <media/dmxdev.h>
  31#include <media/dvbdev.h>
  32#include <media/dvb_demux.h>
  33#include <media/dvb_frontend.h>
  34#include <media/dvb_net.h>
  35
  36#include "mantis_common.h"
  37
  38#include "mantis_vp1033.h"
  39#include "mantis_vp1034.h"
  40#include "mantis_vp1041.h"
  41#include "mantis_vp2033.h"
  42#include "mantis_vp2040.h"
  43#include "mantis_vp3030.h"
  44
  45#include "mantis_dma.h"
  46#include "mantis_ca.h"
  47#include "mantis_dvb.h"
  48#include "mantis_uart.h"
  49#include "mantis_ioc.h"
  50#include "mantis_pci.h"
  51#include "mantis_i2c.h"
  52#include "mantis_reg.h"
  53#include "mantis_input.h"
  54
  55static unsigned int verbose;
  56module_param(verbose, int, 0644);
  57MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
  58
  59static int devs;
  60
  61#define DRIVER_NAME     "Mantis"
  62
  63static char *label[10] = {
  64        "DMA",
  65        "IRQ-0",
  66        "IRQ-1",
  67        "OCERR",
  68        "PABRT",
  69        "RIPRR",
  70        "PPERR",
  71        "FTRGT",
  72        "RISCI",
  73        "RACK"
  74};
  75
  76static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
  77{
  78        u32 stat = 0, mask = 0;
  79        u32 rst_stat = 0, rst_mask = 0;
  80
  81        struct mantis_pci *mantis;
  82        struct mantis_ca *ca;
  83
  84        mantis = (struct mantis_pci *) dev_id;
  85        if (unlikely(mantis == NULL)) {
  86                dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
  87                return IRQ_NONE;
  88        }
  89        ca = mantis->mantis_ca;
  90
  91        stat = mmread(MANTIS_INT_STAT);
  92        mask = mmread(MANTIS_INT_MASK);
  93        if (!(stat & mask))
  94                return IRQ_NONE;
  95
  96        rst_mask  = MANTIS_GPIF_WRACK  |
  97                    MANTIS_GPIF_OTHERR |
  98                    MANTIS_SBUF_WSTO   |
  99                    MANTIS_GPIF_EXTIRQ;
 100
 101        rst_stat  = mmread(MANTIS_GPIF_STATUS);
 102        rst_stat &= rst_mask;
 103        mmwrite(rst_stat, MANTIS_GPIF_STATUS);
 104
 105        mantis->mantis_int_stat = stat;
 106        mantis->mantis_int_mask = mask;
 107        dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
 108        if (stat & MANTIS_INT_RISCEN) {
 109                dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
 110        }
 111        if (stat & MANTIS_INT_IRQ0) {
 112                dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
 113                mantis->gpif_status = rst_stat;
 114                wake_up(&ca->hif_write_wq);
 115                schedule_work(&ca->hif_evm_work);
 116        }
 117        if (stat & MANTIS_INT_IRQ1) {
 118                dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
 119                spin_lock(&mantis->intmask_lock);
 120                mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ1,
 121                        MANTIS_INT_MASK);
 122                spin_unlock(&mantis->intmask_lock);
 123                schedule_work(&mantis->uart_work);
 124        }
 125        if (stat & MANTIS_INT_OCERR) {
 126                dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
 127        }
 128        if (stat & MANTIS_INT_PABORT) {
 129                dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
 130        }
 131        if (stat & MANTIS_INT_RIPERR) {
 132                dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
 133        }
 134        if (stat & MANTIS_INT_PPERR) {
 135                dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
 136        }
 137        if (stat & MANTIS_INT_FTRGT) {
 138                dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
 139        }
 140        if (stat & MANTIS_INT_RISCI) {
 141                dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
 142                mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
 143                tasklet_schedule(&mantis->tasklet);
 144        }
 145        if (stat & MANTIS_INT_I2CDONE) {
 146                dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
 147                wake_up(&mantis->i2c_wq);
 148        }
 149        mmwrite(stat, MANTIS_INT_STAT);
 150        stat &= ~(MANTIS_INT_RISCEN   | MANTIS_INT_I2CDONE |
 151                  MANTIS_INT_I2CRACK  | MANTIS_INT_PCMCIA7 |
 152                  MANTIS_INT_PCMCIA6  | MANTIS_INT_PCMCIA5 |
 153                  MANTIS_INT_PCMCIA4  | MANTIS_INT_PCMCIA3 |
 154                  MANTIS_INT_PCMCIA2  | MANTIS_INT_PCMCIA1 |
 155                  MANTIS_INT_PCMCIA0  | MANTIS_INT_IRQ1    |
 156                  MANTIS_INT_IRQ0     | MANTIS_INT_OCERR   |
 157                  MANTIS_INT_PABORT   | MANTIS_INT_RIPERR  |
 158                  MANTIS_INT_PPERR    | MANTIS_INT_FTRGT   |
 159                  MANTIS_INT_RISCI);
 160
 161        if (stat)
 162                dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
 163
 164        dprintk(MANTIS_DEBUG, 0, "\n");
 165        return IRQ_HANDLED;
 166}
 167
 168static int mantis_pci_probe(struct pci_dev *pdev,
 169                            const struct pci_device_id *pci_id)
 170{
 171        struct mantis_pci_drvdata *drvdata;
 172        struct mantis_pci *mantis;
 173        struct mantis_hwconfig *config;
 174        int err;
 175
 176        mantis = kzalloc(sizeof(*mantis), GFP_KERNEL);
 177        if (!mantis)
 178                return -ENOMEM;
 179
 180        drvdata                 = (void *)pci_id->driver_data;
 181        mantis->num             = devs;
 182        mantis->verbose         = verbose;
 183        mantis->pdev            = pdev;
 184        config                  = drvdata->hwconfig;
 185        config->irq_handler     = &mantis_irq_handler;
 186        mantis->hwconfig        = config;
 187        mantis->rc_map_name     = drvdata->rc_map_name;
 188
 189        spin_lock_init(&mantis->intmask_lock);
 190
 191        err = mantis_pci_init(mantis);
 192        if (err) {
 193                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
 194                goto err_free_mantis;
 195        }
 196
 197        err = mantis_stream_control(mantis, STREAM_TO_HIF);
 198        if (err < 0) {
 199                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
 200                goto err_pci_exit;
 201        }
 202
 203        err = mantis_i2c_init(mantis);
 204        if (err < 0) {
 205                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
 206                goto err_pci_exit;
 207        }
 208
 209        err = mantis_get_mac(mantis);
 210        if (err < 0) {
 211                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
 212                goto err_i2c_exit;
 213        }
 214
 215        err = mantis_dma_init(mantis);
 216        if (err < 0) {
 217                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
 218                goto err_i2c_exit;
 219        }
 220
 221        err = mantis_dvb_init(mantis);
 222        if (err < 0) {
 223                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
 224                goto err_dma_exit;
 225        }
 226
 227        err = mantis_input_init(mantis);
 228        if (err < 0) {
 229                dprintk(MANTIS_ERROR, 1,
 230                        "ERROR: Mantis DVB initialization failed <%d>", err);
 231                goto err_dvb_exit;
 232        }
 233
 234        err = mantis_uart_init(mantis);
 235        if (err < 0) {
 236                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err);
 237                goto err_input_exit;
 238        }
 239
 240        devs++;
 241
 242        return 0;
 243
 244err_input_exit:
 245        mantis_input_exit(mantis);
 246
 247err_dvb_exit:
 248        mantis_dvb_exit(mantis);
 249
 250err_dma_exit:
 251        mantis_dma_exit(mantis);
 252
 253err_i2c_exit:
 254        mantis_i2c_exit(mantis);
 255
 256err_pci_exit:
 257        mantis_pci_exit(mantis);
 258
 259err_free_mantis:
 260        kfree(mantis);
 261
 262        return err;
 263}
 264
 265static void mantis_pci_remove(struct pci_dev *pdev)
 266{
 267        struct mantis_pci *mantis = pci_get_drvdata(pdev);
 268
 269        if (mantis) {
 270
 271                mantis_uart_exit(mantis);
 272                mantis_input_exit(mantis);
 273                mantis_dvb_exit(mantis);
 274                mantis_dma_exit(mantis);
 275                mantis_i2c_exit(mantis);
 276                mantis_pci_exit(mantis);
 277                kfree(mantis);
 278        }
 279        return;
 280}
 281
 282static const struct pci_device_id mantis_pci_table[] = {
 283        MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config,
 284                   RC_MAP_TECHNISAT_TS35),
 285        MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config,
 286                   NULL),
 287        MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config,
 288                   NULL),
 289        MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2040_config,
 290                   RC_MAP_TERRATEC_CINERGY_C_PCI),
 291        MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config,
 292                   RC_MAP_TERRATEC_CINERGY_S2_HD),
 293        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config,
 294                   NULL),
 295        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config,
 296                   NULL),
 297        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config,
 298                   RC_MAP_TWINHAN_DTV_CAB_CI),
 299        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config,
 300                   RC_MAP_TWINHAN_DTV_CAB_CI),
 301        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config,
 302                   NULL),
 303        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config,
 304                   NULL),
 305        { }
 306};
 307
 308MODULE_DEVICE_TABLE(pci, mantis_pci_table);
 309
 310static struct pci_driver mantis_pci_driver = {
 311        .name           = DRIVER_NAME,
 312        .id_table       = mantis_pci_table,
 313        .probe          = mantis_pci_probe,
 314        .remove         = mantis_pci_remove,
 315};
 316
 317module_pci_driver(mantis_pci_driver);
 318
 319MODULE_DESCRIPTION("MANTIS driver");
 320MODULE_AUTHOR("Manu Abraham");
 321MODULE_LICENSE("GPL");
 322