1*b285192aSMauro Carvalho Chehab /* 2*b285192aSMauro Carvalho Chehab * cx18 driver initialization and card probing 3*b285192aSMauro Carvalho Chehab * 4*b285192aSMauro Carvalho Chehab * Derived from ivtv-driver.c 5*b285192aSMauro Carvalho Chehab * 6*b285192aSMauro Carvalho Chehab * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 7*b285192aSMauro Carvalho Chehab * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net> 8*b285192aSMauro Carvalho Chehab * 9*b285192aSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 10*b285192aSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 11*b285192aSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 12*b285192aSMauro Carvalho Chehab * (at your option) any later version. 13*b285192aSMauro Carvalho Chehab * 14*b285192aSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 15*b285192aSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 16*b285192aSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*b285192aSMauro Carvalho Chehab * GNU General Public License for more details. 18*b285192aSMauro Carvalho Chehab * 19*b285192aSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 20*b285192aSMauro Carvalho Chehab * along with this program; if not, write to the Free Software 21*b285192aSMauro Carvalho Chehab * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 22*b285192aSMauro Carvalho Chehab * 02111-1307 USA 23*b285192aSMauro Carvalho Chehab */ 24*b285192aSMauro Carvalho Chehab 25*b285192aSMauro Carvalho Chehab #include "cx18-driver.h" 26*b285192aSMauro Carvalho Chehab #include "cx18-io.h" 27*b285192aSMauro Carvalho Chehab #include "cx18-version.h" 28*b285192aSMauro Carvalho Chehab #include "cx18-cards.h" 29*b285192aSMauro Carvalho Chehab #include "cx18-i2c.h" 30*b285192aSMauro Carvalho Chehab #include "cx18-irq.h" 31*b285192aSMauro Carvalho Chehab #include "cx18-gpio.h" 32*b285192aSMauro Carvalho Chehab #include "cx18-firmware.h" 33*b285192aSMauro Carvalho Chehab #include "cx18-queue.h" 34*b285192aSMauro Carvalho Chehab #include "cx18-streams.h" 35*b285192aSMauro Carvalho Chehab #include "cx18-av-core.h" 36*b285192aSMauro Carvalho Chehab #include "cx18-scb.h" 37*b285192aSMauro Carvalho Chehab #include "cx18-mailbox.h" 38*b285192aSMauro Carvalho Chehab #include "cx18-ioctl.h" 39*b285192aSMauro Carvalho Chehab #include "cx18-controls.h" 40*b285192aSMauro Carvalho Chehab #include "tuner-xc2028.h" 41*b285192aSMauro Carvalho Chehab #include <linux/dma-mapping.h> 42*b285192aSMauro Carvalho Chehab #include <media/tveeprom.h> 43*b285192aSMauro Carvalho Chehab 44*b285192aSMauro Carvalho Chehab /* If you have already X v4l cards, then set this to X. This way 45*b285192aSMauro Carvalho Chehab the device numbers stay matched. Example: you have a WinTV card 46*b285192aSMauro Carvalho Chehab without radio and a Compro H900 with. Normally this would give a 47*b285192aSMauro Carvalho Chehab video1 device together with a radio0 device for the Compro. By 48*b285192aSMauro Carvalho Chehab setting this to 1 you ensure that radio0 is now also radio1. */ 49*b285192aSMauro Carvalho Chehab int cx18_first_minor; 50*b285192aSMauro Carvalho Chehab 51*b285192aSMauro Carvalho Chehab /* Callback for registering extensions */ 52*b285192aSMauro Carvalho Chehab int (*cx18_ext_init)(struct cx18 *); 53*b285192aSMauro Carvalho Chehab EXPORT_SYMBOL(cx18_ext_init); 54*b285192aSMauro Carvalho Chehab 55*b285192aSMauro Carvalho Chehab /* add your revision and whatnot here */ 56*b285192aSMauro Carvalho Chehab static struct pci_device_id cx18_pci_tbl[] __devinitdata = { 57*b285192aSMauro Carvalho Chehab {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418, 58*b285192aSMauro Carvalho Chehab PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 59*b285192aSMauro Carvalho Chehab {0,} 60*b285192aSMauro Carvalho Chehab }; 61*b285192aSMauro Carvalho Chehab 62*b285192aSMauro Carvalho Chehab MODULE_DEVICE_TABLE(pci, cx18_pci_tbl); 63*b285192aSMauro Carvalho Chehab 64*b285192aSMauro Carvalho Chehab static atomic_t cx18_instance = ATOMIC_INIT(0); 65*b285192aSMauro Carvalho Chehab 66*b285192aSMauro Carvalho Chehab /* Parameter declarations */ 67*b285192aSMauro Carvalho Chehab static int cardtype[CX18_MAX_CARDS]; 68*b285192aSMauro Carvalho Chehab static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, 69*b285192aSMauro Carvalho Chehab -1, -1, -1, -1, -1, -1, -1, -1, 70*b285192aSMauro Carvalho Chehab -1, -1, -1, -1, -1, -1, -1, -1, 71*b285192aSMauro Carvalho Chehab -1, -1, -1, -1, -1, -1, -1, -1 }; 72*b285192aSMauro Carvalho Chehab static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, 73*b285192aSMauro Carvalho Chehab -1, -1, -1, -1, -1, -1, -1, -1, 74*b285192aSMauro Carvalho Chehab -1, -1, -1, -1, -1, -1, -1, -1, 75*b285192aSMauro Carvalho Chehab -1, -1, -1, -1, -1, -1, -1, -1 }; 76*b285192aSMauro Carvalho Chehab static unsigned cardtype_c = 1; 77*b285192aSMauro Carvalho Chehab static unsigned tuner_c = 1; 78*b285192aSMauro Carvalho Chehab static unsigned radio_c = 1; 79*b285192aSMauro Carvalho Chehab static char pal[] = "--"; 80*b285192aSMauro Carvalho Chehab static char secam[] = "--"; 81*b285192aSMauro Carvalho Chehab static char ntsc[] = "-"; 82*b285192aSMauro Carvalho Chehab 83*b285192aSMauro Carvalho Chehab /* Buffers */ 84*b285192aSMauro Carvalho Chehab static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS; 85*b285192aSMauro Carvalho Chehab static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS; 86*b285192aSMauro Carvalho Chehab static int enc_idx_buffers = CX18_DEFAULT_ENC_IDX_BUFFERS; 87*b285192aSMauro Carvalho Chehab static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS; 88*b285192aSMauro Carvalho Chehab static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS; 89*b285192aSMauro Carvalho Chehab static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS; 90*b285192aSMauro Carvalho Chehab 91*b285192aSMauro Carvalho Chehab static int enc_ts_bufsize = CX18_DEFAULT_ENC_TS_BUFSIZE; 92*b285192aSMauro Carvalho Chehab static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE; 93*b285192aSMauro Carvalho Chehab static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE; 94*b285192aSMauro Carvalho Chehab static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE; 95*b285192aSMauro Carvalho Chehab static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE; 96*b285192aSMauro Carvalho Chehab 97*b285192aSMauro Carvalho Chehab static int enc_ts_bufs = -1; 98*b285192aSMauro Carvalho Chehab static int enc_mpg_bufs = -1; 99*b285192aSMauro Carvalho Chehab static int enc_idx_bufs = CX18_MAX_FW_MDLS_PER_STREAM; 100*b285192aSMauro Carvalho Chehab static int enc_yuv_bufs = -1; 101*b285192aSMauro Carvalho Chehab static int enc_vbi_bufs = -1; 102*b285192aSMauro Carvalho Chehab static int enc_pcm_bufs = -1; 103*b285192aSMauro Carvalho Chehab 104*b285192aSMauro Carvalho Chehab 105*b285192aSMauro Carvalho Chehab static int cx18_pci_latency = 1; 106*b285192aSMauro Carvalho Chehab 107*b285192aSMauro Carvalho Chehab static int mmio_ndelay; 108*b285192aSMauro Carvalho Chehab static int retry_mmio = 1; 109*b285192aSMauro Carvalho Chehab 110*b285192aSMauro Carvalho Chehab int cx18_debug; 111*b285192aSMauro Carvalho Chehab 112*b285192aSMauro Carvalho Chehab module_param_array(tuner, int, &tuner_c, 0644); 113*b285192aSMauro Carvalho Chehab module_param_array(radio, int, &radio_c, 0644); 114*b285192aSMauro Carvalho Chehab module_param_array(cardtype, int, &cardtype_c, 0644); 115*b285192aSMauro Carvalho Chehab module_param_string(pal, pal, sizeof(pal), 0644); 116*b285192aSMauro Carvalho Chehab module_param_string(secam, secam, sizeof(secam), 0644); 117*b285192aSMauro Carvalho Chehab module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); 118*b285192aSMauro Carvalho Chehab module_param_named(debug, cx18_debug, int, 0644); 119*b285192aSMauro Carvalho Chehab module_param(mmio_ndelay, int, 0644); 120*b285192aSMauro Carvalho Chehab module_param(retry_mmio, int, 0644); 121*b285192aSMauro Carvalho Chehab module_param(cx18_pci_latency, int, 0644); 122*b285192aSMauro Carvalho Chehab module_param(cx18_first_minor, int, 0644); 123*b285192aSMauro Carvalho Chehab 124*b285192aSMauro Carvalho Chehab module_param(enc_ts_buffers, int, 0644); 125*b285192aSMauro Carvalho Chehab module_param(enc_mpg_buffers, int, 0644); 126*b285192aSMauro Carvalho Chehab module_param(enc_idx_buffers, int, 0644); 127*b285192aSMauro Carvalho Chehab module_param(enc_yuv_buffers, int, 0644); 128*b285192aSMauro Carvalho Chehab module_param(enc_vbi_buffers, int, 0644); 129*b285192aSMauro Carvalho Chehab module_param(enc_pcm_buffers, int, 0644); 130*b285192aSMauro Carvalho Chehab 131*b285192aSMauro Carvalho Chehab module_param(enc_ts_bufsize, int, 0644); 132*b285192aSMauro Carvalho Chehab module_param(enc_mpg_bufsize, int, 0644); 133*b285192aSMauro Carvalho Chehab module_param(enc_idx_bufsize, int, 0644); 134*b285192aSMauro Carvalho Chehab module_param(enc_yuv_bufsize, int, 0644); 135*b285192aSMauro Carvalho Chehab module_param(enc_pcm_bufsize, int, 0644); 136*b285192aSMauro Carvalho Chehab 137*b285192aSMauro Carvalho Chehab module_param(enc_ts_bufs, int, 0644); 138*b285192aSMauro Carvalho Chehab module_param(enc_mpg_bufs, int, 0644); 139*b285192aSMauro Carvalho Chehab module_param(enc_idx_bufs, int, 0644); 140*b285192aSMauro Carvalho Chehab module_param(enc_yuv_bufs, int, 0644); 141*b285192aSMauro Carvalho Chehab module_param(enc_vbi_bufs, int, 0644); 142*b285192aSMauro Carvalho Chehab module_param(enc_pcm_bufs, int, 0644); 143*b285192aSMauro Carvalho Chehab 144*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(tuner, "Tuner type selection,\n" 145*b285192aSMauro Carvalho Chehab "\t\t\tsee tuner.h for values"); 146*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(radio, 147*b285192aSMauro Carvalho Chehab "Enable or disable the radio. Use only if autodetection\n" 148*b285192aSMauro Carvalho Chehab "\t\t\tfails. 0 = disable, 1 = enable"); 149*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(cardtype, 150*b285192aSMauro Carvalho Chehab "Only use this option if your card is not detected properly.\n" 151*b285192aSMauro Carvalho Chehab "\t\tSpecify card type:\n" 152*b285192aSMauro Carvalho Chehab "\t\t\t 1 = Hauppauge HVR 1600 (ESMT memory)\n" 153*b285192aSMauro Carvalho Chehab "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n" 154*b285192aSMauro Carvalho Chehab "\t\t\t 3 = Compro VideoMate H900\n" 155*b285192aSMauro Carvalho Chehab "\t\t\t 4 = Yuan MPC718\n" 156*b285192aSMauro Carvalho Chehab "\t\t\t 5 = Conexant Raptor PAL/SECAM\n" 157*b285192aSMauro Carvalho Chehab "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n" 158*b285192aSMauro Carvalho Chehab "\t\t\t 7 = Leadtek WinFast PVR2100\n" 159*b285192aSMauro Carvalho Chehab "\t\t\t 8 = Leadtek WinFast DVR3100 H\n" 160*b285192aSMauro Carvalho Chehab "\t\t\t 9 = GoTView PCI DVD3 Hybrid\n" 161*b285192aSMauro Carvalho Chehab "\t\t\t 10 = Hauppauge HVR 1600 (S5H1411)\n" 162*b285192aSMauro Carvalho Chehab "\t\t\t 0 = Autodetect (default)\n" 163*b285192aSMauro Carvalho Chehab "\t\t\t-1 = Ignore this card\n\t\t"); 164*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); 165*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC"); 166*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K"); 167*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(debug, 168*b285192aSMauro Carvalho Chehab "Debug level (bitmask). Default: 0\n" 169*b285192aSMauro Carvalho Chehab "\t\t\t 1/0x0001: warning\n" 170*b285192aSMauro Carvalho Chehab "\t\t\t 2/0x0002: info\n" 171*b285192aSMauro Carvalho Chehab "\t\t\t 4/0x0004: mailbox\n" 172*b285192aSMauro Carvalho Chehab "\t\t\t 8/0x0008: dma\n" 173*b285192aSMauro Carvalho Chehab "\t\t\t 16/0x0010: ioctl\n" 174*b285192aSMauro Carvalho Chehab "\t\t\t 32/0x0020: file\n" 175*b285192aSMauro Carvalho Chehab "\t\t\t 64/0x0040: i2c\n" 176*b285192aSMauro Carvalho Chehab "\t\t\t128/0x0080: irq\n" 177*b285192aSMauro Carvalho Chehab "\t\t\t256/0x0100: high volume\n"); 178*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(cx18_pci_latency, 179*b285192aSMauro Carvalho Chehab "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" 180*b285192aSMauro Carvalho Chehab "\t\t\tDefault: Yes"); 181*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(retry_mmio, 182*b285192aSMauro Carvalho Chehab "(Deprecated) MMIO writes are now always checked and retried\n" 183*b285192aSMauro Carvalho Chehab "\t\t\tEffectively: 1 [Yes]"); 184*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(mmio_ndelay, 185*b285192aSMauro Carvalho Chehab "(Deprecated) MMIO accesses are now never purposely delayed\n" 186*b285192aSMauro Carvalho Chehab "\t\t\tEffectively: 0 ns"); 187*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_ts_buffers, 188*b285192aSMauro Carvalho Chehab "Encoder TS buffer memory (MB). (enc_ts_bufs can override)\n" 189*b285192aSMauro Carvalho Chehab "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS)); 190*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_ts_bufsize, 191*b285192aSMauro Carvalho Chehab "Size of an encoder TS buffer (kB)\n" 192*b285192aSMauro Carvalho Chehab "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFSIZE)); 193*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_ts_bufs, 194*b285192aSMauro Carvalho Chehab "Number of encoder TS buffers\n" 195*b285192aSMauro Carvalho Chehab "\t\t\tDefault is computed from other enc_ts_* parameters"); 196*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_mpg_buffers, 197*b285192aSMauro Carvalho Chehab "Encoder MPG buffer memory (MB). (enc_mpg_bufs can override)\n" 198*b285192aSMauro Carvalho Chehab "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); 199*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_mpg_bufsize, 200*b285192aSMauro Carvalho Chehab "Size of an encoder MPG buffer (kB)\n" 201*b285192aSMauro Carvalho Chehab "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFSIZE)); 202*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_mpg_bufs, 203*b285192aSMauro Carvalho Chehab "Number of encoder MPG buffers\n" 204*b285192aSMauro Carvalho Chehab "\t\t\tDefault is computed from other enc_mpg_* parameters"); 205*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_idx_buffers, 206*b285192aSMauro Carvalho Chehab "(Deprecated) Encoder IDX buffer memory (MB)\n" 207*b285192aSMauro Carvalho Chehab "\t\t\tIgnored, except 0 disables IDX buffer allocations\n" 208*b285192aSMauro Carvalho Chehab "\t\t\tDefault: 1 [Enabled]"); 209*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_idx_bufsize, 210*b285192aSMauro Carvalho Chehab "Size of an encoder IDX buffer (kB)\n" 211*b285192aSMauro Carvalho Chehab "\t\t\tAllowed values are multiples of 1.5 kB rounded up\n" 212*b285192aSMauro Carvalho Chehab "\t\t\t(multiples of size required for 64 index entries)\n" 213*b285192aSMauro Carvalho Chehab "\t\t\tDefault: 2"); 214*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_idx_bufs, 215*b285192aSMauro Carvalho Chehab "Number of encoder IDX buffers\n" 216*b285192aSMauro Carvalho Chehab "\t\t\tDefault: " __stringify(CX18_MAX_FW_MDLS_PER_STREAM)); 217*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_yuv_buffers, 218*b285192aSMauro Carvalho Chehab "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n" 219*b285192aSMauro Carvalho Chehab "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); 220*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_yuv_bufsize, 221*b285192aSMauro Carvalho Chehab "Size of an encoder YUV buffer (kB)\n" 222*b285192aSMauro Carvalho Chehab "\t\t\tAllowed values are multiples of 33.75 kB rounded up\n" 223*b285192aSMauro Carvalho Chehab "\t\t\t(multiples of size required for 32 screen lines)\n" 224*b285192aSMauro Carvalho Chehab "\t\t\tDefault: 102"); 225*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_yuv_bufs, 226*b285192aSMauro Carvalho Chehab "Number of encoder YUV buffers\n" 227*b285192aSMauro Carvalho Chehab "\t\t\tDefault is computed from other enc_yuv_* parameters"); 228*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_vbi_buffers, 229*b285192aSMauro Carvalho Chehab "Encoder VBI buffer memory (MB). (enc_vbi_bufs can override)\n" 230*b285192aSMauro Carvalho Chehab "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS)); 231*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_vbi_bufs, 232*b285192aSMauro Carvalho Chehab "Number of encoder VBI buffers\n" 233*b285192aSMauro Carvalho Chehab "\t\t\tDefault is computed from enc_vbi_buffers"); 234*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_pcm_buffers, 235*b285192aSMauro Carvalho Chehab "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n" 236*b285192aSMauro Carvalho Chehab "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); 237*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_pcm_bufsize, 238*b285192aSMauro Carvalho Chehab "Size of an encoder PCM buffer (kB)\n" 239*b285192aSMauro Carvalho Chehab "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFSIZE)); 240*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(enc_pcm_bufs, 241*b285192aSMauro Carvalho Chehab "Number of encoder PCM buffers\n" 242*b285192aSMauro Carvalho Chehab "\t\t\tDefault is computed from other enc_pcm_* parameters"); 243*b285192aSMauro Carvalho Chehab 244*b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(cx18_first_minor, 245*b285192aSMauro Carvalho Chehab "Set device node number assigned to first card"); 246*b285192aSMauro Carvalho Chehab 247*b285192aSMauro Carvalho Chehab MODULE_AUTHOR("Hans Verkuil"); 248*b285192aSMauro Carvalho Chehab MODULE_DESCRIPTION("CX23418 driver"); 249*b285192aSMauro Carvalho Chehab MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder"); 250*b285192aSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 251*b285192aSMauro Carvalho Chehab 252*b285192aSMauro Carvalho Chehab MODULE_VERSION(CX18_VERSION); 253*b285192aSMauro Carvalho Chehab 254*b285192aSMauro Carvalho Chehab #if defined(CONFIG_MODULES) && defined(MODULE) 255*b285192aSMauro Carvalho Chehab static void request_module_async(struct work_struct *work) 256*b285192aSMauro Carvalho Chehab { 257*b285192aSMauro Carvalho Chehab struct cx18 *dev = container_of(work, struct cx18, request_module_wk); 258*b285192aSMauro Carvalho Chehab 259*b285192aSMauro Carvalho Chehab /* Make sure cx18-alsa module is loaded */ 260*b285192aSMauro Carvalho Chehab request_module("cx18-alsa"); 261*b285192aSMauro Carvalho Chehab 262*b285192aSMauro Carvalho Chehab /* Initialize cx18-alsa for this instance of the cx18 device */ 263*b285192aSMauro Carvalho Chehab if (cx18_ext_init != NULL) 264*b285192aSMauro Carvalho Chehab cx18_ext_init(dev); 265*b285192aSMauro Carvalho Chehab } 266*b285192aSMauro Carvalho Chehab 267*b285192aSMauro Carvalho Chehab static void request_modules(struct cx18 *dev) 268*b285192aSMauro Carvalho Chehab { 269*b285192aSMauro Carvalho Chehab INIT_WORK(&dev->request_module_wk, request_module_async); 270*b285192aSMauro Carvalho Chehab schedule_work(&dev->request_module_wk); 271*b285192aSMauro Carvalho Chehab } 272*b285192aSMauro Carvalho Chehab 273*b285192aSMauro Carvalho Chehab static void flush_request_modules(struct cx18 *dev) 274*b285192aSMauro Carvalho Chehab { 275*b285192aSMauro Carvalho Chehab flush_work_sync(&dev->request_module_wk); 276*b285192aSMauro Carvalho Chehab } 277*b285192aSMauro Carvalho Chehab #else 278*b285192aSMauro Carvalho Chehab #define request_modules(dev) 279*b285192aSMauro Carvalho Chehab #define flush_request_modules(dev) 280*b285192aSMauro Carvalho Chehab #endif /* CONFIG_MODULES */ 281*b285192aSMauro Carvalho Chehab 282*b285192aSMauro Carvalho Chehab /* Generic utility functions */ 283*b285192aSMauro Carvalho Chehab int cx18_msleep_timeout(unsigned int msecs, int intr) 284*b285192aSMauro Carvalho Chehab { 285*b285192aSMauro Carvalho Chehab long int timeout = msecs_to_jiffies(msecs); 286*b285192aSMauro Carvalho Chehab int sig; 287*b285192aSMauro Carvalho Chehab 288*b285192aSMauro Carvalho Chehab do { 289*b285192aSMauro Carvalho Chehab set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 290*b285192aSMauro Carvalho Chehab timeout = schedule_timeout(timeout); 291*b285192aSMauro Carvalho Chehab sig = intr ? signal_pending(current) : 0; 292*b285192aSMauro Carvalho Chehab } while (!sig && timeout); 293*b285192aSMauro Carvalho Chehab return sig; 294*b285192aSMauro Carvalho Chehab } 295*b285192aSMauro Carvalho Chehab 296*b285192aSMauro Carvalho Chehab /* Release ioremapped memory */ 297*b285192aSMauro Carvalho Chehab static void cx18_iounmap(struct cx18 *cx) 298*b285192aSMauro Carvalho Chehab { 299*b285192aSMauro Carvalho Chehab if (cx == NULL) 300*b285192aSMauro Carvalho Chehab return; 301*b285192aSMauro Carvalho Chehab 302*b285192aSMauro Carvalho Chehab /* Release io memory */ 303*b285192aSMauro Carvalho Chehab if (cx->enc_mem != NULL) { 304*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("releasing enc_mem\n"); 305*b285192aSMauro Carvalho Chehab iounmap(cx->enc_mem); 306*b285192aSMauro Carvalho Chehab cx->enc_mem = NULL; 307*b285192aSMauro Carvalho Chehab } 308*b285192aSMauro Carvalho Chehab } 309*b285192aSMauro Carvalho Chehab 310*b285192aSMauro Carvalho Chehab static void cx18_eeprom_dump(struct cx18 *cx, unsigned char *eedata, int len) 311*b285192aSMauro Carvalho Chehab { 312*b285192aSMauro Carvalho Chehab int i; 313*b285192aSMauro Carvalho Chehab 314*b285192aSMauro Carvalho Chehab CX18_INFO("eeprom dump:\n"); 315*b285192aSMauro Carvalho Chehab for (i = 0; i < len; i++) { 316*b285192aSMauro Carvalho Chehab if (0 == (i % 16)) 317*b285192aSMauro Carvalho Chehab CX18_INFO("eeprom %02x:", i); 318*b285192aSMauro Carvalho Chehab printk(KERN_CONT " %02x", eedata[i]); 319*b285192aSMauro Carvalho Chehab if (15 == (i % 16)) 320*b285192aSMauro Carvalho Chehab printk(KERN_CONT "\n"); 321*b285192aSMauro Carvalho Chehab } 322*b285192aSMauro Carvalho Chehab } 323*b285192aSMauro Carvalho Chehab 324*b285192aSMauro Carvalho Chehab /* Hauppauge card? get values from tveeprom */ 325*b285192aSMauro Carvalho Chehab void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) 326*b285192aSMauro Carvalho Chehab { 327*b285192aSMauro Carvalho Chehab struct i2c_client c; 328*b285192aSMauro Carvalho Chehab u8 eedata[256]; 329*b285192aSMauro Carvalho Chehab 330*b285192aSMauro Carvalho Chehab memset(&c, 0, sizeof(c)); 331*b285192aSMauro Carvalho Chehab strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); 332*b285192aSMauro Carvalho Chehab c.adapter = &cx->i2c_adap[0]; 333*b285192aSMauro Carvalho Chehab c.addr = 0xA0 >> 1; 334*b285192aSMauro Carvalho Chehab 335*b285192aSMauro Carvalho Chehab memset(tv, 0, sizeof(*tv)); 336*b285192aSMauro Carvalho Chehab if (tveeprom_read(&c, eedata, sizeof(eedata))) 337*b285192aSMauro Carvalho Chehab return; 338*b285192aSMauro Carvalho Chehab 339*b285192aSMauro Carvalho Chehab switch (cx->card->type) { 340*b285192aSMauro Carvalho Chehab case CX18_CARD_HVR_1600_ESMT: 341*b285192aSMauro Carvalho Chehab case CX18_CARD_HVR_1600_SAMSUNG: 342*b285192aSMauro Carvalho Chehab case CX18_CARD_HVR_1600_S5H1411: 343*b285192aSMauro Carvalho Chehab tveeprom_hauppauge_analog(&c, tv, eedata); 344*b285192aSMauro Carvalho Chehab break; 345*b285192aSMauro Carvalho Chehab case CX18_CARD_YUAN_MPC718: 346*b285192aSMauro Carvalho Chehab case CX18_CARD_GOTVIEW_PCI_DVD3: 347*b285192aSMauro Carvalho Chehab tv->model = 0x718; 348*b285192aSMauro Carvalho Chehab cx18_eeprom_dump(cx, eedata, sizeof(eedata)); 349*b285192aSMauro Carvalho Chehab CX18_INFO("eeprom PCI ID: %02x%02x:%02x%02x\n", 350*b285192aSMauro Carvalho Chehab eedata[2], eedata[1], eedata[4], eedata[3]); 351*b285192aSMauro Carvalho Chehab break; 352*b285192aSMauro Carvalho Chehab default: 353*b285192aSMauro Carvalho Chehab tv->model = 0xffffffff; 354*b285192aSMauro Carvalho Chehab cx18_eeprom_dump(cx, eedata, sizeof(eedata)); 355*b285192aSMauro Carvalho Chehab break; 356*b285192aSMauro Carvalho Chehab } 357*b285192aSMauro Carvalho Chehab } 358*b285192aSMauro Carvalho Chehab 359*b285192aSMauro Carvalho Chehab static void cx18_process_eeprom(struct cx18 *cx) 360*b285192aSMauro Carvalho Chehab { 361*b285192aSMauro Carvalho Chehab struct tveeprom tv; 362*b285192aSMauro Carvalho Chehab 363*b285192aSMauro Carvalho Chehab cx18_read_eeprom(cx, &tv); 364*b285192aSMauro Carvalho Chehab 365*b285192aSMauro Carvalho Chehab /* Many thanks to Steven Toth from Hauppauge for providing the 366*b285192aSMauro Carvalho Chehab model numbers */ 367*b285192aSMauro Carvalho Chehab /* Note: the Samsung memory models cannot be reliably determined 368*b285192aSMauro Carvalho Chehab from the model number. Use the cardtype module option if you 369*b285192aSMauro Carvalho Chehab have one of these preproduction models. */ 370*b285192aSMauro Carvalho Chehab switch (tv.model) { 371*b285192aSMauro Carvalho Chehab case 74301: /* Retail models */ 372*b285192aSMauro Carvalho Chehab case 74321: 373*b285192aSMauro Carvalho Chehab case 74351: /* OEM models */ 374*b285192aSMauro Carvalho Chehab case 74361: 375*b285192aSMauro Carvalho Chehab /* Digital side is s5h1411/tda18271 */ 376*b285192aSMauro Carvalho Chehab cx->card = cx18_get_card(CX18_CARD_HVR_1600_S5H1411); 377*b285192aSMauro Carvalho Chehab break; 378*b285192aSMauro Carvalho Chehab case 74021: /* Retail models */ 379*b285192aSMauro Carvalho Chehab case 74031: 380*b285192aSMauro Carvalho Chehab case 74041: 381*b285192aSMauro Carvalho Chehab case 74141: 382*b285192aSMauro Carvalho Chehab case 74541: /* OEM models */ 383*b285192aSMauro Carvalho Chehab case 74551: 384*b285192aSMauro Carvalho Chehab case 74591: 385*b285192aSMauro Carvalho Chehab case 74651: 386*b285192aSMauro Carvalho Chehab case 74691: 387*b285192aSMauro Carvalho Chehab case 74751: 388*b285192aSMauro Carvalho Chehab case 74891: 389*b285192aSMauro Carvalho Chehab /* Digital side is s5h1409/mxl5005s */ 390*b285192aSMauro Carvalho Chehab cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); 391*b285192aSMauro Carvalho Chehab break; 392*b285192aSMauro Carvalho Chehab case 0x718: 393*b285192aSMauro Carvalho Chehab return; 394*b285192aSMauro Carvalho Chehab case 0xffffffff: 395*b285192aSMauro Carvalho Chehab CX18_INFO("Unknown EEPROM encoding\n"); 396*b285192aSMauro Carvalho Chehab return; 397*b285192aSMauro Carvalho Chehab case 0: 398*b285192aSMauro Carvalho Chehab CX18_ERR("Invalid EEPROM\n"); 399*b285192aSMauro Carvalho Chehab return; 400*b285192aSMauro Carvalho Chehab default: 401*b285192aSMauro Carvalho Chehab CX18_ERR("Unknown model %d, defaulting to original HVR-1600 " 402*b285192aSMauro Carvalho Chehab "(cardtype=1)\n", tv.model); 403*b285192aSMauro Carvalho Chehab cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); 404*b285192aSMauro Carvalho Chehab break; 405*b285192aSMauro Carvalho Chehab } 406*b285192aSMauro Carvalho Chehab 407*b285192aSMauro Carvalho Chehab cx->v4l2_cap = cx->card->v4l2_capabilities; 408*b285192aSMauro Carvalho Chehab cx->card_name = cx->card->name; 409*b285192aSMauro Carvalho Chehab cx->card_i2c = cx->card->i2c; 410*b285192aSMauro Carvalho Chehab 411*b285192aSMauro Carvalho Chehab CX18_INFO("Autodetected %s\n", cx->card_name); 412*b285192aSMauro Carvalho Chehab 413*b285192aSMauro Carvalho Chehab if (tv.tuner_type == TUNER_ABSENT) 414*b285192aSMauro Carvalho Chehab CX18_ERR("tveeprom cannot autodetect tuner!\n"); 415*b285192aSMauro Carvalho Chehab 416*b285192aSMauro Carvalho Chehab if (cx->options.tuner == -1) 417*b285192aSMauro Carvalho Chehab cx->options.tuner = tv.tuner_type; 418*b285192aSMauro Carvalho Chehab if (cx->options.radio == -1) 419*b285192aSMauro Carvalho Chehab cx->options.radio = (tv.has_radio != 0); 420*b285192aSMauro Carvalho Chehab 421*b285192aSMauro Carvalho Chehab if (cx->std != 0) 422*b285192aSMauro Carvalho Chehab /* user specified tuner standard */ 423*b285192aSMauro Carvalho Chehab return; 424*b285192aSMauro Carvalho Chehab 425*b285192aSMauro Carvalho Chehab /* autodetect tuner standard */ 426*b285192aSMauro Carvalho Chehab #define TVEEPROM_TUNER_FORMAT_ALL (V4L2_STD_B | V4L2_STD_GH | \ 427*b285192aSMauro Carvalho Chehab V4L2_STD_MN | \ 428*b285192aSMauro Carvalho Chehab V4L2_STD_PAL_I | \ 429*b285192aSMauro Carvalho Chehab V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC | \ 430*b285192aSMauro Carvalho Chehab V4L2_STD_DK) 431*b285192aSMauro Carvalho Chehab if ((tv.tuner_formats & TVEEPROM_TUNER_FORMAT_ALL) 432*b285192aSMauro Carvalho Chehab == TVEEPROM_TUNER_FORMAT_ALL) { 433*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("Worldwide tuner detected\n"); 434*b285192aSMauro Carvalho Chehab cx->std = V4L2_STD_ALL; 435*b285192aSMauro Carvalho Chehab } else if (tv.tuner_formats & V4L2_STD_PAL) { 436*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("PAL tuner detected\n"); 437*b285192aSMauro Carvalho Chehab cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H; 438*b285192aSMauro Carvalho Chehab } else if (tv.tuner_formats & V4L2_STD_NTSC) { 439*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("NTSC tuner detected\n"); 440*b285192aSMauro Carvalho Chehab cx->std |= V4L2_STD_NTSC_M; 441*b285192aSMauro Carvalho Chehab } else if (tv.tuner_formats & V4L2_STD_SECAM) { 442*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("SECAM tuner detected\n"); 443*b285192aSMauro Carvalho Chehab cx->std |= V4L2_STD_SECAM_L; 444*b285192aSMauro Carvalho Chehab } else { 445*b285192aSMauro Carvalho Chehab CX18_INFO("No tuner detected, default to NTSC-M\n"); 446*b285192aSMauro Carvalho Chehab cx->std |= V4L2_STD_NTSC_M; 447*b285192aSMauro Carvalho Chehab } 448*b285192aSMauro Carvalho Chehab } 449*b285192aSMauro Carvalho Chehab 450*b285192aSMauro Carvalho Chehab static v4l2_std_id cx18_parse_std(struct cx18 *cx) 451*b285192aSMauro Carvalho Chehab { 452*b285192aSMauro Carvalho Chehab switch (pal[0]) { 453*b285192aSMauro Carvalho Chehab case '6': 454*b285192aSMauro Carvalho Chehab return V4L2_STD_PAL_60; 455*b285192aSMauro Carvalho Chehab case 'b': 456*b285192aSMauro Carvalho Chehab case 'B': 457*b285192aSMauro Carvalho Chehab case 'g': 458*b285192aSMauro Carvalho Chehab case 'G': 459*b285192aSMauro Carvalho Chehab return V4L2_STD_PAL_BG; 460*b285192aSMauro Carvalho Chehab case 'h': 461*b285192aSMauro Carvalho Chehab case 'H': 462*b285192aSMauro Carvalho Chehab return V4L2_STD_PAL_H; 463*b285192aSMauro Carvalho Chehab case 'n': 464*b285192aSMauro Carvalho Chehab case 'N': 465*b285192aSMauro Carvalho Chehab if (pal[1] == 'c' || pal[1] == 'C') 466*b285192aSMauro Carvalho Chehab return V4L2_STD_PAL_Nc; 467*b285192aSMauro Carvalho Chehab return V4L2_STD_PAL_N; 468*b285192aSMauro Carvalho Chehab case 'i': 469*b285192aSMauro Carvalho Chehab case 'I': 470*b285192aSMauro Carvalho Chehab return V4L2_STD_PAL_I; 471*b285192aSMauro Carvalho Chehab case 'd': 472*b285192aSMauro Carvalho Chehab case 'D': 473*b285192aSMauro Carvalho Chehab case 'k': 474*b285192aSMauro Carvalho Chehab case 'K': 475*b285192aSMauro Carvalho Chehab return V4L2_STD_PAL_DK; 476*b285192aSMauro Carvalho Chehab case 'M': 477*b285192aSMauro Carvalho Chehab case 'm': 478*b285192aSMauro Carvalho Chehab return V4L2_STD_PAL_M; 479*b285192aSMauro Carvalho Chehab case '-': 480*b285192aSMauro Carvalho Chehab break; 481*b285192aSMauro Carvalho Chehab default: 482*b285192aSMauro Carvalho Chehab CX18_WARN("pal= argument not recognised\n"); 483*b285192aSMauro Carvalho Chehab return 0; 484*b285192aSMauro Carvalho Chehab } 485*b285192aSMauro Carvalho Chehab 486*b285192aSMauro Carvalho Chehab switch (secam[0]) { 487*b285192aSMauro Carvalho Chehab case 'b': 488*b285192aSMauro Carvalho Chehab case 'B': 489*b285192aSMauro Carvalho Chehab case 'g': 490*b285192aSMauro Carvalho Chehab case 'G': 491*b285192aSMauro Carvalho Chehab case 'h': 492*b285192aSMauro Carvalho Chehab case 'H': 493*b285192aSMauro Carvalho Chehab return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; 494*b285192aSMauro Carvalho Chehab case 'd': 495*b285192aSMauro Carvalho Chehab case 'D': 496*b285192aSMauro Carvalho Chehab case 'k': 497*b285192aSMauro Carvalho Chehab case 'K': 498*b285192aSMauro Carvalho Chehab return V4L2_STD_SECAM_DK; 499*b285192aSMauro Carvalho Chehab case 'l': 500*b285192aSMauro Carvalho Chehab case 'L': 501*b285192aSMauro Carvalho Chehab if (secam[1] == 'C' || secam[1] == 'c') 502*b285192aSMauro Carvalho Chehab return V4L2_STD_SECAM_LC; 503*b285192aSMauro Carvalho Chehab return V4L2_STD_SECAM_L; 504*b285192aSMauro Carvalho Chehab case '-': 505*b285192aSMauro Carvalho Chehab break; 506*b285192aSMauro Carvalho Chehab default: 507*b285192aSMauro Carvalho Chehab CX18_WARN("secam= argument not recognised\n"); 508*b285192aSMauro Carvalho Chehab return 0; 509*b285192aSMauro Carvalho Chehab } 510*b285192aSMauro Carvalho Chehab 511*b285192aSMauro Carvalho Chehab switch (ntsc[0]) { 512*b285192aSMauro Carvalho Chehab case 'm': 513*b285192aSMauro Carvalho Chehab case 'M': 514*b285192aSMauro Carvalho Chehab return V4L2_STD_NTSC_M; 515*b285192aSMauro Carvalho Chehab case 'j': 516*b285192aSMauro Carvalho Chehab case 'J': 517*b285192aSMauro Carvalho Chehab return V4L2_STD_NTSC_M_JP; 518*b285192aSMauro Carvalho Chehab case 'k': 519*b285192aSMauro Carvalho Chehab case 'K': 520*b285192aSMauro Carvalho Chehab return V4L2_STD_NTSC_M_KR; 521*b285192aSMauro Carvalho Chehab case '-': 522*b285192aSMauro Carvalho Chehab break; 523*b285192aSMauro Carvalho Chehab default: 524*b285192aSMauro Carvalho Chehab CX18_WARN("ntsc= argument not recognised\n"); 525*b285192aSMauro Carvalho Chehab return 0; 526*b285192aSMauro Carvalho Chehab } 527*b285192aSMauro Carvalho Chehab 528*b285192aSMauro Carvalho Chehab /* no match found */ 529*b285192aSMauro Carvalho Chehab return 0; 530*b285192aSMauro Carvalho Chehab } 531*b285192aSMauro Carvalho Chehab 532*b285192aSMauro Carvalho Chehab static void cx18_process_options(struct cx18 *cx) 533*b285192aSMauro Carvalho Chehab { 534*b285192aSMauro Carvalho Chehab int i, j; 535*b285192aSMauro Carvalho Chehab 536*b285192aSMauro Carvalho Chehab cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers; 537*b285192aSMauro Carvalho Chehab cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers; 538*b285192aSMauro Carvalho Chehab cx->options.megabytes[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_buffers; 539*b285192aSMauro Carvalho Chehab cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers; 540*b285192aSMauro Carvalho Chehab cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers; 541*b285192aSMauro Carvalho Chehab cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers; 542*b285192aSMauro Carvalho Chehab cx->options.megabytes[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control only */ 543*b285192aSMauro Carvalho Chehab 544*b285192aSMauro Carvalho Chehab cx->stream_buffers[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufs; 545*b285192aSMauro Carvalho Chehab cx->stream_buffers[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufs; 546*b285192aSMauro Carvalho Chehab cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufs; 547*b285192aSMauro Carvalho Chehab cx->stream_buffers[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufs; 548*b285192aSMauro Carvalho Chehab cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_bufs; 549*b285192aSMauro Carvalho Chehab cx->stream_buffers[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufs; 550*b285192aSMauro Carvalho Chehab cx->stream_buffers[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control, no data */ 551*b285192aSMauro Carvalho Chehab 552*b285192aSMauro Carvalho Chehab cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufsize; 553*b285192aSMauro Carvalho Chehab cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize; 554*b285192aSMauro Carvalho Chehab cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize; 555*b285192aSMauro Carvalho Chehab cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize; 556*b285192aSMauro Carvalho Chehab cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_active_samples * 36; 557*b285192aSMauro Carvalho Chehab cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize; 558*b285192aSMauro Carvalho Chehab cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */ 559*b285192aSMauro Carvalho Chehab 560*b285192aSMauro Carvalho Chehab /* Ensure stream_buffers & stream_buf_size are valid */ 561*b285192aSMauro Carvalho Chehab for (i = 0; i < CX18_MAX_STREAMS; i++) { 562*b285192aSMauro Carvalho Chehab if (cx->stream_buffers[i] == 0 || /* User said 0 buffers */ 563*b285192aSMauro Carvalho Chehab cx->options.megabytes[i] <= 0 || /* User said 0 MB total */ 564*b285192aSMauro Carvalho Chehab cx->stream_buf_size[i] <= 0) { /* User said buf size 0 */ 565*b285192aSMauro Carvalho Chehab cx->options.megabytes[i] = 0; 566*b285192aSMauro Carvalho Chehab cx->stream_buffers[i] = 0; 567*b285192aSMauro Carvalho Chehab cx->stream_buf_size[i] = 0; 568*b285192aSMauro Carvalho Chehab continue; 569*b285192aSMauro Carvalho Chehab } 570*b285192aSMauro Carvalho Chehab /* 571*b285192aSMauro Carvalho Chehab * YUV is a special case where the stream_buf_size needs to be 572*b285192aSMauro Carvalho Chehab * an integral multiple of 33.75 kB (storage for 32 screens 573*b285192aSMauro Carvalho Chehab * lines to maintain alignment in case of lost buffers). 574*b285192aSMauro Carvalho Chehab * 575*b285192aSMauro Carvalho Chehab * IDX is a special case where the stream_buf_size should be 576*b285192aSMauro Carvalho Chehab * an integral multiple of 1.5 kB (storage for 64 index entries 577*b285192aSMauro Carvalho Chehab * to maintain alignment in case of lost buffers). 578*b285192aSMauro Carvalho Chehab * 579*b285192aSMauro Carvalho Chehab */ 580*b285192aSMauro Carvalho Chehab if (i == CX18_ENC_STREAM_TYPE_YUV) { 581*b285192aSMauro Carvalho Chehab cx->stream_buf_size[i] *= 1024; 582*b285192aSMauro Carvalho Chehab cx->stream_buf_size[i] -= 583*b285192aSMauro Carvalho Chehab (cx->stream_buf_size[i] % CX18_UNIT_ENC_YUV_BUFSIZE); 584*b285192aSMauro Carvalho Chehab 585*b285192aSMauro Carvalho Chehab if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE) 586*b285192aSMauro Carvalho Chehab cx->stream_buf_size[i] = 587*b285192aSMauro Carvalho Chehab CX18_UNIT_ENC_YUV_BUFSIZE; 588*b285192aSMauro Carvalho Chehab } else if (i == CX18_ENC_STREAM_TYPE_IDX) { 589*b285192aSMauro Carvalho Chehab cx->stream_buf_size[i] *= 1024; 590*b285192aSMauro Carvalho Chehab cx->stream_buf_size[i] -= 591*b285192aSMauro Carvalho Chehab (cx->stream_buf_size[i] % CX18_UNIT_ENC_IDX_BUFSIZE); 592*b285192aSMauro Carvalho Chehab 593*b285192aSMauro Carvalho Chehab if (cx->stream_buf_size[i] < CX18_UNIT_ENC_IDX_BUFSIZE) 594*b285192aSMauro Carvalho Chehab cx->stream_buf_size[i] = 595*b285192aSMauro Carvalho Chehab CX18_UNIT_ENC_IDX_BUFSIZE; 596*b285192aSMauro Carvalho Chehab } 597*b285192aSMauro Carvalho Chehab /* 598*b285192aSMauro Carvalho Chehab * YUV and IDX are special cases where the stream_buf_size is 599*b285192aSMauro Carvalho Chehab * now in bytes. 600*b285192aSMauro Carvalho Chehab * VBI is a special case where the stream_buf_size is fixed 601*b285192aSMauro Carvalho Chehab * and already in bytes 602*b285192aSMauro Carvalho Chehab */ 603*b285192aSMauro Carvalho Chehab if (i == CX18_ENC_STREAM_TYPE_VBI || 604*b285192aSMauro Carvalho Chehab i == CX18_ENC_STREAM_TYPE_YUV || 605*b285192aSMauro Carvalho Chehab i == CX18_ENC_STREAM_TYPE_IDX) { 606*b285192aSMauro Carvalho Chehab if (cx->stream_buffers[i] < 0) { 607*b285192aSMauro Carvalho Chehab cx->stream_buffers[i] = 608*b285192aSMauro Carvalho Chehab cx->options.megabytes[i] * 1024 * 1024 609*b285192aSMauro Carvalho Chehab / cx->stream_buf_size[i]; 610*b285192aSMauro Carvalho Chehab } else { 611*b285192aSMauro Carvalho Chehab /* N.B. This might round down to 0 */ 612*b285192aSMauro Carvalho Chehab cx->options.megabytes[i] = 613*b285192aSMauro Carvalho Chehab cx->stream_buffers[i] 614*b285192aSMauro Carvalho Chehab * cx->stream_buf_size[i]/(1024 * 1024); 615*b285192aSMauro Carvalho Chehab } 616*b285192aSMauro Carvalho Chehab } else { 617*b285192aSMauro Carvalho Chehab /* All other streams have stream_buf_size in kB here */ 618*b285192aSMauro Carvalho Chehab if (cx->stream_buffers[i] < 0) { 619*b285192aSMauro Carvalho Chehab cx->stream_buffers[i] = 620*b285192aSMauro Carvalho Chehab cx->options.megabytes[i] * 1024 621*b285192aSMauro Carvalho Chehab / cx->stream_buf_size[i]; 622*b285192aSMauro Carvalho Chehab } else { 623*b285192aSMauro Carvalho Chehab /* N.B. This might round down to 0 */ 624*b285192aSMauro Carvalho Chehab cx->options.megabytes[i] = 625*b285192aSMauro Carvalho Chehab cx->stream_buffers[i] 626*b285192aSMauro Carvalho Chehab * cx->stream_buf_size[i] / 1024; 627*b285192aSMauro Carvalho Chehab } 628*b285192aSMauro Carvalho Chehab /* convert from kB to bytes */ 629*b285192aSMauro Carvalho Chehab cx->stream_buf_size[i] *= 1024; 630*b285192aSMauro Carvalho Chehab } 631*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, " 632*b285192aSMauro Carvalho Chehab "%d bytes\n", i, cx->options.megabytes[i], 633*b285192aSMauro Carvalho Chehab cx->stream_buffers[i], cx->stream_buf_size[i]); 634*b285192aSMauro Carvalho Chehab } 635*b285192aSMauro Carvalho Chehab 636*b285192aSMauro Carvalho Chehab cx->options.cardtype = cardtype[cx->instance]; 637*b285192aSMauro Carvalho Chehab cx->options.tuner = tuner[cx->instance]; 638*b285192aSMauro Carvalho Chehab cx->options.radio = radio[cx->instance]; 639*b285192aSMauro Carvalho Chehab 640*b285192aSMauro Carvalho Chehab cx->std = cx18_parse_std(cx); 641*b285192aSMauro Carvalho Chehab if (cx->options.cardtype == -1) { 642*b285192aSMauro Carvalho Chehab CX18_INFO("Ignore card\n"); 643*b285192aSMauro Carvalho Chehab return; 644*b285192aSMauro Carvalho Chehab } 645*b285192aSMauro Carvalho Chehab cx->card = cx18_get_card(cx->options.cardtype - 1); 646*b285192aSMauro Carvalho Chehab if (cx->card) 647*b285192aSMauro Carvalho Chehab CX18_INFO("User specified %s card\n", cx->card->name); 648*b285192aSMauro Carvalho Chehab else if (cx->options.cardtype != 0) 649*b285192aSMauro Carvalho Chehab CX18_ERR("Unknown user specified type, trying to autodetect card\n"); 650*b285192aSMauro Carvalho Chehab if (cx->card == NULL) { 651*b285192aSMauro Carvalho Chehab if (cx->pci_dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) { 652*b285192aSMauro Carvalho Chehab cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); 653*b285192aSMauro Carvalho Chehab CX18_INFO("Autodetected Hauppauge card\n"); 654*b285192aSMauro Carvalho Chehab } 655*b285192aSMauro Carvalho Chehab } 656*b285192aSMauro Carvalho Chehab if (cx->card == NULL) { 657*b285192aSMauro Carvalho Chehab for (i = 0; (cx->card = cx18_get_card(i)); i++) { 658*b285192aSMauro Carvalho Chehab if (cx->card->pci_list == NULL) 659*b285192aSMauro Carvalho Chehab continue; 660*b285192aSMauro Carvalho Chehab for (j = 0; cx->card->pci_list[j].device; j++) { 661*b285192aSMauro Carvalho Chehab if (cx->pci_dev->device != 662*b285192aSMauro Carvalho Chehab cx->card->pci_list[j].device) 663*b285192aSMauro Carvalho Chehab continue; 664*b285192aSMauro Carvalho Chehab if (cx->pci_dev->subsystem_vendor != 665*b285192aSMauro Carvalho Chehab cx->card->pci_list[j].subsystem_vendor) 666*b285192aSMauro Carvalho Chehab continue; 667*b285192aSMauro Carvalho Chehab if (cx->pci_dev->subsystem_device != 668*b285192aSMauro Carvalho Chehab cx->card->pci_list[j].subsystem_device) 669*b285192aSMauro Carvalho Chehab continue; 670*b285192aSMauro Carvalho Chehab CX18_INFO("Autodetected %s card\n", cx->card->name); 671*b285192aSMauro Carvalho Chehab goto done; 672*b285192aSMauro Carvalho Chehab } 673*b285192aSMauro Carvalho Chehab } 674*b285192aSMauro Carvalho Chehab } 675*b285192aSMauro Carvalho Chehab done: 676*b285192aSMauro Carvalho Chehab 677*b285192aSMauro Carvalho Chehab if (cx->card == NULL) { 678*b285192aSMauro Carvalho Chehab cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); 679*b285192aSMauro Carvalho Chehab CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n", 680*b285192aSMauro Carvalho Chehab cx->pci_dev->vendor, cx->pci_dev->device); 681*b285192aSMauro Carvalho Chehab CX18_ERR(" subsystem vendor/device: [%04x:%04x]\n", 682*b285192aSMauro Carvalho Chehab cx->pci_dev->subsystem_vendor, 683*b285192aSMauro Carvalho Chehab cx->pci_dev->subsystem_device); 684*b285192aSMauro Carvalho Chehab CX18_ERR("Defaulting to %s card\n", cx->card->name); 685*b285192aSMauro Carvalho Chehab CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); 686*b285192aSMauro Carvalho Chehab CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n"); 687*b285192aSMauro Carvalho Chehab CX18_ERR("Prefix your subject line with [UNKNOWN CX18 CARD].\n"); 688*b285192aSMauro Carvalho Chehab } 689*b285192aSMauro Carvalho Chehab cx->v4l2_cap = cx->card->v4l2_capabilities; 690*b285192aSMauro Carvalho Chehab cx->card_name = cx->card->name; 691*b285192aSMauro Carvalho Chehab cx->card_i2c = cx->card->i2c; 692*b285192aSMauro Carvalho Chehab } 693*b285192aSMauro Carvalho Chehab 694*b285192aSMauro Carvalho Chehab static int __devinit cx18_create_in_workq(struct cx18 *cx) 695*b285192aSMauro Carvalho Chehab { 696*b285192aSMauro Carvalho Chehab snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in", 697*b285192aSMauro Carvalho Chehab cx->v4l2_dev.name); 698*b285192aSMauro Carvalho Chehab cx->in_work_queue = alloc_ordered_workqueue(cx->in_workq_name, 0); 699*b285192aSMauro Carvalho Chehab if (cx->in_work_queue == NULL) { 700*b285192aSMauro Carvalho Chehab CX18_ERR("Unable to create incoming mailbox handler thread\n"); 701*b285192aSMauro Carvalho Chehab return -ENOMEM; 702*b285192aSMauro Carvalho Chehab } 703*b285192aSMauro Carvalho Chehab return 0; 704*b285192aSMauro Carvalho Chehab } 705*b285192aSMauro Carvalho Chehab 706*b285192aSMauro Carvalho Chehab static void __devinit cx18_init_in_work_orders(struct cx18 *cx) 707*b285192aSMauro Carvalho Chehab { 708*b285192aSMauro Carvalho Chehab int i; 709*b285192aSMauro Carvalho Chehab for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) { 710*b285192aSMauro Carvalho Chehab cx->in_work_order[i].cx = cx; 711*b285192aSMauro Carvalho Chehab cx->in_work_order[i].str = cx->epu_debug_str; 712*b285192aSMauro Carvalho Chehab INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler); 713*b285192aSMauro Carvalho Chehab } 714*b285192aSMauro Carvalho Chehab } 715*b285192aSMauro Carvalho Chehab 716*b285192aSMauro Carvalho Chehab /* Precondition: the cx18 structure has been memset to 0. Only 717*b285192aSMauro Carvalho Chehab the dev and instance fields have been filled in. 718*b285192aSMauro Carvalho Chehab No assumptions on the card type may be made here (see cx18_init_struct2 719*b285192aSMauro Carvalho Chehab for that). 720*b285192aSMauro Carvalho Chehab */ 721*b285192aSMauro Carvalho Chehab static int __devinit cx18_init_struct1(struct cx18 *cx) 722*b285192aSMauro Carvalho Chehab { 723*b285192aSMauro Carvalho Chehab int ret; 724*b285192aSMauro Carvalho Chehab 725*b285192aSMauro Carvalho Chehab cx->base_addr = pci_resource_start(cx->pci_dev, 0); 726*b285192aSMauro Carvalho Chehab 727*b285192aSMauro Carvalho Chehab mutex_init(&cx->serialize_lock); 728*b285192aSMauro Carvalho Chehab mutex_init(&cx->gpio_lock); 729*b285192aSMauro Carvalho Chehab mutex_init(&cx->epu2apu_mb_lock); 730*b285192aSMauro Carvalho Chehab mutex_init(&cx->epu2cpu_mb_lock); 731*b285192aSMauro Carvalho Chehab 732*b285192aSMauro Carvalho Chehab ret = cx18_create_in_workq(cx); 733*b285192aSMauro Carvalho Chehab if (ret) 734*b285192aSMauro Carvalho Chehab return ret; 735*b285192aSMauro Carvalho Chehab 736*b285192aSMauro Carvalho Chehab cx18_init_in_work_orders(cx); 737*b285192aSMauro Carvalho Chehab 738*b285192aSMauro Carvalho Chehab /* start counting open_id at 1 */ 739*b285192aSMauro Carvalho Chehab cx->open_id = 1; 740*b285192aSMauro Carvalho Chehab 741*b285192aSMauro Carvalho Chehab /* Initial settings */ 742*b285192aSMauro Carvalho Chehab cx->cxhdl.port = CX2341X_PORT_MEMORY; 743*b285192aSMauro Carvalho Chehab cx->cxhdl.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_SLICED_VBI; 744*b285192aSMauro Carvalho Chehab cx->cxhdl.ops = &cx18_cxhdl_ops; 745*b285192aSMauro Carvalho Chehab cx->cxhdl.func = cx18_api_func; 746*b285192aSMauro Carvalho Chehab cx->cxhdl.priv = &cx->streams[CX18_ENC_STREAM_TYPE_MPG]; 747*b285192aSMauro Carvalho Chehab ret = cx2341x_handler_init(&cx->cxhdl, 50); 748*b285192aSMauro Carvalho Chehab if (ret) 749*b285192aSMauro Carvalho Chehab return ret; 750*b285192aSMauro Carvalho Chehab cx->v4l2_dev.ctrl_handler = &cx->cxhdl.hdl; 751*b285192aSMauro Carvalho Chehab 752*b285192aSMauro Carvalho Chehab cx->temporal_strength = cx->cxhdl.video_temporal_filter->cur.val; 753*b285192aSMauro Carvalho Chehab cx->spatial_strength = cx->cxhdl.video_spatial_filter->cur.val; 754*b285192aSMauro Carvalho Chehab cx->filter_mode = cx->cxhdl.video_spatial_filter_mode->cur.val | 755*b285192aSMauro Carvalho Chehab (cx->cxhdl.video_temporal_filter_mode->cur.val << 1) | 756*b285192aSMauro Carvalho Chehab (cx->cxhdl.video_median_filter_type->cur.val << 2); 757*b285192aSMauro Carvalho Chehab 758*b285192aSMauro Carvalho Chehab init_waitqueue_head(&cx->cap_w); 759*b285192aSMauro Carvalho Chehab init_waitqueue_head(&cx->mb_apu_waitq); 760*b285192aSMauro Carvalho Chehab init_waitqueue_head(&cx->mb_cpu_waitq); 761*b285192aSMauro Carvalho Chehab init_waitqueue_head(&cx->dma_waitq); 762*b285192aSMauro Carvalho Chehab 763*b285192aSMauro Carvalho Chehab /* VBI */ 764*b285192aSMauro Carvalho Chehab cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; 765*b285192aSMauro Carvalho Chehab cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; 766*b285192aSMauro Carvalho Chehab 767*b285192aSMauro Carvalho Chehab /* IVTV style VBI insertion into MPEG streams */ 768*b285192aSMauro Carvalho Chehab INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_buf.list); 769*b285192aSMauro Carvalho Chehab INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.list); 770*b285192aSMauro Carvalho Chehab INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.buf_list); 771*b285192aSMauro Carvalho Chehab list_add(&cx->vbi.sliced_mpeg_buf.list, 772*b285192aSMauro Carvalho Chehab &cx->vbi.sliced_mpeg_mdl.buf_list); 773*b285192aSMauro Carvalho Chehab return 0; 774*b285192aSMauro Carvalho Chehab } 775*b285192aSMauro Carvalho Chehab 776*b285192aSMauro Carvalho Chehab /* Second initialization part. Here the card type has been 777*b285192aSMauro Carvalho Chehab autodetected. */ 778*b285192aSMauro Carvalho Chehab static void __devinit cx18_init_struct2(struct cx18 *cx) 779*b285192aSMauro Carvalho Chehab { 780*b285192aSMauro Carvalho Chehab int i; 781*b285192aSMauro Carvalho Chehab 782*b285192aSMauro Carvalho Chehab for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++) 783*b285192aSMauro Carvalho Chehab if (cx->card->video_inputs[i].video_type == 0) 784*b285192aSMauro Carvalho Chehab break; 785*b285192aSMauro Carvalho Chehab cx->nof_inputs = i; 786*b285192aSMauro Carvalho Chehab for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++) 787*b285192aSMauro Carvalho Chehab if (cx->card->audio_inputs[i].audio_type == 0) 788*b285192aSMauro Carvalho Chehab break; 789*b285192aSMauro Carvalho Chehab cx->nof_audio_inputs = i; 790*b285192aSMauro Carvalho Chehab 791*b285192aSMauro Carvalho Chehab /* Find tuner input */ 792*b285192aSMauro Carvalho Chehab for (i = 0; i < cx->nof_inputs; i++) { 793*b285192aSMauro Carvalho Chehab if (cx->card->video_inputs[i].video_type == 794*b285192aSMauro Carvalho Chehab CX18_CARD_INPUT_VID_TUNER) 795*b285192aSMauro Carvalho Chehab break; 796*b285192aSMauro Carvalho Chehab } 797*b285192aSMauro Carvalho Chehab if (i == cx->nof_inputs) 798*b285192aSMauro Carvalho Chehab i = 0; 799*b285192aSMauro Carvalho Chehab cx->active_input = i; 800*b285192aSMauro Carvalho Chehab cx->audio_input = cx->card->video_inputs[i].audio_index; 801*b285192aSMauro Carvalho Chehab } 802*b285192aSMauro Carvalho Chehab 803*b285192aSMauro Carvalho Chehab static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, 804*b285192aSMauro Carvalho Chehab const struct pci_device_id *pci_id) 805*b285192aSMauro Carvalho Chehab { 806*b285192aSMauro Carvalho Chehab u16 cmd; 807*b285192aSMauro Carvalho Chehab unsigned char pci_latency; 808*b285192aSMauro Carvalho Chehab 809*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("Enabling pci device\n"); 810*b285192aSMauro Carvalho Chehab 811*b285192aSMauro Carvalho Chehab if (pci_enable_device(pci_dev)) { 812*b285192aSMauro Carvalho Chehab CX18_ERR("Can't enable device %d!\n", cx->instance); 813*b285192aSMauro Carvalho Chehab return -EIO; 814*b285192aSMauro Carvalho Chehab } 815*b285192aSMauro Carvalho Chehab if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { 816*b285192aSMauro Carvalho Chehab CX18_ERR("No suitable DMA available, card %d\n", cx->instance); 817*b285192aSMauro Carvalho Chehab return -EIO; 818*b285192aSMauro Carvalho Chehab } 819*b285192aSMauro Carvalho Chehab if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) { 820*b285192aSMauro Carvalho Chehab CX18_ERR("Cannot request encoder memory region, card %d\n", 821*b285192aSMauro Carvalho Chehab cx->instance); 822*b285192aSMauro Carvalho Chehab return -EIO; 823*b285192aSMauro Carvalho Chehab } 824*b285192aSMauro Carvalho Chehab 825*b285192aSMauro Carvalho Chehab /* Enable bus mastering and memory mapped IO for the CX23418 */ 826*b285192aSMauro Carvalho Chehab pci_read_config_word(pci_dev, PCI_COMMAND, &cmd); 827*b285192aSMauro Carvalho Chehab cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; 828*b285192aSMauro Carvalho Chehab pci_write_config_word(pci_dev, PCI_COMMAND, cmd); 829*b285192aSMauro Carvalho Chehab 830*b285192aSMauro Carvalho Chehab cx->card_rev = pci_dev->revision; 831*b285192aSMauro Carvalho Chehab pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency); 832*b285192aSMauro Carvalho Chehab 833*b285192aSMauro Carvalho Chehab if (pci_latency < 64 && cx18_pci_latency) { 834*b285192aSMauro Carvalho Chehab CX18_INFO("Unreasonably low latency timer, " 835*b285192aSMauro Carvalho Chehab "setting to 64 (was %d)\n", pci_latency); 836*b285192aSMauro Carvalho Chehab pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, 64); 837*b285192aSMauro Carvalho Chehab pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency); 838*b285192aSMauro Carvalho Chehab } 839*b285192aSMauro Carvalho Chehab 840*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, " 841*b285192aSMauro Carvalho Chehab "irq: %d, latency: %d, memory: 0x%llx\n", 842*b285192aSMauro Carvalho Chehab cx->pci_dev->device, cx->card_rev, pci_dev->bus->number, 843*b285192aSMauro Carvalho Chehab PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn), 844*b285192aSMauro Carvalho Chehab cx->pci_dev->irq, pci_latency, (u64)cx->base_addr); 845*b285192aSMauro Carvalho Chehab 846*b285192aSMauro Carvalho Chehab return 0; 847*b285192aSMauro Carvalho Chehab } 848*b285192aSMauro Carvalho Chehab 849*b285192aSMauro Carvalho Chehab static void cx18_init_subdevs(struct cx18 *cx) 850*b285192aSMauro Carvalho Chehab { 851*b285192aSMauro Carvalho Chehab u32 hw = cx->card->hw_all; 852*b285192aSMauro Carvalho Chehab u32 device; 853*b285192aSMauro Carvalho Chehab int i; 854*b285192aSMauro Carvalho Chehab 855*b285192aSMauro Carvalho Chehab for (i = 0, device = 1; i < 32; i++, device <<= 1) { 856*b285192aSMauro Carvalho Chehab 857*b285192aSMauro Carvalho Chehab if (!(device & hw)) 858*b285192aSMauro Carvalho Chehab continue; 859*b285192aSMauro Carvalho Chehab 860*b285192aSMauro Carvalho Chehab switch (device) { 861*b285192aSMauro Carvalho Chehab case CX18_HW_DVB: 862*b285192aSMauro Carvalho Chehab case CX18_HW_TVEEPROM: 863*b285192aSMauro Carvalho Chehab /* These subordinate devices do not use probing */ 864*b285192aSMauro Carvalho Chehab cx->hw_flags |= device; 865*b285192aSMauro Carvalho Chehab break; 866*b285192aSMauro Carvalho Chehab case CX18_HW_418_AV: 867*b285192aSMauro Carvalho Chehab /* The A/V decoder gets probed earlier to set PLLs */ 868*b285192aSMauro Carvalho Chehab /* Just note that the card uses it (i.e. has analog) */ 869*b285192aSMauro Carvalho Chehab cx->hw_flags |= device; 870*b285192aSMauro Carvalho Chehab break; 871*b285192aSMauro Carvalho Chehab case CX18_HW_GPIO_RESET_CTRL: 872*b285192aSMauro Carvalho Chehab /* 873*b285192aSMauro Carvalho Chehab * The Reset Controller gets probed and added to 874*b285192aSMauro Carvalho Chehab * hw_flags earlier for i2c adapter/bus initialization 875*b285192aSMauro Carvalho Chehab */ 876*b285192aSMauro Carvalho Chehab break; 877*b285192aSMauro Carvalho Chehab case CX18_HW_GPIO_MUX: 878*b285192aSMauro Carvalho Chehab if (cx18_gpio_register(cx, device) == 0) 879*b285192aSMauro Carvalho Chehab cx->hw_flags |= device; 880*b285192aSMauro Carvalho Chehab break; 881*b285192aSMauro Carvalho Chehab default: 882*b285192aSMauro Carvalho Chehab if (cx18_i2c_register(cx, i) == 0) 883*b285192aSMauro Carvalho Chehab cx->hw_flags |= device; 884*b285192aSMauro Carvalho Chehab break; 885*b285192aSMauro Carvalho Chehab } 886*b285192aSMauro Carvalho Chehab } 887*b285192aSMauro Carvalho Chehab 888*b285192aSMauro Carvalho Chehab if (cx->hw_flags & CX18_HW_418_AV) 889*b285192aSMauro Carvalho Chehab cx->sd_av = cx18_find_hw(cx, CX18_HW_418_AV); 890*b285192aSMauro Carvalho Chehab 891*b285192aSMauro Carvalho Chehab if (cx->card->hw_muxer != 0) 892*b285192aSMauro Carvalho Chehab cx->sd_extmux = cx18_find_hw(cx, cx->card->hw_muxer); 893*b285192aSMauro Carvalho Chehab } 894*b285192aSMauro Carvalho Chehab 895*b285192aSMauro Carvalho Chehab static int __devinit cx18_probe(struct pci_dev *pci_dev, 896*b285192aSMauro Carvalho Chehab const struct pci_device_id *pci_id) 897*b285192aSMauro Carvalho Chehab { 898*b285192aSMauro Carvalho Chehab int retval = 0; 899*b285192aSMauro Carvalho Chehab int i; 900*b285192aSMauro Carvalho Chehab u32 devtype; 901*b285192aSMauro Carvalho Chehab struct cx18 *cx; 902*b285192aSMauro Carvalho Chehab 903*b285192aSMauro Carvalho Chehab /* FIXME - module parameter arrays constrain max instances */ 904*b285192aSMauro Carvalho Chehab i = atomic_inc_return(&cx18_instance) - 1; 905*b285192aSMauro Carvalho Chehab if (i >= CX18_MAX_CARDS) { 906*b285192aSMauro Carvalho Chehab printk(KERN_ERR "cx18: cannot manage card %d, driver has a " 907*b285192aSMauro Carvalho Chehab "limit of 0 - %d\n", i, CX18_MAX_CARDS - 1); 908*b285192aSMauro Carvalho Chehab return -ENOMEM; 909*b285192aSMauro Carvalho Chehab } 910*b285192aSMauro Carvalho Chehab 911*b285192aSMauro Carvalho Chehab cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC); 912*b285192aSMauro Carvalho Chehab if (cx == NULL) { 913*b285192aSMauro Carvalho Chehab printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n", 914*b285192aSMauro Carvalho Chehab i); 915*b285192aSMauro Carvalho Chehab return -ENOMEM; 916*b285192aSMauro Carvalho Chehab } 917*b285192aSMauro Carvalho Chehab cx->pci_dev = pci_dev; 918*b285192aSMauro Carvalho Chehab cx->instance = i; 919*b285192aSMauro Carvalho Chehab 920*b285192aSMauro Carvalho Chehab retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev); 921*b285192aSMauro Carvalho Chehab if (retval) { 922*b285192aSMauro Carvalho Chehab printk(KERN_ERR "cx18: v4l2_device_register of card %d failed" 923*b285192aSMauro Carvalho Chehab "\n", cx->instance); 924*b285192aSMauro Carvalho Chehab kfree(cx); 925*b285192aSMauro Carvalho Chehab return retval; 926*b285192aSMauro Carvalho Chehab } 927*b285192aSMauro Carvalho Chehab snprintf(cx->v4l2_dev.name, sizeof(cx->v4l2_dev.name), "cx18-%d", 928*b285192aSMauro Carvalho Chehab cx->instance); 929*b285192aSMauro Carvalho Chehab CX18_INFO("Initializing card %d\n", cx->instance); 930*b285192aSMauro Carvalho Chehab 931*b285192aSMauro Carvalho Chehab cx18_process_options(cx); 932*b285192aSMauro Carvalho Chehab if (cx->options.cardtype == -1) { 933*b285192aSMauro Carvalho Chehab retval = -ENODEV; 934*b285192aSMauro Carvalho Chehab goto err; 935*b285192aSMauro Carvalho Chehab } 936*b285192aSMauro Carvalho Chehab 937*b285192aSMauro Carvalho Chehab retval = cx18_init_struct1(cx); 938*b285192aSMauro Carvalho Chehab if (retval) 939*b285192aSMauro Carvalho Chehab goto err; 940*b285192aSMauro Carvalho Chehab 941*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("base addr: 0x%llx\n", (u64)cx->base_addr); 942*b285192aSMauro Carvalho Chehab 943*b285192aSMauro Carvalho Chehab /* PCI Device Setup */ 944*b285192aSMauro Carvalho Chehab retval = cx18_setup_pci(cx, pci_dev, pci_id); 945*b285192aSMauro Carvalho Chehab if (retval != 0) 946*b285192aSMauro Carvalho Chehab goto free_workqueues; 947*b285192aSMauro Carvalho Chehab 948*b285192aSMauro Carvalho Chehab /* map io memory */ 949*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", 950*b285192aSMauro Carvalho Chehab (u64)cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE); 951*b285192aSMauro Carvalho Chehab cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET, 952*b285192aSMauro Carvalho Chehab CX18_MEM_SIZE); 953*b285192aSMauro Carvalho Chehab if (!cx->enc_mem) { 954*b285192aSMauro Carvalho Chehab CX18_ERR("ioremap failed. Can't get a window into CX23418 " 955*b285192aSMauro Carvalho Chehab "memory and register space\n"); 956*b285192aSMauro Carvalho Chehab CX18_ERR("Each capture card with a CX23418 needs 64 MB of " 957*b285192aSMauro Carvalho Chehab "vmalloc address space for the window\n"); 958*b285192aSMauro Carvalho Chehab CX18_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); 959*b285192aSMauro Carvalho Chehab CX18_ERR("Use the vmalloc= kernel command line option to set " 960*b285192aSMauro Carvalho Chehab "VmallocTotal to a larger value\n"); 961*b285192aSMauro Carvalho Chehab retval = -ENOMEM; 962*b285192aSMauro Carvalho Chehab goto free_mem; 963*b285192aSMauro Carvalho Chehab } 964*b285192aSMauro Carvalho Chehab cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET; 965*b285192aSMauro Carvalho Chehab devtype = cx18_read_reg(cx, 0xC72028); 966*b285192aSMauro Carvalho Chehab switch (devtype & 0xff000000) { 967*b285192aSMauro Carvalho Chehab case 0xff000000: 968*b285192aSMauro Carvalho Chehab CX18_INFO("cx23418 revision %08x (A)\n", devtype); 969*b285192aSMauro Carvalho Chehab break; 970*b285192aSMauro Carvalho Chehab case 0x01000000: 971*b285192aSMauro Carvalho Chehab CX18_INFO("cx23418 revision %08x (B)\n", devtype); 972*b285192aSMauro Carvalho Chehab break; 973*b285192aSMauro Carvalho Chehab default: 974*b285192aSMauro Carvalho Chehab CX18_INFO("cx23418 revision %08x (Unknown)\n", devtype); 975*b285192aSMauro Carvalho Chehab break; 976*b285192aSMauro Carvalho Chehab } 977*b285192aSMauro Carvalho Chehab 978*b285192aSMauro Carvalho Chehab cx18_init_power(cx, 1); 979*b285192aSMauro Carvalho Chehab cx18_init_memory(cx); 980*b285192aSMauro Carvalho Chehab 981*b285192aSMauro Carvalho Chehab cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET); 982*b285192aSMauro Carvalho Chehab cx18_init_scb(cx); 983*b285192aSMauro Carvalho Chehab 984*b285192aSMauro Carvalho Chehab cx18_gpio_init(cx); 985*b285192aSMauro Carvalho Chehab 986*b285192aSMauro Carvalho Chehab /* Initialize integrated A/V decoder early to set PLLs, just in case */ 987*b285192aSMauro Carvalho Chehab retval = cx18_av_probe(cx); 988*b285192aSMauro Carvalho Chehab if (retval) { 989*b285192aSMauro Carvalho Chehab CX18_ERR("Could not register A/V decoder subdevice\n"); 990*b285192aSMauro Carvalho Chehab goto free_map; 991*b285192aSMauro Carvalho Chehab } 992*b285192aSMauro Carvalho Chehab 993*b285192aSMauro Carvalho Chehab /* Initialize GPIO Reset Controller to do chip resets during i2c init */ 994*b285192aSMauro Carvalho Chehab if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) { 995*b285192aSMauro Carvalho Chehab if (cx18_gpio_register(cx, CX18_HW_GPIO_RESET_CTRL) != 0) 996*b285192aSMauro Carvalho Chehab CX18_WARN("Could not register GPIO reset controller" 997*b285192aSMauro Carvalho Chehab "subdevice; proceeding anyway.\n"); 998*b285192aSMauro Carvalho Chehab else 999*b285192aSMauro Carvalho Chehab cx->hw_flags |= CX18_HW_GPIO_RESET_CTRL; 1000*b285192aSMauro Carvalho Chehab } 1001*b285192aSMauro Carvalho Chehab 1002*b285192aSMauro Carvalho Chehab /* active i2c */ 1003*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("activating i2c...\n"); 1004*b285192aSMauro Carvalho Chehab retval = init_cx18_i2c(cx); 1005*b285192aSMauro Carvalho Chehab if (retval) { 1006*b285192aSMauro Carvalho Chehab CX18_ERR("Could not initialize i2c\n"); 1007*b285192aSMauro Carvalho Chehab goto free_map; 1008*b285192aSMauro Carvalho Chehab } 1009*b285192aSMauro Carvalho Chehab 1010*b285192aSMauro Carvalho Chehab if (cx->card->hw_all & CX18_HW_TVEEPROM) { 1011*b285192aSMauro Carvalho Chehab /* Based on the model number the cardtype may be changed. 1012*b285192aSMauro Carvalho Chehab The PCI IDs are not always reliable. */ 1013*b285192aSMauro Carvalho Chehab const struct cx18_card *orig_card = cx->card; 1014*b285192aSMauro Carvalho Chehab cx18_process_eeprom(cx); 1015*b285192aSMauro Carvalho Chehab 1016*b285192aSMauro Carvalho Chehab if (cx->card != orig_card) { 1017*b285192aSMauro Carvalho Chehab /* Changed the cardtype; re-reset the I2C chips */ 1018*b285192aSMauro Carvalho Chehab cx18_gpio_init(cx); 1019*b285192aSMauro Carvalho Chehab cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, 1020*b285192aSMauro Carvalho Chehab core, reset, (u32) CX18_GPIO_RESET_I2C); 1021*b285192aSMauro Carvalho Chehab } 1022*b285192aSMauro Carvalho Chehab } 1023*b285192aSMauro Carvalho Chehab if (cx->card->comment) 1024*b285192aSMauro Carvalho Chehab CX18_INFO("%s", cx->card->comment); 1025*b285192aSMauro Carvalho Chehab if (cx->card->v4l2_capabilities == 0) { 1026*b285192aSMauro Carvalho Chehab retval = -ENODEV; 1027*b285192aSMauro Carvalho Chehab goto free_i2c; 1028*b285192aSMauro Carvalho Chehab } 1029*b285192aSMauro Carvalho Chehab cx18_init_memory(cx); 1030*b285192aSMauro Carvalho Chehab cx18_init_scb(cx); 1031*b285192aSMauro Carvalho Chehab 1032*b285192aSMauro Carvalho Chehab /* Register IRQ */ 1033*b285192aSMauro Carvalho Chehab retval = request_irq(cx->pci_dev->irq, cx18_irq_handler, 1034*b285192aSMauro Carvalho Chehab IRQF_SHARED | IRQF_DISABLED, 1035*b285192aSMauro Carvalho Chehab cx->v4l2_dev.name, (void *)cx); 1036*b285192aSMauro Carvalho Chehab if (retval) { 1037*b285192aSMauro Carvalho Chehab CX18_ERR("Failed to register irq %d\n", retval); 1038*b285192aSMauro Carvalho Chehab goto free_i2c; 1039*b285192aSMauro Carvalho Chehab } 1040*b285192aSMauro Carvalho Chehab 1041*b285192aSMauro Carvalho Chehab if (cx->std == 0) 1042*b285192aSMauro Carvalho Chehab cx->std = V4L2_STD_NTSC_M; 1043*b285192aSMauro Carvalho Chehab 1044*b285192aSMauro Carvalho Chehab if (cx->options.tuner == -1) { 1045*b285192aSMauro Carvalho Chehab for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) { 1046*b285192aSMauro Carvalho Chehab if ((cx->std & cx->card->tuners[i].std) == 0) 1047*b285192aSMauro Carvalho Chehab continue; 1048*b285192aSMauro Carvalho Chehab cx->options.tuner = cx->card->tuners[i].tuner; 1049*b285192aSMauro Carvalho Chehab break; 1050*b285192aSMauro Carvalho Chehab } 1051*b285192aSMauro Carvalho Chehab } 1052*b285192aSMauro Carvalho Chehab /* if no tuner was found, then pick the first tuner in the card list */ 1053*b285192aSMauro Carvalho Chehab if (cx->options.tuner == -1 && cx->card->tuners[0].std) { 1054*b285192aSMauro Carvalho Chehab cx->std = cx->card->tuners[0].std; 1055*b285192aSMauro Carvalho Chehab if (cx->std & V4L2_STD_PAL) 1056*b285192aSMauro Carvalho Chehab cx->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H; 1057*b285192aSMauro Carvalho Chehab else if (cx->std & V4L2_STD_NTSC) 1058*b285192aSMauro Carvalho Chehab cx->std = V4L2_STD_NTSC_M; 1059*b285192aSMauro Carvalho Chehab else if (cx->std & V4L2_STD_SECAM) 1060*b285192aSMauro Carvalho Chehab cx->std = V4L2_STD_SECAM_L; 1061*b285192aSMauro Carvalho Chehab cx->options.tuner = cx->card->tuners[0].tuner; 1062*b285192aSMauro Carvalho Chehab } 1063*b285192aSMauro Carvalho Chehab if (cx->options.radio == -1) 1064*b285192aSMauro Carvalho Chehab cx->options.radio = (cx->card->radio_input.audio_type != 0); 1065*b285192aSMauro Carvalho Chehab 1066*b285192aSMauro Carvalho Chehab /* The card is now fully identified, continue with card-specific 1067*b285192aSMauro Carvalho Chehab initialization. */ 1068*b285192aSMauro Carvalho Chehab cx18_init_struct2(cx); 1069*b285192aSMauro Carvalho Chehab 1070*b285192aSMauro Carvalho Chehab cx18_init_subdevs(cx); 1071*b285192aSMauro Carvalho Chehab 1072*b285192aSMauro Carvalho Chehab if (cx->std & V4L2_STD_525_60) 1073*b285192aSMauro Carvalho Chehab cx->is_60hz = 1; 1074*b285192aSMauro Carvalho Chehab else 1075*b285192aSMauro Carvalho Chehab cx->is_50hz = 1; 1076*b285192aSMauro Carvalho Chehab 1077*b285192aSMauro Carvalho Chehab cx2341x_handler_set_50hz(&cx->cxhdl, !cx->is_60hz); 1078*b285192aSMauro Carvalho Chehab 1079*b285192aSMauro Carvalho Chehab if (cx->options.radio > 0) 1080*b285192aSMauro Carvalho Chehab cx->v4l2_cap |= V4L2_CAP_RADIO; 1081*b285192aSMauro Carvalho Chehab 1082*b285192aSMauro Carvalho Chehab if (cx->options.tuner > -1) { 1083*b285192aSMauro Carvalho Chehab struct tuner_setup setup; 1084*b285192aSMauro Carvalho Chehab 1085*b285192aSMauro Carvalho Chehab setup.addr = ADDR_UNSET; 1086*b285192aSMauro Carvalho Chehab setup.type = cx->options.tuner; 1087*b285192aSMauro Carvalho Chehab setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ 1088*b285192aSMauro Carvalho Chehab if (cx->options.radio > 0) 1089*b285192aSMauro Carvalho Chehab setup.mode_mask |= T_RADIO; 1090*b285192aSMauro Carvalho Chehab setup.tuner_callback = (setup.type == TUNER_XC2028) ? 1091*b285192aSMauro Carvalho Chehab cx18_reset_tuner_gpio : NULL; 1092*b285192aSMauro Carvalho Chehab cx18_call_all(cx, tuner, s_type_addr, &setup); 1093*b285192aSMauro Carvalho Chehab if (setup.type == TUNER_XC2028) { 1094*b285192aSMauro Carvalho Chehab static struct xc2028_ctrl ctrl = { 1095*b285192aSMauro Carvalho Chehab .fname = XC2028_DEFAULT_FIRMWARE, 1096*b285192aSMauro Carvalho Chehab .max_len = 64, 1097*b285192aSMauro Carvalho Chehab }; 1098*b285192aSMauro Carvalho Chehab struct v4l2_priv_tun_config cfg = { 1099*b285192aSMauro Carvalho Chehab .tuner = cx->options.tuner, 1100*b285192aSMauro Carvalho Chehab .priv = &ctrl, 1101*b285192aSMauro Carvalho Chehab }; 1102*b285192aSMauro Carvalho Chehab cx18_call_all(cx, tuner, s_config, &cfg); 1103*b285192aSMauro Carvalho Chehab } 1104*b285192aSMauro Carvalho Chehab } 1105*b285192aSMauro Carvalho Chehab 1106*b285192aSMauro Carvalho Chehab /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) 1107*b285192aSMauro Carvalho Chehab are not. */ 1108*b285192aSMauro Carvalho Chehab cx->tuner_std = cx->std; 1109*b285192aSMauro Carvalho Chehab if (cx->std == V4L2_STD_ALL) 1110*b285192aSMauro Carvalho Chehab cx->std = V4L2_STD_NTSC_M; 1111*b285192aSMauro Carvalho Chehab 1112*b285192aSMauro Carvalho Chehab retval = cx18_streams_setup(cx); 1113*b285192aSMauro Carvalho Chehab if (retval) { 1114*b285192aSMauro Carvalho Chehab CX18_ERR("Error %d setting up streams\n", retval); 1115*b285192aSMauro Carvalho Chehab goto free_irq; 1116*b285192aSMauro Carvalho Chehab } 1117*b285192aSMauro Carvalho Chehab retval = cx18_streams_register(cx); 1118*b285192aSMauro Carvalho Chehab if (retval) { 1119*b285192aSMauro Carvalho Chehab CX18_ERR("Error %d registering devices\n", retval); 1120*b285192aSMauro Carvalho Chehab goto free_streams; 1121*b285192aSMauro Carvalho Chehab } 1122*b285192aSMauro Carvalho Chehab 1123*b285192aSMauro Carvalho Chehab CX18_INFO("Initialized card: %s\n", cx->card_name); 1124*b285192aSMauro Carvalho Chehab 1125*b285192aSMauro Carvalho Chehab /* Load cx18 submodules (cx18-alsa) */ 1126*b285192aSMauro Carvalho Chehab request_modules(cx); 1127*b285192aSMauro Carvalho Chehab return 0; 1128*b285192aSMauro Carvalho Chehab 1129*b285192aSMauro Carvalho Chehab free_streams: 1130*b285192aSMauro Carvalho Chehab cx18_streams_cleanup(cx, 1); 1131*b285192aSMauro Carvalho Chehab free_irq: 1132*b285192aSMauro Carvalho Chehab free_irq(cx->pci_dev->irq, (void *)cx); 1133*b285192aSMauro Carvalho Chehab free_i2c: 1134*b285192aSMauro Carvalho Chehab exit_cx18_i2c(cx); 1135*b285192aSMauro Carvalho Chehab free_map: 1136*b285192aSMauro Carvalho Chehab cx18_iounmap(cx); 1137*b285192aSMauro Carvalho Chehab free_mem: 1138*b285192aSMauro Carvalho Chehab release_mem_region(cx->base_addr, CX18_MEM_SIZE); 1139*b285192aSMauro Carvalho Chehab free_workqueues: 1140*b285192aSMauro Carvalho Chehab destroy_workqueue(cx->in_work_queue); 1141*b285192aSMauro Carvalho Chehab err: 1142*b285192aSMauro Carvalho Chehab if (retval == 0) 1143*b285192aSMauro Carvalho Chehab retval = -ENODEV; 1144*b285192aSMauro Carvalho Chehab CX18_ERR("Error %d on initialization\n", retval); 1145*b285192aSMauro Carvalho Chehab 1146*b285192aSMauro Carvalho Chehab v4l2_device_unregister(&cx->v4l2_dev); 1147*b285192aSMauro Carvalho Chehab kfree(cx); 1148*b285192aSMauro Carvalho Chehab return retval; 1149*b285192aSMauro Carvalho Chehab } 1150*b285192aSMauro Carvalho Chehab 1151*b285192aSMauro Carvalho Chehab int cx18_init_on_first_open(struct cx18 *cx) 1152*b285192aSMauro Carvalho Chehab { 1153*b285192aSMauro Carvalho Chehab int video_input; 1154*b285192aSMauro Carvalho Chehab int fw_retry_count = 3; 1155*b285192aSMauro Carvalho Chehab struct v4l2_frequency vf; 1156*b285192aSMauro Carvalho Chehab struct cx18_open_id fh; 1157*b285192aSMauro Carvalho Chehab v4l2_std_id std; 1158*b285192aSMauro Carvalho Chehab 1159*b285192aSMauro Carvalho Chehab fh.cx = cx; 1160*b285192aSMauro Carvalho Chehab 1161*b285192aSMauro Carvalho Chehab if (test_bit(CX18_F_I_FAILED, &cx->i_flags)) 1162*b285192aSMauro Carvalho Chehab return -ENXIO; 1163*b285192aSMauro Carvalho Chehab 1164*b285192aSMauro Carvalho Chehab if (test_and_set_bit(CX18_F_I_INITED, &cx->i_flags)) 1165*b285192aSMauro Carvalho Chehab return 0; 1166*b285192aSMauro Carvalho Chehab 1167*b285192aSMauro Carvalho Chehab while (--fw_retry_count > 0) { 1168*b285192aSMauro Carvalho Chehab /* load firmware */ 1169*b285192aSMauro Carvalho Chehab if (cx18_firmware_init(cx) == 0) 1170*b285192aSMauro Carvalho Chehab break; 1171*b285192aSMauro Carvalho Chehab if (fw_retry_count > 1) 1172*b285192aSMauro Carvalho Chehab CX18_WARN("Retry loading firmware\n"); 1173*b285192aSMauro Carvalho Chehab } 1174*b285192aSMauro Carvalho Chehab 1175*b285192aSMauro Carvalho Chehab if (fw_retry_count == 0) { 1176*b285192aSMauro Carvalho Chehab set_bit(CX18_F_I_FAILED, &cx->i_flags); 1177*b285192aSMauro Carvalho Chehab return -ENXIO; 1178*b285192aSMauro Carvalho Chehab } 1179*b285192aSMauro Carvalho Chehab set_bit(CX18_F_I_LOADED_FW, &cx->i_flags); 1180*b285192aSMauro Carvalho Chehab 1181*b285192aSMauro Carvalho Chehab /* 1182*b285192aSMauro Carvalho Chehab * Init the firmware twice to work around a silicon bug 1183*b285192aSMauro Carvalho Chehab * with the digital TS. 1184*b285192aSMauro Carvalho Chehab * 1185*b285192aSMauro Carvalho Chehab * The second firmware load requires us to normalize the APU state, 1186*b285192aSMauro Carvalho Chehab * or the audio for the first analog capture will be badly incorrect. 1187*b285192aSMauro Carvalho Chehab * 1188*b285192aSMauro Carvalho Chehab * I can't seem to call APU_RESETAI and have it succeed without the 1189*b285192aSMauro Carvalho Chehab * APU capturing audio, so we start and stop it here to do the reset 1190*b285192aSMauro Carvalho Chehab */ 1191*b285192aSMauro Carvalho Chehab 1192*b285192aSMauro Carvalho Chehab /* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */ 1193*b285192aSMauro Carvalho Chehab cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0); 1194*b285192aSMauro Carvalho Chehab cx18_vapi(cx, CX18_APU_RESETAI, 0); 1195*b285192aSMauro Carvalho Chehab cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG); 1196*b285192aSMauro Carvalho Chehab 1197*b285192aSMauro Carvalho Chehab fw_retry_count = 3; 1198*b285192aSMauro Carvalho Chehab while (--fw_retry_count > 0) { 1199*b285192aSMauro Carvalho Chehab /* load firmware */ 1200*b285192aSMauro Carvalho Chehab if (cx18_firmware_init(cx) == 0) 1201*b285192aSMauro Carvalho Chehab break; 1202*b285192aSMauro Carvalho Chehab if (fw_retry_count > 1) 1203*b285192aSMauro Carvalho Chehab CX18_WARN("Retry loading firmware\n"); 1204*b285192aSMauro Carvalho Chehab } 1205*b285192aSMauro Carvalho Chehab 1206*b285192aSMauro Carvalho Chehab if (fw_retry_count == 0) { 1207*b285192aSMauro Carvalho Chehab set_bit(CX18_F_I_FAILED, &cx->i_flags); 1208*b285192aSMauro Carvalho Chehab return -ENXIO; 1209*b285192aSMauro Carvalho Chehab } 1210*b285192aSMauro Carvalho Chehab 1211*b285192aSMauro Carvalho Chehab /* 1212*b285192aSMauro Carvalho Chehab * The second firmware load requires us to normalize the APU state, 1213*b285192aSMauro Carvalho Chehab * or the audio for the first analog capture will be badly incorrect. 1214*b285192aSMauro Carvalho Chehab * 1215*b285192aSMauro Carvalho Chehab * I can't seem to call APU_RESETAI and have it succeed without the 1216*b285192aSMauro Carvalho Chehab * APU capturing audio, so we start and stop it here to do the reset 1217*b285192aSMauro Carvalho Chehab */ 1218*b285192aSMauro Carvalho Chehab 1219*b285192aSMauro Carvalho Chehab /* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */ 1220*b285192aSMauro Carvalho Chehab cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0); 1221*b285192aSMauro Carvalho Chehab cx18_vapi(cx, CX18_APU_RESETAI, 0); 1222*b285192aSMauro Carvalho Chehab cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG); 1223*b285192aSMauro Carvalho Chehab 1224*b285192aSMauro Carvalho Chehab /* Init the A/V decoder, if it hasn't been already */ 1225*b285192aSMauro Carvalho Chehab v4l2_subdev_call(cx->sd_av, core, load_fw); 1226*b285192aSMauro Carvalho Chehab 1227*b285192aSMauro Carvalho Chehab vf.tuner = 0; 1228*b285192aSMauro Carvalho Chehab vf.type = V4L2_TUNER_ANALOG_TV; 1229*b285192aSMauro Carvalho Chehab vf.frequency = 6400; /* the tuner 'baseline' frequency */ 1230*b285192aSMauro Carvalho Chehab 1231*b285192aSMauro Carvalho Chehab /* Set initial frequency. For PAL/SECAM broadcasts no 1232*b285192aSMauro Carvalho Chehab 'default' channel exists AFAIK. */ 1233*b285192aSMauro Carvalho Chehab if (cx->std == V4L2_STD_NTSC_M_JP) 1234*b285192aSMauro Carvalho Chehab vf.frequency = 1460; /* ch. 1 91250*16/1000 */ 1235*b285192aSMauro Carvalho Chehab else if (cx->std & V4L2_STD_NTSC_M) 1236*b285192aSMauro Carvalho Chehab vf.frequency = 1076; /* ch. 4 67250*16/1000 */ 1237*b285192aSMauro Carvalho Chehab 1238*b285192aSMauro Carvalho Chehab video_input = cx->active_input; 1239*b285192aSMauro Carvalho Chehab cx->active_input++; /* Force update of input */ 1240*b285192aSMauro Carvalho Chehab cx18_s_input(NULL, &fh, video_input); 1241*b285192aSMauro Carvalho Chehab 1242*b285192aSMauro Carvalho Chehab /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code 1243*b285192aSMauro Carvalho Chehab in one place. */ 1244*b285192aSMauro Carvalho Chehab cx->std++; /* Force full standard initialization */ 1245*b285192aSMauro Carvalho Chehab std = (cx->tuner_std == V4L2_STD_ALL) ? V4L2_STD_NTSC_M : cx->tuner_std; 1246*b285192aSMauro Carvalho Chehab cx18_s_std(NULL, &fh, &std); 1247*b285192aSMauro Carvalho Chehab cx18_s_frequency(NULL, &fh, &vf); 1248*b285192aSMauro Carvalho Chehab return 0; 1249*b285192aSMauro Carvalho Chehab } 1250*b285192aSMauro Carvalho Chehab 1251*b285192aSMauro Carvalho Chehab static void cx18_cancel_in_work_orders(struct cx18 *cx) 1252*b285192aSMauro Carvalho Chehab { 1253*b285192aSMauro Carvalho Chehab int i; 1254*b285192aSMauro Carvalho Chehab for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) 1255*b285192aSMauro Carvalho Chehab cancel_work_sync(&cx->in_work_order[i].work); 1256*b285192aSMauro Carvalho Chehab } 1257*b285192aSMauro Carvalho Chehab 1258*b285192aSMauro Carvalho Chehab static void cx18_cancel_out_work_orders(struct cx18 *cx) 1259*b285192aSMauro Carvalho Chehab { 1260*b285192aSMauro Carvalho Chehab int i; 1261*b285192aSMauro Carvalho Chehab for (i = 0; i < CX18_MAX_STREAMS; i++) 1262*b285192aSMauro Carvalho Chehab if (&cx->streams[i].video_dev != NULL) 1263*b285192aSMauro Carvalho Chehab cancel_work_sync(&cx->streams[i].out_work_order); 1264*b285192aSMauro Carvalho Chehab } 1265*b285192aSMauro Carvalho Chehab 1266*b285192aSMauro Carvalho Chehab static void cx18_remove(struct pci_dev *pci_dev) 1267*b285192aSMauro Carvalho Chehab { 1268*b285192aSMauro Carvalho Chehab struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); 1269*b285192aSMauro Carvalho Chehab struct cx18 *cx = to_cx18(v4l2_dev); 1270*b285192aSMauro Carvalho Chehab int i; 1271*b285192aSMauro Carvalho Chehab 1272*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("Removing Card\n"); 1273*b285192aSMauro Carvalho Chehab 1274*b285192aSMauro Carvalho Chehab flush_request_modules(cx); 1275*b285192aSMauro Carvalho Chehab 1276*b285192aSMauro Carvalho Chehab /* Stop all captures */ 1277*b285192aSMauro Carvalho Chehab CX18_DEBUG_INFO("Stopping all streams\n"); 1278*b285192aSMauro Carvalho Chehab if (atomic_read(&cx->tot_capturing) > 0) 1279*b285192aSMauro Carvalho Chehab cx18_stop_all_captures(cx); 1280*b285192aSMauro Carvalho Chehab 1281*b285192aSMauro Carvalho Chehab /* Stop interrupts that cause incoming work to be queued */ 1282*b285192aSMauro Carvalho Chehab cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); 1283*b285192aSMauro Carvalho Chehab 1284*b285192aSMauro Carvalho Chehab /* Incoming work can cause outgoing work, so clean up incoming first */ 1285*b285192aSMauro Carvalho Chehab cx18_cancel_in_work_orders(cx); 1286*b285192aSMauro Carvalho Chehab cx18_cancel_out_work_orders(cx); 1287*b285192aSMauro Carvalho Chehab 1288*b285192aSMauro Carvalho Chehab /* Stop ack interrupts that may have been needed for work to finish */ 1289*b285192aSMauro Carvalho Chehab cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); 1290*b285192aSMauro Carvalho Chehab 1291*b285192aSMauro Carvalho Chehab cx18_halt_firmware(cx); 1292*b285192aSMauro Carvalho Chehab 1293*b285192aSMauro Carvalho Chehab destroy_workqueue(cx->in_work_queue); 1294*b285192aSMauro Carvalho Chehab 1295*b285192aSMauro Carvalho Chehab cx18_streams_cleanup(cx, 1); 1296*b285192aSMauro Carvalho Chehab 1297*b285192aSMauro Carvalho Chehab exit_cx18_i2c(cx); 1298*b285192aSMauro Carvalho Chehab 1299*b285192aSMauro Carvalho Chehab free_irq(cx->pci_dev->irq, (void *)cx); 1300*b285192aSMauro Carvalho Chehab 1301*b285192aSMauro Carvalho Chehab cx18_iounmap(cx); 1302*b285192aSMauro Carvalho Chehab 1303*b285192aSMauro Carvalho Chehab release_mem_region(cx->base_addr, CX18_MEM_SIZE); 1304*b285192aSMauro Carvalho Chehab 1305*b285192aSMauro Carvalho Chehab pci_disable_device(cx->pci_dev); 1306*b285192aSMauro Carvalho Chehab 1307*b285192aSMauro Carvalho Chehab if (cx->vbi.sliced_mpeg_data[0] != NULL) 1308*b285192aSMauro Carvalho Chehab for (i = 0; i < CX18_VBI_FRAMES; i++) 1309*b285192aSMauro Carvalho Chehab kfree(cx->vbi.sliced_mpeg_data[i]); 1310*b285192aSMauro Carvalho Chehab 1311*b285192aSMauro Carvalho Chehab v4l2_ctrl_handler_free(&cx->av_state.hdl); 1312*b285192aSMauro Carvalho Chehab 1313*b285192aSMauro Carvalho Chehab CX18_INFO("Removed %s\n", cx->card_name); 1314*b285192aSMauro Carvalho Chehab 1315*b285192aSMauro Carvalho Chehab v4l2_device_unregister(v4l2_dev); 1316*b285192aSMauro Carvalho Chehab kfree(cx); 1317*b285192aSMauro Carvalho Chehab } 1318*b285192aSMauro Carvalho Chehab 1319*b285192aSMauro Carvalho Chehab 1320*b285192aSMauro Carvalho Chehab /* define a pci_driver for card detection */ 1321*b285192aSMauro Carvalho Chehab static struct pci_driver cx18_pci_driver = { 1322*b285192aSMauro Carvalho Chehab .name = "cx18", 1323*b285192aSMauro Carvalho Chehab .id_table = cx18_pci_tbl, 1324*b285192aSMauro Carvalho Chehab .probe = cx18_probe, 1325*b285192aSMauro Carvalho Chehab .remove = cx18_remove, 1326*b285192aSMauro Carvalho Chehab }; 1327*b285192aSMauro Carvalho Chehab 1328*b285192aSMauro Carvalho Chehab static int __init module_start(void) 1329*b285192aSMauro Carvalho Chehab { 1330*b285192aSMauro Carvalho Chehab printk(KERN_INFO "cx18: Start initialization, version %s\n", 1331*b285192aSMauro Carvalho Chehab CX18_VERSION); 1332*b285192aSMauro Carvalho Chehab 1333*b285192aSMauro Carvalho Chehab /* Validate parameters */ 1334*b285192aSMauro Carvalho Chehab if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { 1335*b285192aSMauro Carvalho Chehab printk(KERN_ERR "cx18: Exiting, cx18_first_minor must be between 0 and %d\n", 1336*b285192aSMauro Carvalho Chehab CX18_MAX_CARDS - 1); 1337*b285192aSMauro Carvalho Chehab return -1; 1338*b285192aSMauro Carvalho Chehab } 1339*b285192aSMauro Carvalho Chehab 1340*b285192aSMauro Carvalho Chehab if (cx18_debug < 0 || cx18_debug > 511) { 1341*b285192aSMauro Carvalho Chehab cx18_debug = 0; 1342*b285192aSMauro Carvalho Chehab printk(KERN_INFO "cx18: Debug value must be >= 0 and <= 511!\n"); 1343*b285192aSMauro Carvalho Chehab } 1344*b285192aSMauro Carvalho Chehab 1345*b285192aSMauro Carvalho Chehab if (pci_register_driver(&cx18_pci_driver)) { 1346*b285192aSMauro Carvalho Chehab printk(KERN_ERR "cx18: Error detecting PCI card\n"); 1347*b285192aSMauro Carvalho Chehab return -ENODEV; 1348*b285192aSMauro Carvalho Chehab } 1349*b285192aSMauro Carvalho Chehab printk(KERN_INFO "cx18: End initialization\n"); 1350*b285192aSMauro Carvalho Chehab return 0; 1351*b285192aSMauro Carvalho Chehab } 1352*b285192aSMauro Carvalho Chehab 1353*b285192aSMauro Carvalho Chehab static void __exit module_cleanup(void) 1354*b285192aSMauro Carvalho Chehab { 1355*b285192aSMauro Carvalho Chehab pci_unregister_driver(&cx18_pci_driver); 1356*b285192aSMauro Carvalho Chehab } 1357*b285192aSMauro Carvalho Chehab 1358*b285192aSMauro Carvalho Chehab module_init(module_start); 1359*b285192aSMauro Carvalho Chehab module_exit(module_cleanup); 1360*b285192aSMauro Carvalho Chehab MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE); 1361