linux/drivers/media/pci/mantis/mantis_core.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 "mantis_common.h"
  22#include "mantis_core.h"
  23#include "mantis_vp1033.h"
  24#include "mantis_vp1034.h"
  25#include "mantis_vp1041.h"
  26#include "mantis_vp2033.h"
  27#include "mantis_vp2040.h"
  28#include "mantis_vp3030.h"
  29
  30static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
  31{
  32        int err;
  33        struct i2c_msg msg[] = {
  34                {
  35                        .addr = 0x50,
  36                        .flags = 0,
  37                        .buf = data,
  38                        .len = 1
  39                }, {
  40                        .addr = 0x50,
  41                        .flags = I2C_M_RD,
  42                        .buf = data,
  43                        .len = length
  44                },
  45        };
  46
  47        err = i2c_transfer(&mantis->adapter, msg, 2);
  48        if (err < 0) {
  49                dprintk(verbose, MANTIS_ERROR, 1,
  50                        "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >",
  51                        err, data[0], data[1]);
  52
  53                return err;
  54        }
  55
  56        return 0;
  57}
  58
  59static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
  60{
  61        int err;
  62
  63        struct i2c_msg msg = {
  64                .addr = 0x50,
  65                .flags = 0,
  66                .buf = data,
  67                .len = length
  68        };
  69
  70        err = i2c_transfer(&mantis->adapter, &msg, 1);
  71        if (err < 0) {
  72                dprintk(verbose, MANTIS_ERROR, 1,
  73                        "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >",
  74                        err, length, data[0], data[1]);
  75
  76                return err;
  77        }
  78
  79        return 0;
  80}
  81
  82static int get_mac_address(struct mantis_pci *mantis)
  83{
  84        int err;
  85
  86        mantis->mac_address[0] = 0x08;
  87        err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6);
  88        if (err < 0) {
  89                dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error");
  90
  91                return err;
  92        }
  93        dprintk(verbose, MANTIS_ERROR, 0,
  94                "    MAC Address=[%pM]\n", mantis->mac_address);
  95
  96        return 0;
  97}
  98
  99#define MANTIS_MODEL_UNKNOWN    "UNKNOWN"
 100#define MANTIS_DEV_UNKNOWN      "UNKNOWN"
 101
 102struct mantis_hwconfig unknown_device = {
 103        .model_name     = MANTIS_MODEL_UNKNOWN,
 104        .dev_type       = MANTIS_DEV_UNKNOWN,
 105};
 106
 107static void mantis_load_config(struct mantis_pci *mantis)
 108{
 109        switch (mantis->subsystem_device) {
 110        case MANTIS_VP_1033_DVB_S:      /* VP-1033 */
 111                mantis->hwconfig = &vp1033_mantis_config;
 112                break;
 113        case MANTIS_VP_1034_DVB_S:      /* VP-1034 */
 114                mantis->hwconfig = &vp1034_mantis_config;
 115                break;
 116        case MANTIS_VP_1041_DVB_S2:     /* VP-1041 */
 117        case TECHNISAT_SKYSTAR_HD2:
 118                mantis->hwconfig = &vp1041_mantis_config;
 119                break;
 120        case MANTIS_VP_2033_DVB_C:      /* VP-2033 */
 121                mantis->hwconfig = &vp2033_mantis_config;
 122                break;
 123        case MANTIS_VP_2040_DVB_C:      /* VP-2040 */
 124        case CINERGY_C: /* VP-2040 clone */
 125        case TECHNISAT_CABLESTAR_HD2:
 126                mantis->hwconfig = &vp2040_mantis_config;
 127                break;
 128        case MANTIS_VP_3030_DVB_T:      /* VP-3030 */
 129                mantis->hwconfig = &vp3030_mantis_config;
 130                break;
 131        default:
 132                mantis->hwconfig = &unknown_device;
 133                break;
 134        }
 135}
 136
 137int mantis_core_init(struct mantis_pci *mantis)
 138{
 139        int err = 0;
 140
 141        mantis_load_config(mantis);
 142        dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n",
 143                mantis->hwconfig->model_name, mantis->hwconfig->dev_type,
 144                mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn));
 145        dprintk(verbose, MANTIS_ERROR, 0, "    Mantis Rev %d [%04x:%04x], ",
 146                mantis->revision,
 147                mantis->subsystem_vendor, mantis->subsystem_device);
 148        dprintk(verbose, MANTIS_ERROR, 0,
 149                "irq: %d, latency: %d\n    memory: 0x%lx, mmio: 0x%p\n",
 150                mantis->pdev->irq, mantis->latency,
 151                mantis->mantis_addr, mantis->mantis_mmio);
 152
 153        err = mantis_i2c_init(mantis);
 154        if (err < 0) {
 155                dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed");
 156                return err;
 157        }
 158        err = get_mac_address(mantis);
 159        if (err < 0) {
 160                dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed");
 161                return err;
 162        }
 163        err = mantis_dma_init(mantis);
 164        if (err < 0) {
 165                dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed");
 166                return err;
 167        }
 168        err = mantis_dvb_init(mantis);
 169        if (err < 0) {
 170                dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed");
 171                return err;
 172        }
 173        err = mantis_uart_init(mantis);
 174        if (err < 0) {
 175                dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed");
 176                return err;
 177        }
 178
 179        return 0;
 180}
 181
 182int mantis_core_exit(struct mantis_pci *mantis)
 183{
 184        mantis_dma_stop(mantis);
 185        dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping");
 186
 187        mantis_uart_exit(mantis);
 188        dprintk(verbose, MANTIS_ERROR, 1, "UART exit failed");
 189
 190        if (mantis_dma_exit(mantis) < 0)
 191                dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed");
 192        if (mantis_dvb_exit(mantis) < 0)
 193                dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed");
 194        if (mantis_i2c_exit(mantis) < 0)
 195                dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed");
 196
 197        return 0;
 198}
 199
 200/* Turn the given bit on or off. */
 201void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
 202{
 203        u32 cur;
 204
 205        cur = mmread(MANTIS_GPIF_ADDR);
 206        if (value)
 207                mantis->gpio_status = cur | (1 << bitpos);
 208        else
 209                mantis->gpio_status = cur & (~(1 << bitpos));
 210
 211        mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
 212        mmwrite(0x00, MANTIS_GPIF_DOUT);
 213        udelay(100);
 214}
 215
 216/* direction = 0 , no CI passthrough ; 1 , CI passthrough */
 217void mantis_set_direction(struct mantis_pci *mantis, int direction)
 218{
 219        u32 reg;
 220
 221        reg = mmread(0x28);
 222        dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup");
 223        if (direction == 0x01) {
 224                /* to CI */
 225                reg |= 0x04;
 226                mmwrite(reg, 0x28);
 227                reg &= 0xff - 0x04;
 228                mmwrite(reg, 0x28);
 229        } else {
 230                reg &= 0xff - 0x04;
 231                mmwrite(reg, 0x28);
 232                reg |= 0x04;
 233                mmwrite(reg, 0x28);
 234        }
 235}
 236