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 "dmxdev.h"
  31#include "dvbdev.h"
  32#include "dvb_demux.h"
  33#include "dvb_frontend.h"
  34#include "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 = 0;
 175
 176        mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
 177        if (mantis == NULL) {
 178                printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
 179                return -ENOMEM;
 180        }
 181
 182        drvdata                 = (void *)pci_id->driver_data;
 183        mantis->num             = devs;
 184        mantis->verbose         = verbose;
 185        mantis->pdev            = pdev;
 186        config                  = drvdata->hwconfig;
 187        config->irq_handler     = &mantis_irq_handler;
 188        mantis->hwconfig        = config;
 189        mantis->rc_map_name     = drvdata->rc_map_name;
 190
 191        spin_lock_init(&mantis->intmask_lock);
 192
 193        err = mantis_pci_init(mantis);
 194        if (err) {
 195                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
 196                goto err_free_mantis;
 197        }
 198
 199        err = mantis_stream_control(mantis, STREAM_TO_HIF);
 200        if (err < 0) {
 201                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
 202                goto err_pci_exit;
 203        }
 204
 205        err = mantis_i2c_init(mantis);
 206        if (err < 0) {
 207                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
 208                goto err_pci_exit;
 209        }
 210
 211        err = mantis_get_mac(mantis);
 212        if (err < 0) {
 213                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
 214                goto err_i2c_exit;
 215        }
 216
 217        err = mantis_dma_init(mantis);
 218        if (err < 0) {
 219                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
 220                goto err_i2c_exit;
 221        }
 222
 223        err = mantis_dvb_init(mantis);
 224        if (err < 0) {
 225                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
 226                goto err_dma_exit;
 227        }
 228
 229        err = mantis_input_init(mantis);
 230        if (err < 0) {
 231                dprintk(MANTIS_ERROR, 1,
 232                        "ERROR: Mantis DVB initialization failed <%d>", err);
 233                goto err_dvb_exit;
 234        }
 235
 236        err = mantis_uart_init(mantis);
 237        if (err < 0) {
 238                dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err);
 239                goto err_input_exit;
 240        }
 241
 242        devs++;
 243
 244        return 0;
 245
 246err_input_exit:
 247        mantis_input_exit(mantis);
 248
 249err_dvb_exit:
 250        mantis_dvb_exit(mantis);
 251
 252err_dma_exit:
 253        mantis_dma_exit(mantis);
 254
 255err_i2c_exit:
 256        mantis_i2c_exit(mantis);
 257
 258err_pci_exit:
 259        mantis_pci_exit(mantis);
 260
 261err_free_mantis:
 262        kfree(mantis);
 263
 264        return err;
 265}
 266
 267static void mantis_pci_remove(struct pci_dev *pdev)
 268{
 269        struct mantis_pci *mantis = pci_get_drvdata(pdev);
 270
 271        if (mantis) {
 272
 273                mantis_uart_exit(mantis);
 274                mantis_input_exit(mantis);
 275                mantis_dvb_exit(mantis);
 276                mantis_dma_exit(mantis);
 277                mantis_i2c_exit(mantis);
 278                mantis_pci_exit(mantis);
 279                kfree(mantis);
 280        }
 281        return;
 282}
 283
 284static struct pci_device_id mantis_pci_table[] = {
 285        MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config,
 286                   RC_MAP_TECHNISAT_TS35),
 287        MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config,
 288                   NULL),
 289        MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config,
 290                   NULL),
 291        MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2040_config,
 292                   RC_MAP_TERRATEC_CINERGY_C_PCI),
 293        MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config,
 294                   RC_MAP_TERRATEC_CINERGY_S2_HD),
 295        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config,
 296                   NULL),
 297        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config,
 298                   NULL),
 299        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config,
 300                   RC_MAP_TWINHAN_DTV_CAB_CI),
 301        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config,
 302                   RC_MAP_TWINHAN_DTV_CAB_CI),
 303        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config,
 304                   NULL),
 305        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config,
 306                   NULL),
 307        { }
 308};
 309
 310MODULE_DEVICE_TABLE(pci, mantis_pci_table);
 311
 312static struct pci_driver mantis_pci_driver = {
 313        .name           = DRIVER_NAME,
 314        .id_table       = mantis_pci_table,
 315        .probe          = mantis_pci_probe,
 316        .remove         = mantis_pci_remove,
 317};
 318
 319module_pci_driver(mantis_pci_driver);
 320
 321MODULE_DESCRIPTION("MANTIS driver");
 322MODULE_AUTHOR("Manu Abraham");
 323MODULE_LICENSE("GPL");
 324