1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2a611d0caSIgor M. Liplianin /* 3a611d0caSIgor M. Liplianin * dm1105.c - driver for DVB cards based on SDMC DM1105 PCI chip 4a611d0caSIgor M. Liplianin * 5a611d0caSIgor M. Liplianin * Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by> 6a611d0caSIgor M. Liplianin */ 7a611d0caSIgor M. Liplianin 8a611d0caSIgor M. Liplianin #include <linux/i2c.h> 90017505dSIgor M. Liplianin #include <linux/i2c-algo-bit.h> 10a611d0caSIgor M. Liplianin #include <linux/init.h> 11a6b7a407SAlexey Dobriyan #include <linux/interrupt.h> 12a611d0caSIgor M. Liplianin #include <linux/kernel.h> 13a611d0caSIgor M. Liplianin #include <linux/module.h> 14a611d0caSIgor M. Liplianin #include <linux/pci.h> 15a611d0caSIgor M. Liplianin #include <linux/dma-mapping.h> 165a0e3ad6STejun Heo #include <linux/slab.h> 176bda9644SMauro Carvalho Chehab #include <media/rc-core.h> 18a611d0caSIgor M. Liplianin 19fada1935SMauro Carvalho Chehab #include <media/demux.h> 20fada1935SMauro Carvalho Chehab #include <media/dmxdev.h> 21fada1935SMauro Carvalho Chehab #include <media/dvb_demux.h> 22fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h> 23fada1935SMauro Carvalho Chehab #include <media/dvb_net.h> 24fada1935SMauro Carvalho Chehab #include <media/dvbdev.h> 25a611d0caSIgor M. Liplianin #include "dvb-pll.h" 26a611d0caSIgor M. Liplianin 27a611d0caSIgor M. Liplianin #include "stv0299.h" 28e4aab64cSIgor M. Liplianin #include "stv0288.h" 29e4aab64cSIgor M. Liplianin #include "stb6000.h" 3004ad28c9SIgor M. Liplianin #include "si21xx.h" 3135d9c427SIgor M. Liplianin #include "cx24116.h" 32a611d0caSIgor M. Liplianin #include "z0194a.h" 3373f0af44SKonstantin Dimitrov #include "ts2020.h" 34b4a0e816SIgor M. Liplianin #include "ds3000.h" 35a611d0caSIgor M. Liplianin 36727e625cSMauro Carvalho Chehab #define MODULE_NAME "dm1105" 37727e625cSMauro Carvalho Chehab 38d8300df9SIgor M. Liplianin #define UNSET (-1U) 39d8300df9SIgor M. Liplianin 40d8300df9SIgor M. Liplianin #define DM1105_BOARD_NOAUTO UNSET 41d8300df9SIgor M. Liplianin #define DM1105_BOARD_UNKNOWN 0 42d8300df9SIgor M. Liplianin #define DM1105_BOARD_DVBWORLD_2002 1 43d8300df9SIgor M. Liplianin #define DM1105_BOARD_DVBWORLD_2004 2 44d8300df9SIgor M. Liplianin #define DM1105_BOARD_AXESS_DM05 3 450017505dSIgor M. Liplianin #define DM1105_BOARD_UNBRANDED_I2C_ON_GPIO 4 46d8300df9SIgor M. Liplianin 47a611d0caSIgor M. Liplianin /* ----------------------------------------------- */ 48a611d0caSIgor M. Liplianin /* 49a611d0caSIgor M. Liplianin * PCI ID's 50a611d0caSIgor M. Liplianin */ 51a611d0caSIgor M. Liplianin #ifndef PCI_VENDOR_ID_TRIGEM 52a611d0caSIgor M. Liplianin #define PCI_VENDOR_ID_TRIGEM 0x109f 53a611d0caSIgor M. Liplianin #endif 54519a4bdcSIgor M. Liplianin #ifndef PCI_VENDOR_ID_AXESS 55519a4bdcSIgor M. Liplianin #define PCI_VENDOR_ID_AXESS 0x195d 56519a4bdcSIgor M. Liplianin #endif 57a611d0caSIgor M. Liplianin #ifndef PCI_DEVICE_ID_DM1105 58a611d0caSIgor M. Liplianin #define PCI_DEVICE_ID_DM1105 0x036f 59a611d0caSIgor M. Liplianin #endif 60a611d0caSIgor M. Liplianin #ifndef PCI_DEVICE_ID_DW2002 61a611d0caSIgor M. Liplianin #define PCI_DEVICE_ID_DW2002 0x2002 62a611d0caSIgor M. Liplianin #endif 63a611d0caSIgor M. Liplianin #ifndef PCI_DEVICE_ID_DW2004 64a611d0caSIgor M. Liplianin #define PCI_DEVICE_ID_DW2004 0x2004 65a611d0caSIgor M. Liplianin #endif 66519a4bdcSIgor M. Liplianin #ifndef PCI_DEVICE_ID_DM05 67519a4bdcSIgor M. Liplianin #define PCI_DEVICE_ID_DM05 0x1105 68519a4bdcSIgor M. Liplianin #endif 69a611d0caSIgor M. Liplianin /* ----------------------------------------------- */ 70a611d0caSIgor M. Liplianin /* sdmc dm1105 registers */ 71a611d0caSIgor M. Liplianin 72a611d0caSIgor M. Liplianin /* TS Control */ 73a611d0caSIgor M. Liplianin #define DM1105_TSCTR 0x00 74a611d0caSIgor M. Liplianin #define DM1105_DTALENTH 0x04 75a611d0caSIgor M. Liplianin 76a611d0caSIgor M. Liplianin /* GPIO Interface */ 77a611d0caSIgor M. Liplianin #define DM1105_GPIOVAL 0x08 78a611d0caSIgor M. Liplianin #define DM1105_GPIOCTR 0x0c 79a611d0caSIgor M. Liplianin 80a611d0caSIgor M. Liplianin /* PID serial number */ 81a611d0caSIgor M. Liplianin #define DM1105_PIDN 0x10 82a611d0caSIgor M. Liplianin 83a611d0caSIgor M. Liplianin /* Odd-even secret key select */ 84a611d0caSIgor M. Liplianin #define DM1105_CWSEL 0x14 85a611d0caSIgor M. Liplianin 86a611d0caSIgor M. Liplianin /* Host Command Interface */ 87a611d0caSIgor M. Liplianin #define DM1105_HOST_CTR 0x18 88a611d0caSIgor M. Liplianin #define DM1105_HOST_AD 0x1c 89a611d0caSIgor M. Liplianin 90a611d0caSIgor M. Liplianin /* PCI Interface */ 91a611d0caSIgor M. Liplianin #define DM1105_CR 0x30 92a611d0caSIgor M. Liplianin #define DM1105_RST 0x34 93a611d0caSIgor M. Liplianin #define DM1105_STADR 0x38 94a611d0caSIgor M. Liplianin #define DM1105_RLEN 0x3c 95a611d0caSIgor M. Liplianin #define DM1105_WRP 0x40 96a611d0caSIgor M. Liplianin #define DM1105_INTCNT 0x44 97a611d0caSIgor M. Liplianin #define DM1105_INTMAK 0x48 98a611d0caSIgor M. Liplianin #define DM1105_INTSTS 0x4c 99a611d0caSIgor M. Liplianin 100a611d0caSIgor M. Liplianin /* CW Value */ 101a611d0caSIgor M. Liplianin #define DM1105_ODD 0x50 102a611d0caSIgor M. Liplianin #define DM1105_EVEN 0x58 103a611d0caSIgor M. Liplianin 104a611d0caSIgor M. Liplianin /* PID Value */ 105a611d0caSIgor M. Liplianin #define DM1105_PID 0x60 106a611d0caSIgor M. Liplianin 107a611d0caSIgor M. Liplianin /* IR Control */ 108a611d0caSIgor M. Liplianin #define DM1105_IRCTR 0x64 109a611d0caSIgor M. Liplianin #define DM1105_IRMODE 0x68 110a611d0caSIgor M. Liplianin #define DM1105_SYSTEMCODE 0x6c 111a611d0caSIgor M. Liplianin #define DM1105_IRCODE 0x70 112a611d0caSIgor M. Liplianin 113a611d0caSIgor M. Liplianin /* Unknown Values */ 114a611d0caSIgor M. Liplianin #define DM1105_ENCRYPT 0x74 115a611d0caSIgor M. Liplianin #define DM1105_VER 0x7c 116a611d0caSIgor M. Liplianin 117a611d0caSIgor M. Liplianin /* I2C Interface */ 118a611d0caSIgor M. Liplianin #define DM1105_I2CCTR 0x80 119a611d0caSIgor M. Liplianin #define DM1105_I2CSTS 0x81 120a611d0caSIgor M. Liplianin #define DM1105_I2CDAT 0x82 121a611d0caSIgor M. Liplianin #define DM1105_I2C_RA 0x83 122a611d0caSIgor M. Liplianin /* ----------------------------------------------- */ 123a611d0caSIgor M. Liplianin /* Interrupt Mask Bits */ 124a611d0caSIgor M. Liplianin 125a611d0caSIgor M. Liplianin #define INTMAK_TSIRQM 0x01 126a611d0caSIgor M. Liplianin #define INTMAK_HIRQM 0x04 127a611d0caSIgor M. Liplianin #define INTMAK_IRM 0x08 128a611d0caSIgor M. Liplianin #define INTMAK_ALLMASK (INTMAK_TSIRQM | \ 129a611d0caSIgor M. Liplianin INTMAK_HIRQM | \ 130a611d0caSIgor M. Liplianin INTMAK_IRM) 131a611d0caSIgor M. Liplianin #define INTMAK_NONEMASK 0x00 132a611d0caSIgor M. Liplianin 133a611d0caSIgor M. Liplianin /* Interrupt Status Bits */ 134a611d0caSIgor M. Liplianin #define INTSTS_TSIRQ 0x01 135a611d0caSIgor M. Liplianin #define INTSTS_HIRQ 0x04 136a611d0caSIgor M. Liplianin #define INTSTS_IR 0x08 137a611d0caSIgor M. Liplianin 138a611d0caSIgor M. Liplianin /* IR Control Bits */ 139a611d0caSIgor M. Liplianin #define DM1105_IR_EN 0x01 140a611d0caSIgor M. Liplianin #define DM1105_SYS_CHK 0x02 141a611d0caSIgor M. Liplianin #define DM1105_REP_FLG 0x08 142a611d0caSIgor M. Liplianin 143a611d0caSIgor M. Liplianin /* EEPROM addr */ 144a611d0caSIgor M. Liplianin #define IIC_24C01_addr 0xa0 145a611d0caSIgor M. Liplianin /* Max board count */ 146a611d0caSIgor M. Liplianin #define DM1105_MAX 0x04 147a611d0caSIgor M. Liplianin 148a611d0caSIgor M. Liplianin #define DRIVER_NAME "dm1105" 1490017505dSIgor M. Liplianin #define DM1105_I2C_GPIO_NAME "dm1105-gpio" 150a611d0caSIgor M. Liplianin 151a611d0caSIgor M. Liplianin #define DM1105_DMA_PACKETS 47 152a611d0caSIgor M. Liplianin #define DM1105_DMA_PACKET_LENGTH (128*4) 153a611d0caSIgor M. Liplianin #define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS) 154a611d0caSIgor M. Liplianin 1550017505dSIgor M. Liplianin /* */ 1560017505dSIgor M. Liplianin #define GPIO08 (1 << 8) 1570017505dSIgor M. Liplianin #define GPIO13 (1 << 13) 1580017505dSIgor M. Liplianin #define GPIO14 (1 << 14) 1590017505dSIgor M. Liplianin #define GPIO15 (1 << 15) 1600017505dSIgor M. Liplianin #define GPIO16 (1 << 16) 1610017505dSIgor M. Liplianin #define GPIO17 (1 << 17) 1620017505dSIgor M. Liplianin #define GPIO_ALL 0x03ffff 1630017505dSIgor M. Liplianin 164a611d0caSIgor M. Liplianin /* GPIO's for LNB power control */ 1650017505dSIgor M. Liplianin #define DM1105_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) 1660017505dSIgor M. Liplianin #define DM1105_LNB_OFF GPIO17 1670017505dSIgor M. Liplianin #define DM1105_LNB_13V (GPIO16 | GPIO08) 1680017505dSIgor M. Liplianin #define DM1105_LNB_18V GPIO08 169a611d0caSIgor M. Liplianin 170519a4bdcSIgor M. Liplianin /* GPIO's for LNB power control for Axess DM05 */ 1710017505dSIgor M. Liplianin #define DM05_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) 1720017505dSIgor M. Liplianin #define DM05_LNB_OFF GPIO17/* actually 13v */ 1730017505dSIgor M. Liplianin #define DM05_LNB_13V GPIO17 1740017505dSIgor M. Liplianin #define DM05_LNB_18V (GPIO17 | GPIO16) 1750017505dSIgor M. Liplianin 1760017505dSIgor M. Liplianin /* GPIO's for LNB power control for unbranded with I2C on GPIO */ 1770017505dSIgor M. Liplianin #define UNBR_LNB_MASK (GPIO17 | GPIO16) 1780017505dSIgor M. Liplianin #define UNBR_LNB_OFF 0 1790017505dSIgor M. Liplianin #define UNBR_LNB_13V GPIO17 1800017505dSIgor M. Liplianin #define UNBR_LNB_18V (GPIO17 | GPIO16) 181519a4bdcSIgor M. Liplianin 182d8300df9SIgor M. Liplianin static unsigned int card[] = {[0 ... 3] = UNSET }; 183d8300df9SIgor M. Liplianin module_param_array(card, int, NULL, 0444); 184d8300df9SIgor M. Liplianin MODULE_PARM_DESC(card, "card type"); 185d8300df9SIgor M. Liplianin 186a611d0caSIgor M. Liplianin static int ir_debug; 187a611d0caSIgor M. Liplianin module_param(ir_debug, int, 0644); 188a611d0caSIgor M. Liplianin MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); 189a611d0caSIgor M. Liplianin 190d8300df9SIgor M. Liplianin static unsigned int dm1105_devcount; 191d8300df9SIgor M. Liplianin 192a611d0caSIgor M. Liplianin DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 193a611d0caSIgor M. Liplianin 194d8300df9SIgor M. Liplianin struct dm1105_board { 195d8300df9SIgor M. Liplianin char *name; 1960017505dSIgor M. Liplianin struct { 1970017505dSIgor M. Liplianin u32 mask, off, v13, v18; 1980017505dSIgor M. Liplianin } lnb; 1990017505dSIgor M. Liplianin u32 gpio_scl, gpio_sda; 200d8300df9SIgor M. Liplianin }; 201d8300df9SIgor M. Liplianin 202d8300df9SIgor M. Liplianin struct dm1105_subid { 203d8300df9SIgor M. Liplianin u16 subvendor; 204d8300df9SIgor M. Liplianin u16 subdevice; 205d8300df9SIgor M. Liplianin u32 card; 206d8300df9SIgor M. Liplianin }; 207d8300df9SIgor M. Liplianin 208d8300df9SIgor M. Liplianin static const struct dm1105_board dm1105_boards[] = { 209d8300df9SIgor M. Liplianin [DM1105_BOARD_UNKNOWN] = { 210d8300df9SIgor M. Liplianin .name = "UNKNOWN/GENERIC", 2110017505dSIgor M. Liplianin .lnb = { 2120017505dSIgor M. Liplianin .mask = DM1105_LNB_MASK, 2130017505dSIgor M. Liplianin .off = DM1105_LNB_OFF, 2140017505dSIgor M. Liplianin .v13 = DM1105_LNB_13V, 2150017505dSIgor M. Liplianin .v18 = DM1105_LNB_18V, 2160017505dSIgor M. Liplianin }, 217d8300df9SIgor M. Liplianin }, 218d8300df9SIgor M. Liplianin [DM1105_BOARD_DVBWORLD_2002] = { 219d8300df9SIgor M. Liplianin .name = "DVBWorld PCI 2002", 2200017505dSIgor M. Liplianin .lnb = { 2210017505dSIgor M. Liplianin .mask = DM1105_LNB_MASK, 2220017505dSIgor M. Liplianin .off = DM1105_LNB_OFF, 2230017505dSIgor M. Liplianin .v13 = DM1105_LNB_13V, 2240017505dSIgor M. Liplianin .v18 = DM1105_LNB_18V, 2250017505dSIgor M. Liplianin }, 226d8300df9SIgor M. Liplianin }, 227d8300df9SIgor M. Liplianin [DM1105_BOARD_DVBWORLD_2004] = { 228d8300df9SIgor M. Liplianin .name = "DVBWorld PCI 2004", 2290017505dSIgor M. Liplianin .lnb = { 2300017505dSIgor M. Liplianin .mask = DM1105_LNB_MASK, 2310017505dSIgor M. Liplianin .off = DM1105_LNB_OFF, 2320017505dSIgor M. Liplianin .v13 = DM1105_LNB_13V, 2330017505dSIgor M. Liplianin .v18 = DM1105_LNB_18V, 2340017505dSIgor M. Liplianin }, 235d8300df9SIgor M. Liplianin }, 236d8300df9SIgor M. Liplianin [DM1105_BOARD_AXESS_DM05] = { 237d8300df9SIgor M. Liplianin .name = "Axess/EasyTv DM05", 2380017505dSIgor M. Liplianin .lnb = { 2390017505dSIgor M. Liplianin .mask = DM05_LNB_MASK, 2400017505dSIgor M. Liplianin .off = DM05_LNB_OFF, 2410017505dSIgor M. Liplianin .v13 = DM05_LNB_13V, 2420017505dSIgor M. Liplianin .v18 = DM05_LNB_18V, 2430017505dSIgor M. Liplianin }, 2440017505dSIgor M. Liplianin }, 2450017505dSIgor M. Liplianin [DM1105_BOARD_UNBRANDED_I2C_ON_GPIO] = { 2460017505dSIgor M. Liplianin .name = "Unbranded DM1105 with i2c on GPIOs", 2470017505dSIgor M. Liplianin .lnb = { 2480017505dSIgor M. Liplianin .mask = UNBR_LNB_MASK, 2490017505dSIgor M. Liplianin .off = UNBR_LNB_OFF, 2500017505dSIgor M. Liplianin .v13 = UNBR_LNB_13V, 2510017505dSIgor M. Liplianin .v18 = UNBR_LNB_18V, 2520017505dSIgor M. Liplianin }, 2530017505dSIgor M. Liplianin .gpio_scl = GPIO14, 2540017505dSIgor M. Liplianin .gpio_sda = GPIO13, 255d8300df9SIgor M. Liplianin }, 256d8300df9SIgor M. Liplianin }; 257d8300df9SIgor M. Liplianin 258d8300df9SIgor M. Liplianin static const struct dm1105_subid dm1105_subids[] = { 259d8300df9SIgor M. Liplianin { 260d8300df9SIgor M. Liplianin .subvendor = 0x0000, 261d8300df9SIgor M. Liplianin .subdevice = 0x2002, 262d8300df9SIgor M. Liplianin .card = DM1105_BOARD_DVBWORLD_2002, 263d8300df9SIgor M. Liplianin }, { 264d8300df9SIgor M. Liplianin .subvendor = 0x0001, 265d8300df9SIgor M. Liplianin .subdevice = 0x2002, 266d8300df9SIgor M. Liplianin .card = DM1105_BOARD_DVBWORLD_2002, 267d8300df9SIgor M. Liplianin }, { 268d8300df9SIgor M. Liplianin .subvendor = 0x0000, 269d8300df9SIgor M. Liplianin .subdevice = 0x2004, 270d8300df9SIgor M. Liplianin .card = DM1105_BOARD_DVBWORLD_2004, 271d8300df9SIgor M. Liplianin }, { 272d8300df9SIgor M. Liplianin .subvendor = 0x0001, 273d8300df9SIgor M. Liplianin .subdevice = 0x2004, 274d8300df9SIgor M. Liplianin .card = DM1105_BOARD_DVBWORLD_2004, 275d8300df9SIgor M. Liplianin }, { 276d8300df9SIgor M. Liplianin .subvendor = 0x195d, 277d8300df9SIgor M. Liplianin .subdevice = 0x1105, 278d8300df9SIgor M. Liplianin .card = DM1105_BOARD_AXESS_DM05, 279d8300df9SIgor M. Liplianin }, 280d8300df9SIgor M. Liplianin }; 281d8300df9SIgor M. Liplianin 282d8300df9SIgor M. Liplianin static void dm1105_card_list(struct pci_dev *pci) 283d8300df9SIgor M. Liplianin { 284d8300df9SIgor M. Liplianin int i; 285d8300df9SIgor M. Liplianin 286d8300df9SIgor M. Liplianin if (0 == pci->subsystem_vendor && 287d8300df9SIgor M. Liplianin 0 == pci->subsystem_device) { 288d8300df9SIgor M. Liplianin printk(KERN_ERR 289d8300df9SIgor M. Liplianin "dm1105: Your board has no valid PCI Subsystem ID\n" 290d8300df9SIgor M. Liplianin "dm1105: and thus can't be autodetected\n" 291d8300df9SIgor M. Liplianin "dm1105: Please pass card=<n> insmod option to\n" 292d8300df9SIgor M. Liplianin "dm1105: workaround that. Redirect complaints to\n" 293d8300df9SIgor M. Liplianin "dm1105: the vendor of the TV card. Best regards,\n" 294d8300df9SIgor M. Liplianin "dm1105: -- tux\n"); 295d8300df9SIgor M. Liplianin } else { 296d8300df9SIgor M. Liplianin printk(KERN_ERR 297d8300df9SIgor M. Liplianin "dm1105: Your board isn't known (yet) to the driver.\n" 298d8300df9SIgor M. Liplianin "dm1105: You can try to pick one of the existing\n" 299d8300df9SIgor M. Liplianin "dm1105: card configs via card=<n> insmod option.\n" 300d8300df9SIgor M. Liplianin "dm1105: Updating to the latest version might help\n" 301d8300df9SIgor M. Liplianin "dm1105: as well.\n"); 302d8300df9SIgor M. Liplianin } 3030e8aebb5SMauro Carvalho Chehab printk(KERN_ERR "Here is a list of valid choices for the card=<n> insmod option:\n"); 304d8300df9SIgor M. Liplianin for (i = 0; i < ARRAY_SIZE(dm1105_boards); i++) 305d8300df9SIgor M. Liplianin printk(KERN_ERR "dm1105: card=%d -> %s\n", 306d8300df9SIgor M. Liplianin i, dm1105_boards[i].name); 307d8300df9SIgor M. Liplianin } 308d8300df9SIgor M. Liplianin 309a611d0caSIgor M. Liplianin /* infrared remote control */ 310a611d0caSIgor M. Liplianin struct infrared { 311d8b4b582SDavid Härdeman struct rc_dev *dev; 312a611d0caSIgor M. Liplianin char input_phys[32]; 313b72857ddSIgor M. Liplianin struct work_struct work; 314a611d0caSIgor M. Liplianin u32 ir_command; 315a611d0caSIgor M. Liplianin }; 316a611d0caSIgor M. Liplianin 31734d2f9bfSIgor M. Liplianin struct dm1105_dev { 318a611d0caSIgor M. Liplianin /* pci */ 319a611d0caSIgor M. Liplianin struct pci_dev *pdev; 320a611d0caSIgor M. Liplianin u8 __iomem *io_mem; 321a611d0caSIgor M. Liplianin 322a611d0caSIgor M. Liplianin /* ir */ 323a611d0caSIgor M. Liplianin struct infrared ir; 324a611d0caSIgor M. Liplianin 325a611d0caSIgor M. Liplianin /* dvb */ 326a611d0caSIgor M. Liplianin struct dmx_frontend hw_frontend; 327a611d0caSIgor M. Liplianin struct dmx_frontend mem_frontend; 328a611d0caSIgor M. Liplianin struct dmxdev dmxdev; 329a611d0caSIgor M. Liplianin struct dvb_adapter dvb_adapter; 330a611d0caSIgor M. Liplianin struct dvb_demux demux; 331a611d0caSIgor M. Liplianin struct dvb_frontend *fe; 332a611d0caSIgor M. Liplianin struct dvb_net dvbnet; 333a611d0caSIgor M. Liplianin unsigned int full_ts_users; 334d8300df9SIgor M. Liplianin unsigned int boardnr; 335d8300df9SIgor M. Liplianin int nr; 336a611d0caSIgor M. Liplianin 337a611d0caSIgor M. Liplianin /* i2c */ 338a611d0caSIgor M. Liplianin struct i2c_adapter i2c_adap; 3390017505dSIgor M. Liplianin struct i2c_adapter i2c_bb_adap; 3400017505dSIgor M. Liplianin struct i2c_algo_bit_data i2c_bit; 341a611d0caSIgor M. Liplianin 342d1498ffcSIgor M. Liplianin /* irq */ 343d1498ffcSIgor M. Liplianin struct work_struct work; 344519a4bdcSIgor M. Liplianin struct workqueue_struct *wq; 345519a4bdcSIgor M. Liplianin char wqn[16]; 346d1498ffcSIgor M. Liplianin 347a611d0caSIgor M. Liplianin /* dma */ 348a611d0caSIgor M. Liplianin dma_addr_t dma_addr; 349a611d0caSIgor M. Liplianin unsigned char *ts_buf; 350a611d0caSIgor M. Liplianin u32 wrp; 351d1498ffcSIgor M. Liplianin u32 nextwrp; 352a611d0caSIgor M. Liplianin u32 buffer_size; 353a611d0caSIgor M. Liplianin unsigned int PacketErrorCount; 354a611d0caSIgor M. Liplianin unsigned int dmarst; 355a611d0caSIgor M. Liplianin spinlock_t lock; 356a611d0caSIgor M. Liplianin }; 357a611d0caSIgor M. Liplianin 35834d2f9bfSIgor M. Liplianin #define dm_io_mem(reg) ((unsigned long)(&dev->io_mem[reg])) 359a611d0caSIgor M. Liplianin 3605eb3291fSIgor M. Liplianin #define dm_readb(reg) inb(dm_io_mem(reg)) 3615eb3291fSIgor M. Liplianin #define dm_writeb(reg, value) outb((value), (dm_io_mem(reg))) 3625eb3291fSIgor M. Liplianin 3635eb3291fSIgor M. Liplianin #define dm_readw(reg) inw(dm_io_mem(reg)) 3645eb3291fSIgor M. Liplianin #define dm_writew(reg, value) outw((value), (dm_io_mem(reg))) 3655eb3291fSIgor M. Liplianin 3665eb3291fSIgor M. Liplianin #define dm_readl(reg) inl(dm_io_mem(reg)) 3675eb3291fSIgor M. Liplianin #define dm_writel(reg, value) outl((value), (dm_io_mem(reg))) 3685eb3291fSIgor M. Liplianin 3695eb3291fSIgor M. Liplianin #define dm_andorl(reg, mask, value) \ 3705eb3291fSIgor M. Liplianin outl((inl(dm_io_mem(reg)) & ~(mask)) |\ 3715eb3291fSIgor M. Liplianin ((value) & (mask)), (dm_io_mem(reg))) 3725eb3291fSIgor M. Liplianin 3735eb3291fSIgor M. Liplianin #define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit)) 3745eb3291fSIgor M. Liplianin #define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0) 3755eb3291fSIgor M. Liplianin 3760017505dSIgor M. Liplianin /* The chip has 18 GPIOs. In HOST mode GPIO's used as 15 bit address lines, 3770017505dSIgor M. Liplianin so we can use only 3 GPIO's from GPIO15 to GPIO17. 3780017505dSIgor M. Liplianin Here I don't check whether HOST is enebled as it is not implemented yet. 3790017505dSIgor M. Liplianin */ 3800017505dSIgor M. Liplianin static void dm1105_gpio_set(struct dm1105_dev *dev, u32 mask) 3810017505dSIgor M. Liplianin { 3820017505dSIgor M. Liplianin if (mask & 0xfffc0000) 3830017505dSIgor M. Liplianin printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 3840017505dSIgor M. Liplianin 3850017505dSIgor M. Liplianin if (mask & 0x0003ffff) 3860017505dSIgor M. Liplianin dm_setl(DM1105_GPIOVAL, mask & 0x0003ffff); 3870017505dSIgor M. Liplianin 3880017505dSIgor M. Liplianin } 3890017505dSIgor M. Liplianin 3900017505dSIgor M. Liplianin static void dm1105_gpio_clear(struct dm1105_dev *dev, u32 mask) 3910017505dSIgor M. Liplianin { 3920017505dSIgor M. Liplianin if (mask & 0xfffc0000) 3930017505dSIgor M. Liplianin printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 3940017505dSIgor M. Liplianin 3950017505dSIgor M. Liplianin if (mask & 0x0003ffff) 3960017505dSIgor M. Liplianin dm_clearl(DM1105_GPIOVAL, mask & 0x0003ffff); 3970017505dSIgor M. Liplianin 3980017505dSIgor M. Liplianin } 3990017505dSIgor M. Liplianin 4000017505dSIgor M. Liplianin static void dm1105_gpio_andor(struct dm1105_dev *dev, u32 mask, u32 val) 4010017505dSIgor M. Liplianin { 4020017505dSIgor M. Liplianin if (mask & 0xfffc0000) 4030017505dSIgor M. Liplianin printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 4040017505dSIgor M. Liplianin 4050017505dSIgor M. Liplianin if (mask & 0x0003ffff) 4060017505dSIgor M. Liplianin dm_andorl(DM1105_GPIOVAL, mask & 0x0003ffff, val); 4070017505dSIgor M. Liplianin 4080017505dSIgor M. Liplianin } 4090017505dSIgor M. Liplianin 4100017505dSIgor M. Liplianin static u32 dm1105_gpio_get(struct dm1105_dev *dev, u32 mask) 4110017505dSIgor M. Liplianin { 4120017505dSIgor M. Liplianin if (mask & 0xfffc0000) 4130017505dSIgor M. Liplianin printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 4140017505dSIgor M. Liplianin 4150017505dSIgor M. Liplianin if (mask & 0x0003ffff) 4160017505dSIgor M. Liplianin return dm_readl(DM1105_GPIOVAL) & mask & 0x0003ffff; 4170017505dSIgor M. Liplianin 4180017505dSIgor M. Liplianin return 0; 4190017505dSIgor M. Liplianin } 4200017505dSIgor M. Liplianin 4210017505dSIgor M. Liplianin static void dm1105_gpio_enable(struct dm1105_dev *dev, u32 mask, int asoutput) 4220017505dSIgor M. Liplianin { 4230017505dSIgor M. Liplianin if (mask & 0xfffc0000) 4240017505dSIgor M. Liplianin printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); 4250017505dSIgor M. Liplianin 4260017505dSIgor M. Liplianin if ((mask & 0x0003ffff) && asoutput) 4270017505dSIgor M. Liplianin dm_clearl(DM1105_GPIOCTR, mask & 0x0003ffff); 4280017505dSIgor M. Liplianin else if ((mask & 0x0003ffff) && !asoutput) 4290017505dSIgor M. Liplianin dm_setl(DM1105_GPIOCTR, mask & 0x0003ffff); 4300017505dSIgor M. Liplianin 4310017505dSIgor M. Liplianin } 4320017505dSIgor M. Liplianin 4330017505dSIgor M. Liplianin static void dm1105_setline(struct dm1105_dev *dev, u32 line, int state) 4340017505dSIgor M. Liplianin { 4350017505dSIgor M. Liplianin if (state) 4360017505dSIgor M. Liplianin dm1105_gpio_enable(dev, line, 0); 4370017505dSIgor M. Liplianin else { 4380017505dSIgor M. Liplianin dm1105_gpio_enable(dev, line, 1); 4390017505dSIgor M. Liplianin dm1105_gpio_clear(dev, line); 4400017505dSIgor M. Liplianin } 4410017505dSIgor M. Liplianin } 4420017505dSIgor M. Liplianin 4430017505dSIgor M. Liplianin static void dm1105_setsda(void *data, int state) 4440017505dSIgor M. Liplianin { 4450017505dSIgor M. Liplianin struct dm1105_dev *dev = data; 4460017505dSIgor M. Liplianin 4470017505dSIgor M. Liplianin dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_sda, state); 4480017505dSIgor M. Liplianin } 4490017505dSIgor M. Liplianin 4500017505dSIgor M. Liplianin static void dm1105_setscl(void *data, int state) 4510017505dSIgor M. Liplianin { 4520017505dSIgor M. Liplianin struct dm1105_dev *dev = data; 4530017505dSIgor M. Liplianin 4540017505dSIgor M. Liplianin dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_scl, state); 4550017505dSIgor M. Liplianin } 4560017505dSIgor M. Liplianin 4570017505dSIgor M. Liplianin static int dm1105_getsda(void *data) 4580017505dSIgor M. Liplianin { 4590017505dSIgor M. Liplianin struct dm1105_dev *dev = data; 4600017505dSIgor M. Liplianin 4610017505dSIgor M. Liplianin return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_sda) 4620017505dSIgor M. Liplianin ? 1 : 0; 4630017505dSIgor M. Liplianin } 4640017505dSIgor M. Liplianin 4650017505dSIgor M. Liplianin static int dm1105_getscl(void *data) 4660017505dSIgor M. Liplianin { 4670017505dSIgor M. Liplianin struct dm1105_dev *dev = data; 4680017505dSIgor M. Liplianin 4690017505dSIgor M. Liplianin return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_scl) 4700017505dSIgor M. Liplianin ? 1 : 0; 4710017505dSIgor M. Liplianin } 4720017505dSIgor M. Liplianin 473a611d0caSIgor M. Liplianin static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, 474a611d0caSIgor M. Liplianin struct i2c_msg *msgs, int num) 475a611d0caSIgor M. Liplianin { 47634d2f9bfSIgor M. Liplianin struct dm1105_dev *dev ; 477a611d0caSIgor M. Liplianin 478a611d0caSIgor M. Liplianin int addr, rc, i, j, k, len, byte, data; 479a611d0caSIgor M. Liplianin u8 status; 480a611d0caSIgor M. Liplianin 48134d2f9bfSIgor M. Liplianin dev = i2c_adap->algo_data; 482a611d0caSIgor M. Liplianin for (i = 0; i < num; i++) { 4835eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CCTR, 0x00); 484a611d0caSIgor M. Liplianin if (msgs[i].flags & I2C_M_RD) { 485a611d0caSIgor M. Liplianin /* read bytes */ 486a611d0caSIgor M. Liplianin addr = msgs[i].addr << 1; 487a611d0caSIgor M. Liplianin addr |= 1; 4885eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CDAT, addr); 489a611d0caSIgor M. Liplianin for (byte = 0; byte < msgs[i].len; byte++) 4905eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CDAT + byte + 1, 0); 491a611d0caSIgor M. Liplianin 4925eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len); 493a611d0caSIgor M. Liplianin for (j = 0; j < 55; j++) { 494a611d0caSIgor M. Liplianin mdelay(10); 4955eb3291fSIgor M. Liplianin status = dm_readb(DM1105_I2CSTS); 496a611d0caSIgor M. Liplianin if ((status & 0xc0) == 0x40) 497a611d0caSIgor M. Liplianin break; 498a611d0caSIgor M. Liplianin } 499a611d0caSIgor M. Liplianin if (j >= 55) 500a611d0caSIgor M. Liplianin return -1; 501a611d0caSIgor M. Liplianin 502a611d0caSIgor M. Liplianin for (byte = 0; byte < msgs[i].len; byte++) { 5035eb3291fSIgor M. Liplianin rc = dm_readb(DM1105_I2CDAT + byte + 1); 504a611d0caSIgor M. Liplianin if (rc < 0) 505a611d0caSIgor M. Liplianin goto err; 506a611d0caSIgor M. Liplianin msgs[i].buf[byte] = rc; 507a611d0caSIgor M. Liplianin } 508ed7c847aSIgor M. Liplianin } else if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) { 50916790554SMauro Carvalho Chehab /* prepared for cx24116 firmware */ 510a611d0caSIgor M. Liplianin /* Write in small blocks */ 511a611d0caSIgor M. Liplianin len = msgs[i].len - 1; 512a611d0caSIgor M. Liplianin k = 1; 513a611d0caSIgor M. Liplianin do { 5145eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1); 5155eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CDAT + 1, 0xf7); 516a611d0caSIgor M. Liplianin for (byte = 0; byte < (len > 48 ? 48 : len); byte++) { 517a611d0caSIgor M. Liplianin data = msgs[i].buf[k + byte]; 5185eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CDAT + byte + 2, data); 519a611d0caSIgor M. Liplianin } 5205eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CCTR, 0x82 + (len > 48 ? 48 : len)); 521a611d0caSIgor M. Liplianin for (j = 0; j < 25; j++) { 522a611d0caSIgor M. Liplianin mdelay(10); 5235eb3291fSIgor M. Liplianin status = dm_readb(DM1105_I2CSTS); 524a611d0caSIgor M. Liplianin if ((status & 0xc0) == 0x40) 525a611d0caSIgor M. Liplianin break; 526a611d0caSIgor M. Liplianin } 527a611d0caSIgor M. Liplianin 528a611d0caSIgor M. Liplianin if (j >= 25) 529a611d0caSIgor M. Liplianin return -1; 530a611d0caSIgor M. Liplianin 531a611d0caSIgor M. Liplianin k += 48; 532a611d0caSIgor M. Liplianin len -= 48; 533a611d0caSIgor M. Liplianin } while (len > 0); 534a611d0caSIgor M. Liplianin } else { 535a611d0caSIgor M. Liplianin /* write bytes */ 5365eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1); 537a611d0caSIgor M. Liplianin for (byte = 0; byte < msgs[i].len; byte++) { 538a611d0caSIgor M. Liplianin data = msgs[i].buf[byte]; 5395eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CDAT + byte + 1, data); 540a611d0caSIgor M. Liplianin } 5415eb3291fSIgor M. Liplianin dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len); 542a611d0caSIgor M. Liplianin for (j = 0; j < 25; j++) { 543a611d0caSIgor M. Liplianin mdelay(10); 5445eb3291fSIgor M. Liplianin status = dm_readb(DM1105_I2CSTS); 545a611d0caSIgor M. Liplianin if ((status & 0xc0) == 0x40) 546a611d0caSIgor M. Liplianin break; 547a611d0caSIgor M. Liplianin } 548a611d0caSIgor M. Liplianin 549a611d0caSIgor M. Liplianin if (j >= 25) 550a611d0caSIgor M. Liplianin return -1; 551a611d0caSIgor M. Liplianin } 552a611d0caSIgor M. Liplianin } 553a611d0caSIgor M. Liplianin return num; 554a611d0caSIgor M. Liplianin err: 555a611d0caSIgor M. Liplianin return rc; 556a611d0caSIgor M. Liplianin } 557a611d0caSIgor M. Liplianin 558a611d0caSIgor M. Liplianin static u32 functionality(struct i2c_adapter *adap) 559a611d0caSIgor M. Liplianin { 560a611d0caSIgor M. Liplianin return I2C_FUNC_I2C; 561a611d0caSIgor M. Liplianin } 562a611d0caSIgor M. Liplianin 5633c13978eSGustavo A. R. Silva static const struct i2c_algorithm dm1105_algo = { 564a611d0caSIgor M. Liplianin .master_xfer = dm1105_i2c_xfer, 565a611d0caSIgor M. Liplianin .functionality = functionality, 566a611d0caSIgor M. Liplianin }; 567a611d0caSIgor M. Liplianin 56834d2f9bfSIgor M. Liplianin static inline struct dm1105_dev *feed_to_dm1105_dev(struct dvb_demux_feed *feed) 569a611d0caSIgor M. Liplianin { 57034d2f9bfSIgor M. Liplianin return container_of(feed->demux, struct dm1105_dev, demux); 571a611d0caSIgor M. Liplianin } 572a611d0caSIgor M. Liplianin 57334d2f9bfSIgor M. Liplianin static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe) 574a611d0caSIgor M. Liplianin { 57534d2f9bfSIgor M. Liplianin return container_of(fe->dvb, struct dm1105_dev, dvb_adapter); 576a611d0caSIgor M. Liplianin } 577a611d0caSIgor M. Liplianin 5780df289a2SMauro Carvalho Chehab static int dm1105_set_voltage(struct dvb_frontend *fe, 5790df289a2SMauro Carvalho Chehab enum fe_sec_voltage voltage) 580a611d0caSIgor M. Liplianin { 58134d2f9bfSIgor M. Liplianin struct dm1105_dev *dev = frontend_to_dm1105_dev(fe); 582a611d0caSIgor M. Liplianin 5830017505dSIgor M. Liplianin dm1105_gpio_enable(dev, dm1105_boards[dev->boardnr].lnb.mask, 1); 584519a4bdcSIgor M. Liplianin if (voltage == SEC_VOLTAGE_18) 5850017505dSIgor M. Liplianin dm1105_gpio_andor(dev, 5860017505dSIgor M. Liplianin dm1105_boards[dev->boardnr].lnb.mask, 5870017505dSIgor M. Liplianin dm1105_boards[dev->boardnr].lnb.v18); 588d8300df9SIgor M. Liplianin else if (voltage == SEC_VOLTAGE_13) 5890017505dSIgor M. Liplianin dm1105_gpio_andor(dev, 5900017505dSIgor M. Liplianin dm1105_boards[dev->boardnr].lnb.mask, 5910017505dSIgor M. Liplianin dm1105_boards[dev->boardnr].lnb.v13); 592d8300df9SIgor M. Liplianin else 5930017505dSIgor M. Liplianin dm1105_gpio_andor(dev, 5940017505dSIgor M. Liplianin dm1105_boards[dev->boardnr].lnb.mask, 5950017505dSIgor M. Liplianin dm1105_boards[dev->boardnr].lnb.off); 596519a4bdcSIgor M. Liplianin 597a611d0caSIgor M. Liplianin return 0; 598a611d0caSIgor M. Liplianin } 599a611d0caSIgor M. Liplianin 60034d2f9bfSIgor M. Liplianin static void dm1105_set_dma_addr(struct dm1105_dev *dev) 601a611d0caSIgor M. Liplianin { 602888bd5dcSHans Verkuil dm_writel(DM1105_STADR, (__force u32)cpu_to_le32(dev->dma_addr)); 603a611d0caSIgor M. Liplianin } 604a611d0caSIgor M. Liplianin 6054c62e976SGreg Kroah-Hartman static int dm1105_dma_map(struct dm1105_dev *dev) 606a611d0caSIgor M. Liplianin { 607*acc4c91eSChristophe JAILLET dev->ts_buf = dma_alloc_coherent(&dev->pdev->dev, 608*acc4c91eSChristophe JAILLET 6 * DM1105_DMA_BYTES, &dev->dma_addr, 609*acc4c91eSChristophe JAILLET GFP_KERNEL); 610a611d0caSIgor M. Liplianin 61134d2f9bfSIgor M. Liplianin return !dev->ts_buf; 612a611d0caSIgor M. Liplianin } 613a611d0caSIgor M. Liplianin 61434d2f9bfSIgor M. Liplianin static void dm1105_dma_unmap(struct dm1105_dev *dev) 615a611d0caSIgor M. Liplianin { 616*acc4c91eSChristophe JAILLET dma_free_coherent(&dev->pdev->dev, 6 * DM1105_DMA_BYTES, dev->ts_buf, 61734d2f9bfSIgor M. Liplianin dev->dma_addr); 618a611d0caSIgor M. Liplianin } 619a611d0caSIgor M. Liplianin 62034d2f9bfSIgor M. Liplianin static void dm1105_enable_irqs(struct dm1105_dev *dev) 621a611d0caSIgor M. Liplianin { 6225eb3291fSIgor M. Liplianin dm_writeb(DM1105_INTMAK, INTMAK_ALLMASK); 6235eb3291fSIgor M. Liplianin dm_writeb(DM1105_CR, 1); 624a611d0caSIgor M. Liplianin } 625a611d0caSIgor M. Liplianin 62634d2f9bfSIgor M. Liplianin static void dm1105_disable_irqs(struct dm1105_dev *dev) 627a611d0caSIgor M. Liplianin { 6285eb3291fSIgor M. Liplianin dm_writeb(DM1105_INTMAK, INTMAK_IRM); 6295eb3291fSIgor M. Liplianin dm_writeb(DM1105_CR, 0); 630a611d0caSIgor M. Liplianin } 631a611d0caSIgor M. Liplianin 63234d2f9bfSIgor M. Liplianin static int dm1105_start_feed(struct dvb_demux_feed *f) 633a611d0caSIgor M. Liplianin { 63434d2f9bfSIgor M. Liplianin struct dm1105_dev *dev = feed_to_dm1105_dev(f); 635a611d0caSIgor M. Liplianin 63634d2f9bfSIgor M. Liplianin if (dev->full_ts_users++ == 0) 63734d2f9bfSIgor M. Liplianin dm1105_enable_irqs(dev); 638a611d0caSIgor M. Liplianin 639a611d0caSIgor M. Liplianin return 0; 640a611d0caSIgor M. Liplianin } 641a611d0caSIgor M. Liplianin 64234d2f9bfSIgor M. Liplianin static int dm1105_stop_feed(struct dvb_demux_feed *f) 643a611d0caSIgor M. Liplianin { 64434d2f9bfSIgor M. Liplianin struct dm1105_dev *dev = feed_to_dm1105_dev(f); 645a611d0caSIgor M. Liplianin 64634d2f9bfSIgor M. Liplianin if (--dev->full_ts_users == 0) 64734d2f9bfSIgor M. Liplianin dm1105_disable_irqs(dev); 648a611d0caSIgor M. Liplianin 649a611d0caSIgor M. Liplianin return 0; 650a611d0caSIgor M. Liplianin } 651a611d0caSIgor M. Liplianin 652b72857ddSIgor M. Liplianin /* ir work handler */ 653b72857ddSIgor M. Liplianin static void dm1105_emit_key(struct work_struct *work) 654a611d0caSIgor M. Liplianin { 655b72857ddSIgor M. Liplianin struct infrared *ir = container_of(work, struct infrared, work); 656a611d0caSIgor M. Liplianin u32 ircom = ir->ir_command; 657a611d0caSIgor M. Liplianin u8 data; 658a611d0caSIgor M. Liplianin 659d1498ffcSIgor M. Liplianin if (ir_debug) 660d1498ffcSIgor M. Liplianin printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom); 661d1498ffcSIgor M. Liplianin 662a611d0caSIgor M. Liplianin data = (ircom >> 8) & 0x7f; 663a611d0caSIgor M. Liplianin 664120703f9SDavid Härdeman /* FIXME: UNKNOWN because we don't generate a full NEC scancode (yet?) */ 6656d741bfeSSean Young rc_keydown(ir->dev, RC_PROTO_UNKNOWN, data, 0); 666a611d0caSIgor M. Liplianin } 667a611d0caSIgor M. Liplianin 668d1498ffcSIgor M. Liplianin /* work handler */ 669d1498ffcSIgor M. Liplianin static void dm1105_dmx_buffer(struct work_struct *work) 670a611d0caSIgor M. Liplianin { 67134d2f9bfSIgor M. Liplianin struct dm1105_dev *dev = container_of(work, struct dm1105_dev, work); 672a611d0caSIgor M. Liplianin unsigned int nbpackets; 67334d2f9bfSIgor M. Liplianin u32 oldwrp = dev->wrp; 67434d2f9bfSIgor M. Liplianin u32 nextwrp = dev->nextwrp; 675a611d0caSIgor M. Liplianin 67634d2f9bfSIgor M. Liplianin if (!((dev->ts_buf[oldwrp] == 0x47) && 67734d2f9bfSIgor M. Liplianin (dev->ts_buf[oldwrp + 188] == 0x47) && 67834d2f9bfSIgor M. Liplianin (dev->ts_buf[oldwrp + 188 * 2] == 0x47))) { 67934d2f9bfSIgor M. Liplianin dev->PacketErrorCount++; 680a611d0caSIgor M. Liplianin /* bad packet found */ 68134d2f9bfSIgor M. Liplianin if ((dev->PacketErrorCount >= 2) && 68234d2f9bfSIgor M. Liplianin (dev->dmarst == 0)) { 6835eb3291fSIgor M. Liplianin dm_writeb(DM1105_RST, 1); 68434d2f9bfSIgor M. Liplianin dev->wrp = 0; 68534d2f9bfSIgor M. Liplianin dev->PacketErrorCount = 0; 68634d2f9bfSIgor M. Liplianin dev->dmarst = 0; 687d1498ffcSIgor M. Liplianin return; 688a611d0caSIgor M. Liplianin } 689a611d0caSIgor M. Liplianin } 690d1498ffcSIgor M. Liplianin 691a611d0caSIgor M. Liplianin if (nextwrp < oldwrp) { 69234d2f9bfSIgor M. Liplianin memcpy(dev->ts_buf + dev->buffer_size, dev->ts_buf, nextwrp); 69334d2f9bfSIgor M. Liplianin nbpackets = ((dev->buffer_size - oldwrp) + nextwrp) / 188; 694d1498ffcSIgor M. Liplianin } else 695a611d0caSIgor M. Liplianin nbpackets = (nextwrp - oldwrp) / 188; 696d1498ffcSIgor M. Liplianin 69734d2f9bfSIgor M. Liplianin dev->wrp = nextwrp; 69834d2f9bfSIgor M. Liplianin dvb_dmx_swfilter_packets(&dev->demux, &dev->ts_buf[oldwrp], nbpackets); 699d1498ffcSIgor M. Liplianin } 700d1498ffcSIgor M. Liplianin 70134d2f9bfSIgor M. Liplianin static irqreturn_t dm1105_irq(int irq, void *dev_id) 702d1498ffcSIgor M. Liplianin { 70334d2f9bfSIgor M. Liplianin struct dm1105_dev *dev = dev_id; 704d1498ffcSIgor M. Liplianin 705d1498ffcSIgor M. Liplianin /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */ 7065eb3291fSIgor M. Liplianin unsigned int intsts = dm_readb(DM1105_INTSTS); 7075eb3291fSIgor M. Liplianin dm_writeb(DM1105_INTSTS, intsts); 708d1498ffcSIgor M. Liplianin 709d1498ffcSIgor M. Liplianin switch (intsts) { 710d1498ffcSIgor M. Liplianin case INTSTS_TSIRQ: 711d1498ffcSIgor M. Liplianin case (INTSTS_TSIRQ | INTSTS_IR): 7125eb3291fSIgor M. Liplianin dev->nextwrp = dm_readl(DM1105_WRP) - dm_readl(DM1105_STADR); 71334d2f9bfSIgor M. Liplianin queue_work(dev->wq, &dev->work); 714a611d0caSIgor M. Liplianin break; 715a611d0caSIgor M. Liplianin case INTSTS_IR: 7165eb3291fSIgor M. Liplianin dev->ir.ir_command = dm_readl(DM1105_IRCODE); 71734d2f9bfSIgor M. Liplianin schedule_work(&dev->ir.work); 718a611d0caSIgor M. Liplianin break; 719a611d0caSIgor M. Liplianin } 720d1498ffcSIgor M. Liplianin 721a611d0caSIgor M. Liplianin return IRQ_HANDLED; 722a611d0caSIgor M. Liplianin } 723a611d0caSIgor M. Liplianin 7244c62e976SGreg Kroah-Hartman static int dm1105_ir_init(struct dm1105_dev *dm1105) 725a611d0caSIgor M. Liplianin { 726d8b4b582SDavid Härdeman struct rc_dev *dev; 727b72857ddSIgor M. Liplianin int err = -ENOMEM; 728a611d0caSIgor M. Liplianin 7290f7499fdSAndi Shyti dev = rc_allocate_device(RC_DRIVER_SCANCODE); 730d8b4b582SDavid Härdeman if (!dev) 731a611d0caSIgor M. Liplianin return -ENOMEM; 732a611d0caSIgor M. Liplianin 733a611d0caSIgor M. Liplianin snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), 734a611d0caSIgor M. Liplianin "pci-%s/ir0", pci_name(dm1105->pdev)); 735a611d0caSIgor M. Liplianin 736d8b4b582SDavid Härdeman dev->driver_name = MODULE_NAME; 737d8b4b582SDavid Härdeman dev->map_name = RC_MAP_DM1105_NEC; 738518f4b26SSean Young dev->device_name = "DVB on-card IR receiver"; 739d8b4b582SDavid Härdeman dev->input_phys = dm1105->ir.input_phys; 740d8b4b582SDavid Härdeman dev->input_id.bustype = BUS_PCI; 741d8b4b582SDavid Härdeman dev->input_id.version = 1; 742a611d0caSIgor M. Liplianin if (dm1105->pdev->subsystem_vendor) { 743d8b4b582SDavid Härdeman dev->input_id.vendor = dm1105->pdev->subsystem_vendor; 744d8b4b582SDavid Härdeman dev->input_id.product = dm1105->pdev->subsystem_device; 745a611d0caSIgor M. Liplianin } else { 746d8b4b582SDavid Härdeman dev->input_id.vendor = dm1105->pdev->vendor; 747d8b4b582SDavid Härdeman dev->input_id.product = dm1105->pdev->device; 748a611d0caSIgor M. Liplianin } 749d8b4b582SDavid Härdeman dev->dev.parent = &dm1105->pdev->dev; 750b72857ddSIgor M. Liplianin 751b72857ddSIgor M. Liplianin INIT_WORK(&dm1105->ir.work, dm1105_emit_key); 752b72857ddSIgor M. Liplianin 753d8b4b582SDavid Härdeman err = rc_register_device(dev); 75415100d89SDavid Härdeman if (err < 0) { 755d8b4b582SDavid Härdeman rc_free_device(dev); 756579e7d60SMauro Carvalho Chehab return err; 757a611d0caSIgor M. Liplianin } 758a611d0caSIgor M. Liplianin 759d8b4b582SDavid Härdeman dm1105->ir.dev = dev; 76015100d89SDavid Härdeman return 0; 76115100d89SDavid Härdeman } 76215100d89SDavid Härdeman 7634c62e976SGreg Kroah-Hartman static void dm1105_ir_exit(struct dm1105_dev *dm1105) 764a611d0caSIgor M. Liplianin { 765d8b4b582SDavid Härdeman rc_unregister_device(dm1105->ir.dev); 766a611d0caSIgor M. Liplianin } 767a611d0caSIgor M. Liplianin 7684c62e976SGreg Kroah-Hartman static int dm1105_hw_init(struct dm1105_dev *dev) 769a611d0caSIgor M. Liplianin { 77034d2f9bfSIgor M. Liplianin dm1105_disable_irqs(dev); 771a611d0caSIgor M. Liplianin 7725eb3291fSIgor M. Liplianin dm_writeb(DM1105_HOST_CTR, 0); 773a611d0caSIgor M. Liplianin 774a611d0caSIgor M. Liplianin /*DATALEN 188,*/ 7755eb3291fSIgor M. Liplianin dm_writeb(DM1105_DTALENTH, 188); 776a611d0caSIgor M. Liplianin /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/ 7775eb3291fSIgor M. Liplianin dm_writew(DM1105_TSCTR, 0xc10a); 778a611d0caSIgor M. Liplianin 779a611d0caSIgor M. Liplianin /* map DMA and set address */ 78034d2f9bfSIgor M. Liplianin dm1105_dma_map(dev); 78134d2f9bfSIgor M. Liplianin dm1105_set_dma_addr(dev); 782a611d0caSIgor M. Liplianin /* big buffer */ 7835eb3291fSIgor M. Liplianin dm_writel(DM1105_RLEN, 5 * DM1105_DMA_BYTES); 7845eb3291fSIgor M. Liplianin dm_writeb(DM1105_INTCNT, 47); 785a611d0caSIgor M. Liplianin 786a611d0caSIgor M. Liplianin /* IR NEC mode enable */ 7875eb3291fSIgor M. Liplianin dm_writeb(DM1105_IRCTR, (DM1105_IR_EN | DM1105_SYS_CHK)); 7885eb3291fSIgor M. Liplianin dm_writeb(DM1105_IRMODE, 0); 7895eb3291fSIgor M. Liplianin dm_writew(DM1105_SYSTEMCODE, 0); 790a611d0caSIgor M. Liplianin 791a611d0caSIgor M. Liplianin return 0; 792a611d0caSIgor M. Liplianin } 793a611d0caSIgor M. Liplianin 79434d2f9bfSIgor M. Liplianin static void dm1105_hw_exit(struct dm1105_dev *dev) 795a611d0caSIgor M. Liplianin { 79634d2f9bfSIgor M. Liplianin dm1105_disable_irqs(dev); 797a611d0caSIgor M. Liplianin 798a611d0caSIgor M. Liplianin /* IR disable */ 7995eb3291fSIgor M. Liplianin dm_writeb(DM1105_IRCTR, 0); 8005eb3291fSIgor M. Liplianin dm_writeb(DM1105_INTMAK, INTMAK_NONEMASK); 801a611d0caSIgor M. Liplianin 80234d2f9bfSIgor M. Liplianin dm1105_dma_unmap(dev); 803a611d0caSIgor M. Liplianin } 804e4aab64cSIgor M. Liplianin 805650497f1SBhumika Goyal static const struct stv0299_config sharp_z0194a_config = { 806d4305c68SIgor M. Liplianin .demod_address = 0x68, 807d4305c68SIgor M. Liplianin .inittab = sharp_z0194a_inittab, 808d4305c68SIgor M. Liplianin .mclk = 88000000UL, 809d4305c68SIgor M. Liplianin .invert = 1, 810d4305c68SIgor M. Liplianin .skip_reinit = 0, 811d4305c68SIgor M. Liplianin .lock_output = STV0299_LOCKOUTPUT_1, 812d4305c68SIgor M. Liplianin .volt13_op0_op1 = STV0299_VOLT13_OP1, 813d4305c68SIgor M. Liplianin .min_delay_ms = 100, 814d4305c68SIgor M. Liplianin .set_symbol_rate = sharp_z0194a_set_symbol_rate, 815d4305c68SIgor M. Liplianin }; 816d4305c68SIgor M. Liplianin 817a611d0caSIgor M. Liplianin static struct stv0288_config earda_config = { 818a611d0caSIgor M. Liplianin .demod_address = 0x68, 819a611d0caSIgor M. Liplianin .min_delay_ms = 100, 820a611d0caSIgor M. Liplianin }; 821a611d0caSIgor M. Liplianin 822a611d0caSIgor M. Liplianin static struct si21xx_config serit_config = { 823a611d0caSIgor M. Liplianin .demod_address = 0x68, 824a611d0caSIgor M. Liplianin .min_delay_ms = 100, 825a611d0caSIgor M. Liplianin 826a611d0caSIgor M. Liplianin }; 827a611d0caSIgor M. Liplianin 828a611d0caSIgor M. Liplianin static struct cx24116_config serit_sp2633_config = { 829a611d0caSIgor M. Liplianin .demod_address = 0x55, 830a611d0caSIgor M. Liplianin }; 831a611d0caSIgor M. Liplianin 832b4a0e816SIgor M. Liplianin static struct ds3000_config dvbworld_ds3000_config = { 833b4a0e816SIgor M. Liplianin .demod_address = 0x68, 834b4a0e816SIgor M. Liplianin }; 835b4a0e816SIgor M. Liplianin 83673f0af44SKonstantin Dimitrov static struct ts2020_config dvbworld_ts2020_config = { 83773f0af44SKonstantin Dimitrov .tuner_address = 0x60, 838b858c331SIgor M. Liplianin .clk_out_div = 1, 83973f0af44SKonstantin Dimitrov }; 84073f0af44SKonstantin Dimitrov 8414c62e976SGreg Kroah-Hartman static int frontend_init(struct dm1105_dev *dev) 842a611d0caSIgor M. Liplianin { 843a611d0caSIgor M. Liplianin int ret; 844a611d0caSIgor M. Liplianin 84534d2f9bfSIgor M. Liplianin switch (dev->boardnr) { 8460017505dSIgor M. Liplianin case DM1105_BOARD_UNBRANDED_I2C_ON_GPIO: 8470017505dSIgor M. Liplianin dm1105_gpio_enable(dev, GPIO15, 1); 8480017505dSIgor M. Liplianin dm1105_gpio_clear(dev, GPIO15); 8490017505dSIgor M. Liplianin msleep(100); 8500017505dSIgor M. Liplianin dm1105_gpio_set(dev, GPIO15); 8510017505dSIgor M. Liplianin msleep(200); 8520017505dSIgor M. Liplianin dev->fe = dvb_attach( 8530017505dSIgor M. Liplianin stv0299_attach, &sharp_z0194a_config, 8540017505dSIgor M. Liplianin &dev->i2c_bb_adap); 8550017505dSIgor M. Liplianin if (dev->fe) { 8560017505dSIgor M. Liplianin dev->fe->ops.set_voltage = dm1105_set_voltage; 8570017505dSIgor M. Liplianin dvb_attach(dvb_pll_attach, dev->fe, 0x60, 8580017505dSIgor M. Liplianin &dev->i2c_bb_adap, DVB_PLL_OPERA1); 8590017505dSIgor M. Liplianin break; 8600017505dSIgor M. Liplianin } 8610017505dSIgor M. Liplianin 8620017505dSIgor M. Liplianin dev->fe = dvb_attach( 8630017505dSIgor M. Liplianin stv0288_attach, &earda_config, 8640017505dSIgor M. Liplianin &dev->i2c_bb_adap); 8650017505dSIgor M. Liplianin if (dev->fe) { 8660017505dSIgor M. Liplianin dev->fe->ops.set_voltage = dm1105_set_voltage; 8670017505dSIgor M. Liplianin dvb_attach(stb6000_attach, dev->fe, 0x61, 8680017505dSIgor M. Liplianin &dev->i2c_bb_adap); 8690017505dSIgor M. Liplianin break; 8700017505dSIgor M. Liplianin } 8710017505dSIgor M. Liplianin 8720017505dSIgor M. Liplianin dev->fe = dvb_attach( 8730017505dSIgor M. Liplianin si21xx_attach, &serit_config, 8740017505dSIgor M. Liplianin &dev->i2c_bb_adap); 8750017505dSIgor M. Liplianin if (dev->fe) 8760017505dSIgor M. Liplianin dev->fe->ops.set_voltage = dm1105_set_voltage; 8770017505dSIgor M. Liplianin break; 878d8300df9SIgor M. Liplianin case DM1105_BOARD_DVBWORLD_2004: 87934d2f9bfSIgor M. Liplianin dev->fe = dvb_attach( 880519a4bdcSIgor M. Liplianin cx24116_attach, &serit_sp2633_config, 88134d2f9bfSIgor M. Liplianin &dev->i2c_adap); 88234d2f9bfSIgor M. Liplianin if (dev->fe) { 88334d2f9bfSIgor M. Liplianin dev->fe->ops.set_voltage = dm1105_set_voltage; 884b4a0e816SIgor M. Liplianin break; 885b4a0e816SIgor M. Liplianin } 886b4a0e816SIgor M. Liplianin 88734d2f9bfSIgor M. Liplianin dev->fe = dvb_attach( 888b4a0e816SIgor M. Liplianin ds3000_attach, &dvbworld_ds3000_config, 88934d2f9bfSIgor M. Liplianin &dev->i2c_adap); 89073f0af44SKonstantin Dimitrov if (dev->fe) { 89173f0af44SKonstantin Dimitrov dvb_attach(ts2020_attach, dev->fe, 89273f0af44SKonstantin Dimitrov &dvbworld_ts2020_config, &dev->i2c_adap); 89334d2f9bfSIgor M. Liplianin dev->fe->ops.set_voltage = dm1105_set_voltage; 89473f0af44SKonstantin Dimitrov } 895519a4bdcSIgor M. Liplianin 896519a4bdcSIgor M. Liplianin break; 897d8300df9SIgor M. Liplianin case DM1105_BOARD_DVBWORLD_2002: 898d8300df9SIgor M. Liplianin case DM1105_BOARD_AXESS_DM05: 899519a4bdcSIgor M. Liplianin default: 90034d2f9bfSIgor M. Liplianin dev->fe = dvb_attach( 901a611d0caSIgor M. Liplianin stv0299_attach, &sharp_z0194a_config, 90234d2f9bfSIgor M. Liplianin &dev->i2c_adap); 90334d2f9bfSIgor M. Liplianin if (dev->fe) { 90434d2f9bfSIgor M. Liplianin dev->fe->ops.set_voltage = dm1105_set_voltage; 90534d2f9bfSIgor M. Liplianin dvb_attach(dvb_pll_attach, dev->fe, 0x60, 90634d2f9bfSIgor M. Liplianin &dev->i2c_adap, DVB_PLL_OPERA1); 907519a4bdcSIgor M. Liplianin break; 908a611d0caSIgor M. Liplianin } 909e4aab64cSIgor M. Liplianin 91034d2f9bfSIgor M. Liplianin dev->fe = dvb_attach( 911a611d0caSIgor M. Liplianin stv0288_attach, &earda_config, 91234d2f9bfSIgor M. Liplianin &dev->i2c_adap); 91334d2f9bfSIgor M. Liplianin if (dev->fe) { 91434d2f9bfSIgor M. Liplianin dev->fe->ops.set_voltage = dm1105_set_voltage; 91534d2f9bfSIgor M. Liplianin dvb_attach(stb6000_attach, dev->fe, 0x61, 91634d2f9bfSIgor M. Liplianin &dev->i2c_adap); 917519a4bdcSIgor M. Liplianin break; 918a611d0caSIgor M. Liplianin } 919e4aab64cSIgor M. Liplianin 92034d2f9bfSIgor M. Liplianin dev->fe = dvb_attach( 921a611d0caSIgor M. Liplianin si21xx_attach, &serit_config, 92234d2f9bfSIgor M. Liplianin &dev->i2c_adap); 92334d2f9bfSIgor M. Liplianin if (dev->fe) 92434d2f9bfSIgor M. Liplianin dev->fe->ops.set_voltage = dm1105_set_voltage; 925519a4bdcSIgor M. Liplianin 926a611d0caSIgor M. Liplianin } 927a611d0caSIgor M. Liplianin 92834d2f9bfSIgor M. Liplianin if (!dev->fe) { 92934d2f9bfSIgor M. Liplianin dev_err(&dev->pdev->dev, "could not attach frontend\n"); 930a611d0caSIgor M. Liplianin return -ENODEV; 931a611d0caSIgor M. Liplianin } 932a611d0caSIgor M. Liplianin 93334d2f9bfSIgor M. Liplianin ret = dvb_register_frontend(&dev->dvb_adapter, dev->fe); 934a611d0caSIgor M. Liplianin if (ret < 0) { 93534d2f9bfSIgor M. Liplianin if (dev->fe->ops.release) 93634d2f9bfSIgor M. Liplianin dev->fe->ops.release(dev->fe); 93734d2f9bfSIgor M. Liplianin dev->fe = NULL; 938a611d0caSIgor M. Liplianin return ret; 939a611d0caSIgor M. Liplianin } 940a611d0caSIgor M. Liplianin 941a611d0caSIgor M. Liplianin return 0; 942a611d0caSIgor M. Liplianin } 943a611d0caSIgor M. Liplianin 9444c62e976SGreg Kroah-Hartman static void dm1105_read_mac(struct dm1105_dev *dev, u8 *mac) 945a611d0caSIgor M. Liplianin { 946a611d0caSIgor M. Liplianin static u8 command[1] = { 0x28 }; 947a611d0caSIgor M. Liplianin 948a611d0caSIgor M. Liplianin struct i2c_msg msg[] = { 949519a4bdcSIgor M. Liplianin { 950519a4bdcSIgor M. Liplianin .addr = IIC_24C01_addr >> 1, 951519a4bdcSIgor M. Liplianin .flags = 0, 952519a4bdcSIgor M. Liplianin .buf = command, 953519a4bdcSIgor M. Liplianin .len = 1 954519a4bdcSIgor M. Liplianin }, { 955519a4bdcSIgor M. Liplianin .addr = IIC_24C01_addr >> 1, 956519a4bdcSIgor M. Liplianin .flags = I2C_M_RD, 957519a4bdcSIgor M. Liplianin .buf = mac, 958519a4bdcSIgor M. Liplianin .len = 6 959519a4bdcSIgor M. Liplianin }, 960a611d0caSIgor M. Liplianin }; 961a611d0caSIgor M. Liplianin 96234d2f9bfSIgor M. Liplianin dm1105_i2c_xfer(&dev->i2c_adap, msg , 2); 96334d2f9bfSIgor M. Liplianin dev_info(&dev->pdev->dev, "MAC %pM\n", mac); 964a611d0caSIgor M. Liplianin } 965a611d0caSIgor M. Liplianin 9664c62e976SGreg Kroah-Hartman static int dm1105_probe(struct pci_dev *pdev, 967a611d0caSIgor M. Liplianin const struct pci_device_id *ent) 968a611d0caSIgor M. Liplianin { 96934d2f9bfSIgor M. Liplianin struct dm1105_dev *dev; 970a611d0caSIgor M. Liplianin struct dvb_adapter *dvb_adapter; 971a611d0caSIgor M. Liplianin struct dvb_demux *dvbdemux; 972a611d0caSIgor M. Liplianin struct dmx_demux *dmx; 973a611d0caSIgor M. Liplianin int ret = -ENOMEM; 974d8300df9SIgor M. Liplianin int i; 975a611d0caSIgor M. Liplianin 97665b40a98SAnton Vasilyev if (dm1105_devcount >= ARRAY_SIZE(card)) 97765b40a98SAnton Vasilyev return -ENODEV; 97865b40a98SAnton Vasilyev 97934d2f9bfSIgor M. Liplianin dev = kzalloc(sizeof(struct dm1105_dev), GFP_KERNEL); 98034d2f9bfSIgor M. Liplianin if (!dev) 981d1498ffcSIgor M. Liplianin return -ENOMEM; 982a611d0caSIgor M. Liplianin 983d8300df9SIgor M. Liplianin /* board config */ 98434d2f9bfSIgor M. Liplianin dev->nr = dm1105_devcount; 98534d2f9bfSIgor M. Liplianin dev->boardnr = UNSET; 98634d2f9bfSIgor M. Liplianin if (card[dev->nr] < ARRAY_SIZE(dm1105_boards)) 98734d2f9bfSIgor M. Liplianin dev->boardnr = card[dev->nr]; 98834d2f9bfSIgor M. Liplianin for (i = 0; UNSET == dev->boardnr && 989d8300df9SIgor M. Liplianin i < ARRAY_SIZE(dm1105_subids); i++) 990d8300df9SIgor M. Liplianin if (pdev->subsystem_vendor == 991d8300df9SIgor M. Liplianin dm1105_subids[i].subvendor && 992d8300df9SIgor M. Liplianin pdev->subsystem_device == 993d8300df9SIgor M. Liplianin dm1105_subids[i].subdevice) 99434d2f9bfSIgor M. Liplianin dev->boardnr = dm1105_subids[i].card; 995d8300df9SIgor M. Liplianin 99634d2f9bfSIgor M. Liplianin if (UNSET == dev->boardnr) { 99734d2f9bfSIgor M. Liplianin dev->boardnr = DM1105_BOARD_UNKNOWN; 998d8300df9SIgor M. Liplianin dm1105_card_list(pdev); 999d8300df9SIgor M. Liplianin } 1000d8300df9SIgor M. Liplianin 1001d8300df9SIgor M. Liplianin dm1105_devcount++; 100234d2f9bfSIgor M. Liplianin dev->pdev = pdev; 100334d2f9bfSIgor M. Liplianin dev->buffer_size = 5 * DM1105_DMA_BYTES; 100434d2f9bfSIgor M. Liplianin dev->PacketErrorCount = 0; 100534d2f9bfSIgor M. Liplianin dev->dmarst = 0; 1006a611d0caSIgor M. Liplianin 1007a611d0caSIgor M. Liplianin ret = pci_enable_device(pdev); 1008a611d0caSIgor M. Liplianin if (ret < 0) 1009a611d0caSIgor M. Liplianin goto err_kfree; 1010a611d0caSIgor M. Liplianin 1011*acc4c91eSChristophe JAILLET ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 1012a611d0caSIgor M. Liplianin if (ret < 0) 1013a611d0caSIgor M. Liplianin goto err_pci_disable_device; 1014a611d0caSIgor M. Liplianin 1015a611d0caSIgor M. Liplianin pci_set_master(pdev); 1016a611d0caSIgor M. Liplianin 1017a611d0caSIgor M. Liplianin ret = pci_request_regions(pdev, DRIVER_NAME); 1018a611d0caSIgor M. Liplianin if (ret < 0) 1019a611d0caSIgor M. Liplianin goto err_pci_disable_device; 1020a611d0caSIgor M. Liplianin 102134d2f9bfSIgor M. Liplianin dev->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); 102234d2f9bfSIgor M. Liplianin if (!dev->io_mem) { 1023a611d0caSIgor M. Liplianin ret = -EIO; 1024a611d0caSIgor M. Liplianin goto err_pci_release_regions; 1025a611d0caSIgor M. Liplianin } 1026a611d0caSIgor M. Liplianin 102734d2f9bfSIgor M. Liplianin spin_lock_init(&dev->lock); 102834d2f9bfSIgor M. Liplianin pci_set_drvdata(pdev, dev); 1029a611d0caSIgor M. Liplianin 103034d2f9bfSIgor M. Liplianin ret = dm1105_hw_init(dev); 1031a611d0caSIgor M. Liplianin if (ret < 0) 1032d1498ffcSIgor M. Liplianin goto err_pci_iounmap; 1033a611d0caSIgor M. Liplianin 1034a611d0caSIgor M. Liplianin /* i2c */ 103534d2f9bfSIgor M. Liplianin i2c_set_adapdata(&dev->i2c_adap, dev); 1036cc1e6315SMauro Carvalho Chehab strscpy(dev->i2c_adap.name, DRIVER_NAME, sizeof(dev->i2c_adap.name)); 103734d2f9bfSIgor M. Liplianin dev->i2c_adap.owner = THIS_MODULE; 103834d2f9bfSIgor M. Liplianin dev->i2c_adap.dev.parent = &pdev->dev; 103934d2f9bfSIgor M. Liplianin dev->i2c_adap.algo = &dm1105_algo; 104034d2f9bfSIgor M. Liplianin dev->i2c_adap.algo_data = dev; 104134d2f9bfSIgor M. Liplianin ret = i2c_add_adapter(&dev->i2c_adap); 1042a611d0caSIgor M. Liplianin 1043a611d0caSIgor M. Liplianin if (ret < 0) 104434d2f9bfSIgor M. Liplianin goto err_dm1105_hw_exit; 1045a611d0caSIgor M. Liplianin 10460017505dSIgor M. Liplianin i2c_set_adapdata(&dev->i2c_bb_adap, dev); 1047cc1e6315SMauro Carvalho Chehab strscpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME, 1048cc1e6315SMauro Carvalho Chehab sizeof(dev->i2c_bb_adap.name)); 10490017505dSIgor M. Liplianin dev->i2c_bb_adap.owner = THIS_MODULE; 10500017505dSIgor M. Liplianin dev->i2c_bb_adap.dev.parent = &pdev->dev; 10510017505dSIgor M. Liplianin dev->i2c_bb_adap.algo_data = &dev->i2c_bit; 10520017505dSIgor M. Liplianin dev->i2c_bit.data = dev; 10530017505dSIgor M. Liplianin dev->i2c_bit.setsda = dm1105_setsda; 10540017505dSIgor M. Liplianin dev->i2c_bit.setscl = dm1105_setscl; 10550017505dSIgor M. Liplianin dev->i2c_bit.getsda = dm1105_getsda; 10560017505dSIgor M. Liplianin dev->i2c_bit.getscl = dm1105_getscl; 10570017505dSIgor M. Liplianin dev->i2c_bit.udelay = 10; 10580017505dSIgor M. Liplianin dev->i2c_bit.timeout = 10; 10590017505dSIgor M. Liplianin 10600017505dSIgor M. Liplianin /* Raise SCL and SDA */ 10610017505dSIgor M. Liplianin dm1105_setsda(dev, 1); 10620017505dSIgor M. Liplianin dm1105_setscl(dev, 1); 10630017505dSIgor M. Liplianin 10640017505dSIgor M. Liplianin ret = i2c_bit_add_bus(&dev->i2c_bb_adap); 10650017505dSIgor M. Liplianin if (ret < 0) 10660017505dSIgor M. Liplianin goto err_i2c_del_adapter; 10670017505dSIgor M. Liplianin 1068a611d0caSIgor M. Liplianin /* dvb */ 106934d2f9bfSIgor M. Liplianin ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME, 1070a611d0caSIgor M. Liplianin THIS_MODULE, &pdev->dev, adapter_nr); 1071a611d0caSIgor M. Liplianin if (ret < 0) 10720017505dSIgor M. Liplianin goto err_i2c_del_adapters; 1073a611d0caSIgor M. Liplianin 107434d2f9bfSIgor M. Liplianin dvb_adapter = &dev->dvb_adapter; 1075a611d0caSIgor M. Liplianin 107634d2f9bfSIgor M. Liplianin dm1105_read_mac(dev, dvb_adapter->proposed_mac); 1077a611d0caSIgor M. Liplianin 107834d2f9bfSIgor M. Liplianin dvbdemux = &dev->demux; 1079a611d0caSIgor M. Liplianin dvbdemux->filternum = 256; 1080a611d0caSIgor M. Liplianin dvbdemux->feednum = 256; 108134d2f9bfSIgor M. Liplianin dvbdemux->start_feed = dm1105_start_feed; 108234d2f9bfSIgor M. Liplianin dvbdemux->stop_feed = dm1105_stop_feed; 1083a611d0caSIgor M. Liplianin dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | 1084a611d0caSIgor M. Liplianin DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); 1085a611d0caSIgor M. Liplianin ret = dvb_dmx_init(dvbdemux); 1086a611d0caSIgor M. Liplianin if (ret < 0) 1087a611d0caSIgor M. Liplianin goto err_dvb_unregister_adapter; 1088a611d0caSIgor M. Liplianin 1089a611d0caSIgor M. Liplianin dmx = &dvbdemux->dmx; 109034d2f9bfSIgor M. Liplianin dev->dmxdev.filternum = 256; 109134d2f9bfSIgor M. Liplianin dev->dmxdev.demux = dmx; 109234d2f9bfSIgor M. Liplianin dev->dmxdev.capabilities = 0; 1093a611d0caSIgor M. Liplianin 109434d2f9bfSIgor M. Liplianin ret = dvb_dmxdev_init(&dev->dmxdev, dvb_adapter); 1095a611d0caSIgor M. Liplianin if (ret < 0) 1096a611d0caSIgor M. Liplianin goto err_dvb_dmx_release; 1097a611d0caSIgor M. Liplianin 109834d2f9bfSIgor M. Liplianin dev->hw_frontend.source = DMX_FRONTEND_0; 1099a611d0caSIgor M. Liplianin 110034d2f9bfSIgor M. Liplianin ret = dmx->add_frontend(dmx, &dev->hw_frontend); 1101a611d0caSIgor M. Liplianin if (ret < 0) 1102a611d0caSIgor M. Liplianin goto err_dvb_dmxdev_release; 1103a611d0caSIgor M. Liplianin 110434d2f9bfSIgor M. Liplianin dev->mem_frontend.source = DMX_MEMORY_FE; 1105a611d0caSIgor M. Liplianin 110634d2f9bfSIgor M. Liplianin ret = dmx->add_frontend(dmx, &dev->mem_frontend); 1107a611d0caSIgor M. Liplianin if (ret < 0) 1108a611d0caSIgor M. Liplianin goto err_remove_hw_frontend; 1109a611d0caSIgor M. Liplianin 111034d2f9bfSIgor M. Liplianin ret = dmx->connect_frontend(dmx, &dev->hw_frontend); 1111a611d0caSIgor M. Liplianin if (ret < 0) 1112a611d0caSIgor M. Liplianin goto err_remove_mem_frontend; 1113a611d0caSIgor M. Liplianin 11145584c641SJonathan Nieder ret = dvb_net_init(dvb_adapter, &dev->dvbnet, dmx); 11155584c641SJonathan Nieder if (ret < 0) 11165584c641SJonathan Nieder goto err_disconnect_frontend; 11175584c641SJonathan Nieder 111834d2f9bfSIgor M. Liplianin ret = frontend_init(dev); 1119a611d0caSIgor M. Liplianin if (ret < 0) 1120e9966341SJonathan Nieder goto err_dvb_net; 1121a611d0caSIgor M. Liplianin 112234d2f9bfSIgor M. Liplianin dm1105_ir_init(dev); 1123d1498ffcSIgor M. Liplianin 112434d2f9bfSIgor M. Liplianin INIT_WORK(&dev->work, dm1105_dmx_buffer); 112534d2f9bfSIgor M. Liplianin sprintf(dev->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num); 112634d2f9bfSIgor M. Liplianin dev->wq = create_singlethread_workqueue(dev->wqn); 112795d08126SPeter Senna Tschudin if (!dev->wq) { 112895d08126SPeter Senna Tschudin ret = -ENOMEM; 1129519a4bdcSIgor M. Liplianin goto err_dvb_net; 113095d08126SPeter Senna Tschudin } 1131d1498ffcSIgor M. Liplianin 113234d2f9bfSIgor M. Liplianin ret = request_irq(pdev->irq, dm1105_irq, IRQF_SHARED, 113334d2f9bfSIgor M. Liplianin DRIVER_NAME, dev); 1134d1498ffcSIgor M. Liplianin if (ret < 0) 1135519a4bdcSIgor M. Liplianin goto err_workqueue; 1136d1498ffcSIgor M. Liplianin 1137d1498ffcSIgor M. Liplianin return 0; 1138a611d0caSIgor M. Liplianin 1139519a4bdcSIgor M. Liplianin err_workqueue: 114034d2f9bfSIgor M. Liplianin destroy_workqueue(dev->wq); 1141519a4bdcSIgor M. Liplianin err_dvb_net: 114234d2f9bfSIgor M. Liplianin dvb_net_release(&dev->dvbnet); 1143a611d0caSIgor M. Liplianin err_disconnect_frontend: 1144a611d0caSIgor M. Liplianin dmx->disconnect_frontend(dmx); 1145a611d0caSIgor M. Liplianin err_remove_mem_frontend: 114634d2f9bfSIgor M. Liplianin dmx->remove_frontend(dmx, &dev->mem_frontend); 1147a611d0caSIgor M. Liplianin err_remove_hw_frontend: 114834d2f9bfSIgor M. Liplianin dmx->remove_frontend(dmx, &dev->hw_frontend); 1149a611d0caSIgor M. Liplianin err_dvb_dmxdev_release: 115034d2f9bfSIgor M. Liplianin dvb_dmxdev_release(&dev->dmxdev); 1151a611d0caSIgor M. Liplianin err_dvb_dmx_release: 1152a611d0caSIgor M. Liplianin dvb_dmx_release(dvbdemux); 1153a611d0caSIgor M. Liplianin err_dvb_unregister_adapter: 1154a611d0caSIgor M. Liplianin dvb_unregister_adapter(dvb_adapter); 11550017505dSIgor M. Liplianin err_i2c_del_adapters: 11560017505dSIgor M. Liplianin i2c_del_adapter(&dev->i2c_bb_adap); 1157a611d0caSIgor M. Liplianin err_i2c_del_adapter: 115834d2f9bfSIgor M. Liplianin i2c_del_adapter(&dev->i2c_adap); 115934d2f9bfSIgor M. Liplianin err_dm1105_hw_exit: 116034d2f9bfSIgor M. Liplianin dm1105_hw_exit(dev); 1161a611d0caSIgor M. Liplianin err_pci_iounmap: 116234d2f9bfSIgor M. Liplianin pci_iounmap(pdev, dev->io_mem); 1163a611d0caSIgor M. Liplianin err_pci_release_regions: 1164a611d0caSIgor M. Liplianin pci_release_regions(pdev); 1165a611d0caSIgor M. Liplianin err_pci_disable_device: 1166a611d0caSIgor M. Liplianin pci_disable_device(pdev); 1167a611d0caSIgor M. Liplianin err_kfree: 116834d2f9bfSIgor M. Liplianin kfree(dev); 1169d1498ffcSIgor M. Liplianin return ret; 1170a611d0caSIgor M. Liplianin } 1171a611d0caSIgor M. Liplianin 11724c62e976SGreg Kroah-Hartman static void dm1105_remove(struct pci_dev *pdev) 1173a611d0caSIgor M. Liplianin { 117434d2f9bfSIgor M. Liplianin struct dm1105_dev *dev = pci_get_drvdata(pdev); 117534d2f9bfSIgor M. Liplianin struct dvb_adapter *dvb_adapter = &dev->dvb_adapter; 117634d2f9bfSIgor M. Liplianin struct dvb_demux *dvbdemux = &dev->demux; 1177a611d0caSIgor M. Liplianin struct dmx_demux *dmx = &dvbdemux->dmx; 1178a611d0caSIgor M. Liplianin 117934d2f9bfSIgor M. Liplianin dm1105_ir_exit(dev); 1180a611d0caSIgor M. Liplianin dmx->close(dmx); 118134d2f9bfSIgor M. Liplianin dvb_net_release(&dev->dvbnet); 118234d2f9bfSIgor M. Liplianin if (dev->fe) 118334d2f9bfSIgor M. Liplianin dvb_unregister_frontend(dev->fe); 1184a611d0caSIgor M. Liplianin 1185a611d0caSIgor M. Liplianin dmx->disconnect_frontend(dmx); 118634d2f9bfSIgor M. Liplianin dmx->remove_frontend(dmx, &dev->mem_frontend); 118734d2f9bfSIgor M. Liplianin dmx->remove_frontend(dmx, &dev->hw_frontend); 118834d2f9bfSIgor M. Liplianin dvb_dmxdev_release(&dev->dmxdev); 1189a611d0caSIgor M. Liplianin dvb_dmx_release(dvbdemux); 1190a611d0caSIgor M. Liplianin dvb_unregister_adapter(dvb_adapter); 119134d2f9bfSIgor M. Liplianin i2c_del_adapter(&dev->i2c_adap); 1192a611d0caSIgor M. Liplianin 119334d2f9bfSIgor M. Liplianin dm1105_hw_exit(dev); 119434d2f9bfSIgor M. Liplianin free_irq(pdev->irq, dev); 119534d2f9bfSIgor M. Liplianin pci_iounmap(pdev, dev->io_mem); 1196a611d0caSIgor M. Liplianin pci_release_regions(pdev); 1197a611d0caSIgor M. Liplianin pci_disable_device(pdev); 1198d8300df9SIgor M. Liplianin dm1105_devcount--; 119934d2f9bfSIgor M. Liplianin kfree(dev); 1200a611d0caSIgor M. Liplianin } 1201a611d0caSIgor M. Liplianin 120282c055cdSArvind Yadav static const struct pci_device_id dm1105_id_table[] = { 1203a611d0caSIgor M. Liplianin { 1204a611d0caSIgor M. Liplianin .vendor = PCI_VENDOR_ID_TRIGEM, 1205a611d0caSIgor M. Liplianin .device = PCI_DEVICE_ID_DM1105, 1206a611d0caSIgor M. Liplianin .subvendor = PCI_ANY_ID, 1207d8300df9SIgor M. Liplianin .subdevice = PCI_ANY_ID, 1208a611d0caSIgor M. Liplianin }, { 1209519a4bdcSIgor M. Liplianin .vendor = PCI_VENDOR_ID_AXESS, 1210519a4bdcSIgor M. Liplianin .device = PCI_DEVICE_ID_DM05, 1211d8300df9SIgor M. Liplianin .subvendor = PCI_ANY_ID, 1212d8300df9SIgor M. Liplianin .subdevice = PCI_ANY_ID, 1213519a4bdcSIgor M. Liplianin }, { 1214a611d0caSIgor M. Liplianin /* empty */ 1215a611d0caSIgor M. Liplianin }, 1216a611d0caSIgor M. Liplianin }; 1217a611d0caSIgor M. Liplianin 1218a611d0caSIgor M. Liplianin MODULE_DEVICE_TABLE(pci, dm1105_id_table); 1219a611d0caSIgor M. Liplianin 1220a611d0caSIgor M. Liplianin static struct pci_driver dm1105_driver = { 1221a611d0caSIgor M. Liplianin .name = DRIVER_NAME, 1222a611d0caSIgor M. Liplianin .id_table = dm1105_id_table, 1223a611d0caSIgor M. Liplianin .probe = dm1105_probe, 12244c62e976SGreg Kroah-Hartman .remove = dm1105_remove, 1225a611d0caSIgor M. Liplianin }; 1226a611d0caSIgor M. Liplianin 1227548006ceSLibo Chen module_pci_driver(dm1105_driver); 1228a611d0caSIgor M. Liplianin 1229a611d0caSIgor M. Liplianin MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>"); 1230a611d0caSIgor M. Liplianin MODULE_DESCRIPTION("SDMC DM1105 DVB driver"); 1231a611d0caSIgor M. Liplianin MODULE_LICENSE("GPL"); 1232