18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci ivtv driver initialization and card probing 38c2ecf20Sopenharmony_ci Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> 48c2ecf20Sopenharmony_ci Copyright (C) 2004 Chris Kennedy <c@groovy.org> 58c2ecf20Sopenharmony_ci Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci This program is free software; you can redistribute it and/or modify 88c2ecf20Sopenharmony_ci it under the terms of the GNU General Public License as published by 98c2ecf20Sopenharmony_ci the Free Software Foundation; either version 2 of the License, or 108c2ecf20Sopenharmony_ci (at your option) any later version. 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci This program is distributed in the hope that it will be useful, 138c2ecf20Sopenharmony_ci but WITHOUT ANY WARRANTY; without even the implied warranty of 148c2ecf20Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 158c2ecf20Sopenharmony_ci GNU General Public License for more details. 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci You should have received a copy of the GNU General Public License 188c2ecf20Sopenharmony_ci along with this program; if not, write to the Free Software 198c2ecf20Sopenharmony_ci Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* Main Driver file for the ivtv project: 238c2ecf20Sopenharmony_ci * Driver for the Conexant CX23415/CX23416 chip. 248c2ecf20Sopenharmony_ci * Author: Kevin Thayer (nufan_wfk at yahoo.com) 258c2ecf20Sopenharmony_ci * License: GPL 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * ----- 288c2ecf20Sopenharmony_ci * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> 298c2ecf20Sopenharmony_ci * and Takeru KOMORIYA<komoriya@paken.org> 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> 328c2ecf20Sopenharmony_ci * using information provided by Jiun-Kuei Jung @ AVerMedia. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Kurouto Sikou CX23416GYC-STVLP tested by K.Ohta <alpha292@bremen.or.jp> 358c2ecf20Sopenharmony_ci * using information from T.Adachi,Takeru KOMORIYA and others :-) 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * Nagase TRANSGEAR 5000TV, Aopen VA2000MAX-STN6 and I/O data GV-MVP/RX 388c2ecf20Sopenharmony_ci * version by T.Adachi. Special thanks Mr.Suzuki 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#include "ivtv-driver.h" 428c2ecf20Sopenharmony_ci#include "ivtv-version.h" 438c2ecf20Sopenharmony_ci#include "ivtv-fileops.h" 448c2ecf20Sopenharmony_ci#include "ivtv-i2c.h" 458c2ecf20Sopenharmony_ci#include "ivtv-firmware.h" 468c2ecf20Sopenharmony_ci#include "ivtv-queue.h" 478c2ecf20Sopenharmony_ci#include "ivtv-udma.h" 488c2ecf20Sopenharmony_ci#include "ivtv-irq.h" 498c2ecf20Sopenharmony_ci#include "ivtv-mailbox.h" 508c2ecf20Sopenharmony_ci#include "ivtv-streams.h" 518c2ecf20Sopenharmony_ci#include "ivtv-ioctl.h" 528c2ecf20Sopenharmony_ci#include "ivtv-cards.h" 538c2ecf20Sopenharmony_ci#include "ivtv-vbi.h" 548c2ecf20Sopenharmony_ci#include "ivtv-routing.h" 558c2ecf20Sopenharmony_ci#include "ivtv-controls.h" 568c2ecf20Sopenharmony_ci#include "ivtv-gpio.h" 578c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 588c2ecf20Sopenharmony_ci#include <media/tveeprom.h> 598c2ecf20Sopenharmony_ci#include <media/i2c/saa7115.h> 608c2ecf20Sopenharmony_ci#include "tuner-xc2028.h" 618c2ecf20Sopenharmony_ci#include <uapi/linux/sched/types.h> 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* If you have already X v4l cards, then set this to X. This way 648c2ecf20Sopenharmony_ci the device numbers stay matched. Example: you have a WinTV card 658c2ecf20Sopenharmony_ci without radio and a PVR-350 with. Normally this would give a 668c2ecf20Sopenharmony_ci video1 device together with a radio0 device for the PVR. By 678c2ecf20Sopenharmony_ci setting this to 1 you ensure that radio0 is now also radio1. */ 688c2ecf20Sopenharmony_ciint ivtv_first_minor; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* Callback for registering extensions */ 718c2ecf20Sopenharmony_ciint (*ivtv_ext_init)(struct ivtv *); 728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_ext_init); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* add your revision and whatnot here */ 758c2ecf20Sopenharmony_cistatic const struct pci_device_id ivtv_pci_tbl[] = { 768c2ecf20Sopenharmony_ci {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15, 778c2ecf20Sopenharmony_ci PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 788c2ecf20Sopenharmony_ci {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16, 798c2ecf20Sopenharmony_ci PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 808c2ecf20Sopenharmony_ci {0,} 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci,ivtv_pci_tbl); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* ivtv instance counter */ 868c2ecf20Sopenharmony_cistatic atomic_t ivtv_instance = ATOMIC_INIT(0); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* Parameter declarations */ 898c2ecf20Sopenharmony_cistatic int cardtype[IVTV_MAX_CARDS]; 908c2ecf20Sopenharmony_cistatic int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, 918c2ecf20Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, 928c2ecf20Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, 938c2ecf20Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1 }; 948c2ecf20Sopenharmony_cistatic int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, 958c2ecf20Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, 968c2ecf20Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, 978c2ecf20Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1 }; 988c2ecf20Sopenharmony_cistatic int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, 998c2ecf20Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, 1008c2ecf20Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, 1018c2ecf20Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1 }; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic unsigned int cardtype_c = 1; 1048c2ecf20Sopenharmony_cistatic unsigned int tuner_c = 1; 1058c2ecf20Sopenharmony_cistatic int radio_c = 1; 1068c2ecf20Sopenharmony_cistatic unsigned int i2c_clock_period_c = 1; 1078c2ecf20Sopenharmony_cistatic char pal[] = "---"; 1088c2ecf20Sopenharmony_cistatic char secam[] = "--"; 1098c2ecf20Sopenharmony_cistatic char ntsc[] = "-"; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* Buffers */ 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci/* DMA Buffers, Default size in MB allocated */ 1148c2ecf20Sopenharmony_ci#define IVTV_DEFAULT_ENC_MPG_BUFFERS 4 1158c2ecf20Sopenharmony_ci#define IVTV_DEFAULT_ENC_YUV_BUFFERS 2 1168c2ecf20Sopenharmony_ci#define IVTV_DEFAULT_ENC_VBI_BUFFERS 1 1178c2ecf20Sopenharmony_ci/* Exception: size in kB for this stream (MB is overkill) */ 1188c2ecf20Sopenharmony_ci#define IVTV_DEFAULT_ENC_PCM_BUFFERS 320 1198c2ecf20Sopenharmony_ci#define IVTV_DEFAULT_DEC_MPG_BUFFERS 1 1208c2ecf20Sopenharmony_ci#define IVTV_DEFAULT_DEC_YUV_BUFFERS 1 1218c2ecf20Sopenharmony_ci/* Exception: size in kB for this stream (MB is way overkill) */ 1228c2ecf20Sopenharmony_ci#define IVTV_DEFAULT_DEC_VBI_BUFFERS 64 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int enc_mpg_buffers = IVTV_DEFAULT_ENC_MPG_BUFFERS; 1258c2ecf20Sopenharmony_cistatic int enc_yuv_buffers = IVTV_DEFAULT_ENC_YUV_BUFFERS; 1268c2ecf20Sopenharmony_cistatic int enc_vbi_buffers = IVTV_DEFAULT_ENC_VBI_BUFFERS; 1278c2ecf20Sopenharmony_cistatic int enc_pcm_buffers = IVTV_DEFAULT_ENC_PCM_BUFFERS; 1288c2ecf20Sopenharmony_cistatic int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS; 1298c2ecf20Sopenharmony_cistatic int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS; 1308c2ecf20Sopenharmony_cistatic int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic int ivtv_yuv_mode; 1338c2ecf20Sopenharmony_cistatic int ivtv_yuv_threshold = -1; 1348c2ecf20Sopenharmony_cistatic int ivtv_pci_latency = 1; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ciint ivtv_debug; 1378c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 1388c2ecf20Sopenharmony_ciint ivtv_fw_debug; 1398c2ecf20Sopenharmony_ci#endif 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic int tunertype = -1; 1428c2ecf20Sopenharmony_cistatic int newi2c = -1; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cimodule_param_array(tuner, int, &tuner_c, 0644); 1458c2ecf20Sopenharmony_cimodule_param_array(radio, int, &radio_c, 0644); 1468c2ecf20Sopenharmony_cimodule_param_array(cardtype, int, &cardtype_c, 0644); 1478c2ecf20Sopenharmony_cimodule_param_string(pal, pal, sizeof(pal), 0644); 1488c2ecf20Sopenharmony_cimodule_param_string(secam, secam, sizeof(secam), 0644); 1498c2ecf20Sopenharmony_cimodule_param_string(ntsc, ntsc, sizeof(ntsc), 0644); 1508c2ecf20Sopenharmony_cimodule_param_named(debug,ivtv_debug, int, 0644); 1518c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 1528c2ecf20Sopenharmony_cimodule_param_named(fw_debug, ivtv_fw_debug, int, 0644); 1538c2ecf20Sopenharmony_ci#endif 1548c2ecf20Sopenharmony_cimodule_param(ivtv_pci_latency, int, 0644); 1558c2ecf20Sopenharmony_cimodule_param(ivtv_yuv_mode, int, 0644); 1568c2ecf20Sopenharmony_cimodule_param(ivtv_yuv_threshold, int, 0644); 1578c2ecf20Sopenharmony_cimodule_param(ivtv_first_minor, int, 0644); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cimodule_param(enc_mpg_buffers, int, 0644); 1608c2ecf20Sopenharmony_cimodule_param(enc_yuv_buffers, int, 0644); 1618c2ecf20Sopenharmony_cimodule_param(enc_vbi_buffers, int, 0644); 1628c2ecf20Sopenharmony_cimodule_param(enc_pcm_buffers, int, 0644); 1638c2ecf20Sopenharmony_cimodule_param(dec_mpg_buffers, int, 0644); 1648c2ecf20Sopenharmony_cimodule_param(dec_yuv_buffers, int, 0644); 1658c2ecf20Sopenharmony_cimodule_param(dec_vbi_buffers, int, 0644); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cimodule_param(tunertype, int, 0644); 1688c2ecf20Sopenharmony_cimodule_param(newi2c, int, 0644); 1698c2ecf20Sopenharmony_cimodule_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciMODULE_PARM_DESC(tuner, "Tuner type selection,\n" 1728c2ecf20Sopenharmony_ci "\t\t\tsee tuner.h for values"); 1738c2ecf20Sopenharmony_ciMODULE_PARM_DESC(radio, 1748c2ecf20Sopenharmony_ci "Enable or disable the radio. Use only if autodetection\n" 1758c2ecf20Sopenharmony_ci "\t\t\tfails. 0 = disable, 1 = enable"); 1768c2ecf20Sopenharmony_ciMODULE_PARM_DESC(cardtype, 1778c2ecf20Sopenharmony_ci "Only use this option if your card is not detected properly.\n" 1788c2ecf20Sopenharmony_ci "\t\tSpecify card type:\n" 1798c2ecf20Sopenharmony_ci "\t\t\t 1 = WinTV PVR 250\n" 1808c2ecf20Sopenharmony_ci "\t\t\t 2 = WinTV PVR 350\n" 1818c2ecf20Sopenharmony_ci "\t\t\t 3 = WinTV PVR-150 or PVR-500\n" 1828c2ecf20Sopenharmony_ci "\t\t\t 4 = AVerMedia M179\n" 1838c2ecf20Sopenharmony_ci "\t\t\t 5 = YUAN MPG600/Kuroutoshikou iTVC16-STVLP\n" 1848c2ecf20Sopenharmony_ci "\t\t\t 6 = YUAN MPG160/Kuroutoshikou iTVC15-STVLP\n" 1858c2ecf20Sopenharmony_ci "\t\t\t 7 = YUAN PG600/DIAMONDMM PVR-550 (CX Falcon 2)\n" 1868c2ecf20Sopenharmony_ci "\t\t\t 8 = Adaptec AVC-2410\n" 1878c2ecf20Sopenharmony_ci "\t\t\t 9 = Adaptec AVC-2010\n" 1888c2ecf20Sopenharmony_ci "\t\t\t10 = NAGASE TRANSGEAR 5000TV\n" 1898c2ecf20Sopenharmony_ci "\t\t\t11 = AOpen VA2000MAX-STN6\n" 1908c2ecf20Sopenharmony_ci "\t\t\t12 = YUAN MPG600GR/Kuroutoshikou CX23416GYC-STVLP\n" 1918c2ecf20Sopenharmony_ci "\t\t\t13 = I/O Data GV-MVP/RX\n" 1928c2ecf20Sopenharmony_ci "\t\t\t14 = I/O Data GV-MVP/RX2E\n" 1938c2ecf20Sopenharmony_ci "\t\t\t15 = GOTVIEW PCI DVD\n" 1948c2ecf20Sopenharmony_ci "\t\t\t16 = GOTVIEW PCI DVD2 Deluxe\n" 1958c2ecf20Sopenharmony_ci "\t\t\t17 = Yuan MPC622\n" 1968c2ecf20Sopenharmony_ci "\t\t\t18 = Digital Cowboy DCT-MTVP1\n" 1978c2ecf20Sopenharmony_ci "\t\t\t19 = Yuan PG600V2/GotView PCI DVD Lite\n" 1988c2ecf20Sopenharmony_ci "\t\t\t20 = Club3D ZAP-TV1x01\n" 1998c2ecf20Sopenharmony_ci "\t\t\t21 = AverTV MCE 116 Plus\n" 2008c2ecf20Sopenharmony_ci "\t\t\t22 = ASUS Falcon2\n" 2018c2ecf20Sopenharmony_ci "\t\t\t23 = AverMedia PVR-150 Plus\n" 2028c2ecf20Sopenharmony_ci "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n" 2038c2ecf20Sopenharmony_ci "\t\t\t25 = AverMedia M104 (not yet working)\n" 2048c2ecf20Sopenharmony_ci "\t\t\t26 = Buffalo PC-MV5L/PCI\n" 2058c2ecf20Sopenharmony_ci "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n" 2068c2ecf20Sopenharmony_ci "\t\t\t28 = Sony VAIO Giga Pocket (ENX Kikyou)\n" 2078c2ecf20Sopenharmony_ci "\t\t\t 0 = Autodetect (default)\n" 2088c2ecf20Sopenharmony_ci "\t\t\t-1 = Ignore this card\n\t\t"); 2098c2ecf20Sopenharmony_ciMODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); 2108c2ecf20Sopenharmony_ciMODULE_PARM_DESC(secam, "Set SECAM standard: BGH, DK, L, LC"); 2118c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J (Japan), K (South Korea)"); 2128c2ecf20Sopenharmony_ciMODULE_PARM_DESC(tunertype, 2138c2ecf20Sopenharmony_ci "Specify tuner type:\n" 2148c2ecf20Sopenharmony_ci "\t\t\t 0 = tuner for PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc\n" 2158c2ecf20Sopenharmony_ci "\t\t\t 1 = tuner for NTSC-M/J/K, PAL-M/N/Nc\n" 2168c2ecf20Sopenharmony_ci "\t\t\t-1 = Autodetect (default)\n"); 2178c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, 2188c2ecf20Sopenharmony_ci "Debug level (bitmask). Default: 0\n" 2198c2ecf20Sopenharmony_ci "\t\t\t 1/0x0001: warning\n" 2208c2ecf20Sopenharmony_ci "\t\t\t 2/0x0002: info\n" 2218c2ecf20Sopenharmony_ci "\t\t\t 4/0x0004: mailbox\n" 2228c2ecf20Sopenharmony_ci "\t\t\t 8/0x0008: ioctl\n" 2238c2ecf20Sopenharmony_ci "\t\t\t 16/0x0010: file\n" 2248c2ecf20Sopenharmony_ci "\t\t\t 32/0x0020: dma\n" 2258c2ecf20Sopenharmony_ci "\t\t\t 64/0x0040: irq\n" 2268c2ecf20Sopenharmony_ci "\t\t\t 128/0x0080: decoder\n" 2278c2ecf20Sopenharmony_ci "\t\t\t 256/0x0100: yuv\n" 2288c2ecf20Sopenharmony_ci "\t\t\t 512/0x0200: i2c\n" 2298c2ecf20Sopenharmony_ci "\t\t\t1024/0x0400: high volume\n"); 2308c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 2318c2ecf20Sopenharmony_ciMODULE_PARM_DESC(fw_debug, 2328c2ecf20Sopenharmony_ci "Enable code for debugging firmware problems. Default: 0\n"); 2338c2ecf20Sopenharmony_ci#endif 2348c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ivtv_pci_latency, 2358c2ecf20Sopenharmony_ci "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" 2368c2ecf20Sopenharmony_ci "\t\t\tDefault: Yes"); 2378c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ivtv_yuv_mode, 2388c2ecf20Sopenharmony_ci "Specify the yuv playback mode:\n" 2398c2ecf20Sopenharmony_ci "\t\t\t0 = interlaced\n\t\t\t1 = progressive\n\t\t\t2 = auto\n" 2408c2ecf20Sopenharmony_ci "\t\t\tDefault: 0 (interlaced)"); 2418c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ivtv_yuv_threshold, 2428c2ecf20Sopenharmony_ci "If ivtv_yuv_mode is 2 (auto) then playback content as\n\t\tprogressive if src height <= ivtv_yuvthreshold\n" 2438c2ecf20Sopenharmony_ci "\t\t\tDefault: 480"); 2448c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enc_mpg_buffers, 2458c2ecf20Sopenharmony_ci "Encoder MPG Buffers (in MB)\n" 2468c2ecf20Sopenharmony_ci "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_MPG_BUFFERS)); 2478c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enc_yuv_buffers, 2488c2ecf20Sopenharmony_ci "Encoder YUV Buffers (in MB)\n" 2498c2ecf20Sopenharmony_ci "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_YUV_BUFFERS)); 2508c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enc_vbi_buffers, 2518c2ecf20Sopenharmony_ci "Encoder VBI Buffers (in MB)\n" 2528c2ecf20Sopenharmony_ci "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_VBI_BUFFERS)); 2538c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enc_pcm_buffers, 2548c2ecf20Sopenharmony_ci "Encoder PCM buffers (in kB)\n" 2558c2ecf20Sopenharmony_ci "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_PCM_BUFFERS)); 2568c2ecf20Sopenharmony_ciMODULE_PARM_DESC(dec_mpg_buffers, 2578c2ecf20Sopenharmony_ci "Decoder MPG buffers (in MB)\n" 2588c2ecf20Sopenharmony_ci "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_MPG_BUFFERS)); 2598c2ecf20Sopenharmony_ciMODULE_PARM_DESC(dec_yuv_buffers, 2608c2ecf20Sopenharmony_ci "Decoder YUV buffers (in MB)\n" 2618c2ecf20Sopenharmony_ci "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_YUV_BUFFERS)); 2628c2ecf20Sopenharmony_ciMODULE_PARM_DESC(dec_vbi_buffers, 2638c2ecf20Sopenharmony_ci "Decoder VBI buffers (in kB)\n" 2648c2ecf20Sopenharmony_ci "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_VBI_BUFFERS)); 2658c2ecf20Sopenharmony_ciMODULE_PARM_DESC(newi2c, 2668c2ecf20Sopenharmony_ci "Use new I2C implementation\n" 2678c2ecf20Sopenharmony_ci "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" 2688c2ecf20Sopenharmony_ci "\t\t\tDefault is autodetect"); 2698c2ecf20Sopenharmony_ciMODULE_PARM_DESC(i2c_clock_period, 2708c2ecf20Sopenharmony_ci "Period of SCL for the I2C bus controlled by the CX23415/6\n" 2718c2ecf20Sopenharmony_ci "\t\t\tMin: 10 usec (100 kHz), Max: 4500 usec (222 Hz)\n" 2728c2ecf20Sopenharmony_ci "\t\t\tDefault: " __stringify(IVTV_DEFAULT_I2C_CLOCK_PERIOD)); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card"); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); 2778c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("CX23415/CX23416 driver"); 2788c2ecf20Sopenharmony_ciMODULE_SUPPORTED_DEVICE 2798c2ecf20Sopenharmony_ci ("CX23415/CX23416 MPEG2 encoder (WinTV PVR-150/250/350/500,\n" 2808c2ecf20Sopenharmony_ci "\t\t\tYuan MPG series and similar)"); 2818c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ciMODULE_VERSION(IVTV_VERSION); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci#if defined(CONFIG_MODULES) && defined(MODULE) 2868c2ecf20Sopenharmony_cistatic void request_module_async(struct work_struct *work) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci struct ivtv *dev = container_of(work, struct ivtv, request_module_wk); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* Make sure ivtv-alsa module is loaded */ 2918c2ecf20Sopenharmony_ci request_module("ivtv-alsa"); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* Initialize ivtv-alsa for this instance of the cx18 device */ 2948c2ecf20Sopenharmony_ci if (ivtv_ext_init != NULL) 2958c2ecf20Sopenharmony_ci ivtv_ext_init(dev); 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic void request_modules(struct ivtv *dev) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci INIT_WORK(&dev->request_module_wk, request_module_async); 3018c2ecf20Sopenharmony_ci schedule_work(&dev->request_module_wk); 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic void flush_request_modules(struct ivtv *dev) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci flush_work(&dev->request_module_wk); 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci#else 3098c2ecf20Sopenharmony_ci#define request_modules(dev) 3108c2ecf20Sopenharmony_ci#define flush_request_modules(dev) 3118c2ecf20Sopenharmony_ci#endif /* CONFIG_MODULES */ 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_civoid ivtv_clear_irq_mask(struct ivtv *itv, u32 mask) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci itv->irqmask &= ~mask; 3168c2ecf20Sopenharmony_ci write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK); 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_civoid ivtv_set_irq_mask(struct ivtv *itv, u32 mask) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci itv->irqmask |= mask; 3228c2ecf20Sopenharmony_ci write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK); 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ciint ivtv_set_output_mode(struct ivtv *itv, int mode) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci int old_mode; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci spin_lock(&itv->lock); 3308c2ecf20Sopenharmony_ci old_mode = itv->output_mode; 3318c2ecf20Sopenharmony_ci if (old_mode == 0) 3328c2ecf20Sopenharmony_ci itv->output_mode = old_mode = mode; 3338c2ecf20Sopenharmony_ci spin_unlock(&itv->lock); 3348c2ecf20Sopenharmony_ci return old_mode; 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistruct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci switch (itv->output_mode) { 3408c2ecf20Sopenharmony_ci case OUT_MPG: 3418c2ecf20Sopenharmony_ci return &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; 3428c2ecf20Sopenharmony_ci case OUT_YUV: 3438c2ecf20Sopenharmony_ci return &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; 3448c2ecf20Sopenharmony_ci default: 3458c2ecf20Sopenharmony_ci return NULL; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ciint ivtv_waitq(wait_queue_head_t *waitq) 3508c2ecf20Sopenharmony_ci{ 3518c2ecf20Sopenharmony_ci DEFINE_WAIT(wait); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE); 3548c2ecf20Sopenharmony_ci schedule(); 3558c2ecf20Sopenharmony_ci finish_wait(waitq, &wait); 3568c2ecf20Sopenharmony_ci return signal_pending(current) ? -EINTR : 0; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci/* Generic utility functions */ 3608c2ecf20Sopenharmony_ciint ivtv_msleep_timeout(unsigned int msecs, int intr) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci int timeout = msecs_to_jiffies(msecs); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci do { 3658c2ecf20Sopenharmony_ci set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 3668c2ecf20Sopenharmony_ci timeout = schedule_timeout(timeout); 3678c2ecf20Sopenharmony_ci if (intr) { 3688c2ecf20Sopenharmony_ci int ret = signal_pending(current); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (ret) 3718c2ecf20Sopenharmony_ci return ret; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci } while (timeout); 3748c2ecf20Sopenharmony_ci return 0; 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci/* Release ioremapped memory */ 3788c2ecf20Sopenharmony_cistatic void ivtv_iounmap(struct ivtv *itv) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci if (itv == NULL) 3818c2ecf20Sopenharmony_ci return; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* Release registers memory */ 3848c2ecf20Sopenharmony_ci if (itv->reg_mem != NULL) { 3858c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("releasing reg_mem\n"); 3868c2ecf20Sopenharmony_ci iounmap(itv->reg_mem); 3878c2ecf20Sopenharmony_ci itv->reg_mem = NULL; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci /* Release io memory */ 3908c2ecf20Sopenharmony_ci if (itv->has_cx23415 && itv->dec_mem != NULL) { 3918c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("releasing dec_mem\n"); 3928c2ecf20Sopenharmony_ci iounmap(itv->dec_mem); 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci itv->dec_mem = NULL; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci /* Release io memory */ 3978c2ecf20Sopenharmony_ci if (itv->enc_mem != NULL) { 3988c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("releasing enc_mem\n"); 3998c2ecf20Sopenharmony_ci iounmap(itv->enc_mem); 4008c2ecf20Sopenharmony_ci itv->enc_mem = NULL; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci} 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci/* Hauppauge card? get values from tveeprom */ 4058c2ecf20Sopenharmony_civoid ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci u8 eedata[256]; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci itv->i2c_client.addr = 0xA0 >> 1; 4108c2ecf20Sopenharmony_ci tveeprom_read(&itv->i2c_client, eedata, sizeof(eedata)); 4118c2ecf20Sopenharmony_ci tveeprom_hauppauge_analog(tv, eedata); 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic void ivtv_process_eeprom(struct ivtv *itv) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci struct tveeprom tv; 4178c2ecf20Sopenharmony_ci int pci_slot = PCI_SLOT(itv->pdev->devfn); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci ivtv_read_eeprom(itv, &tv); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci /* Many thanks to Steven Toth from Hauppauge for providing the 4228c2ecf20Sopenharmony_ci model numbers */ 4238c2ecf20Sopenharmony_ci switch (tv.model) { 4248c2ecf20Sopenharmony_ci /* In a few cases the PCI subsystem IDs do not correctly 4258c2ecf20Sopenharmony_ci identify the card. A better method is to check the 4268c2ecf20Sopenharmony_ci model number from the eeprom instead. */ 4278c2ecf20Sopenharmony_ci case 30012 ... 30039: /* Low profile PVR250 */ 4288c2ecf20Sopenharmony_ci case 32000 ... 32999: 4298c2ecf20Sopenharmony_ci case 48000 ... 48099: /* 48??? range are PVR250s with a cx23415 */ 4308c2ecf20Sopenharmony_ci case 48400 ... 48599: 4318c2ecf20Sopenharmony_ci itv->card = ivtv_get_card(IVTV_CARD_PVR_250); 4328c2ecf20Sopenharmony_ci break; 4338c2ecf20Sopenharmony_ci case 48100 ... 48399: 4348c2ecf20Sopenharmony_ci case 48600 ... 48999: 4358c2ecf20Sopenharmony_ci itv->card = ivtv_get_card(IVTV_CARD_PVR_350); 4368c2ecf20Sopenharmony_ci break; 4378c2ecf20Sopenharmony_ci case 23000 ... 23999: /* PVR500 */ 4388c2ecf20Sopenharmony_ci case 25000 ... 25999: /* Low profile PVR150 */ 4398c2ecf20Sopenharmony_ci case 26000 ... 26999: /* Regular PVR150 */ 4408c2ecf20Sopenharmony_ci itv->card = ivtv_get_card(IVTV_CARD_PVR_150); 4418c2ecf20Sopenharmony_ci break; 4428c2ecf20Sopenharmony_ci case 0: 4438c2ecf20Sopenharmony_ci IVTV_ERR("Invalid EEPROM\n"); 4448c2ecf20Sopenharmony_ci return; 4458c2ecf20Sopenharmony_ci default: 4468c2ecf20Sopenharmony_ci IVTV_ERR("Unknown model %d, defaulting to PVR-150\n", tv.model); 4478c2ecf20Sopenharmony_ci itv->card = ivtv_get_card(IVTV_CARD_PVR_150); 4488c2ecf20Sopenharmony_ci break; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci switch (tv.model) { 4528c2ecf20Sopenharmony_ci /* Old style PVR350 (with an saa7114) uses this input for 4538c2ecf20Sopenharmony_ci the tuner. */ 4548c2ecf20Sopenharmony_ci case 48254: 4558c2ecf20Sopenharmony_ci itv->card = ivtv_get_card(IVTV_CARD_PVR_350_V1); 4568c2ecf20Sopenharmony_ci break; 4578c2ecf20Sopenharmony_ci default: 4588c2ecf20Sopenharmony_ci break; 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci itv->v4l2_cap = itv->card->v4l2_capabilities; 4628c2ecf20Sopenharmony_ci itv->card_name = itv->card->name; 4638c2ecf20Sopenharmony_ci itv->card_i2c = itv->card->i2c; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci /* If this is a PVR500 then it should be possible to detect whether it is the 4668c2ecf20Sopenharmony_ci first or second unit by looking at the subsystem device ID: is bit 4 is 4678c2ecf20Sopenharmony_ci set, then it is the second unit (according to info from Hauppauge). 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci However, while this works for most cards, I have seen a few PVR500 cards 4708c2ecf20Sopenharmony_ci where both units have the same subsystem ID. 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci So instead I look at the reported 'PCI slot' (which is the slot on the PVR500 4738c2ecf20Sopenharmony_ci PCI bridge) and if it is 8, then it is assumed to be the first unit, otherwise 4748c2ecf20Sopenharmony_ci it is the second unit. It is possible that it is a different slot when ivtv is 4758c2ecf20Sopenharmony_ci used in Xen, in that case I ignore this card here. The worst that can happen 4768c2ecf20Sopenharmony_ci is that the card presents itself with a non-working radio device. 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci This detection is needed since the eeprom reports incorrectly that a radio is 4798c2ecf20Sopenharmony_ci present on the second unit. */ 4808c2ecf20Sopenharmony_ci if (tv.model / 1000 == 23) { 4818c2ecf20Sopenharmony_ci static const struct ivtv_card_tuner_i2c ivtv_i2c_radio = { 4828c2ecf20Sopenharmony_ci .radio = { 0x60, I2C_CLIENT_END }, 4838c2ecf20Sopenharmony_ci .demod = { 0x43, I2C_CLIENT_END }, 4848c2ecf20Sopenharmony_ci .tv = { 0x61, I2C_CLIENT_END }, 4858c2ecf20Sopenharmony_ci }; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci itv->card_name = "WinTV PVR 500"; 4888c2ecf20Sopenharmony_ci itv->card_i2c = &ivtv_i2c_radio; 4898c2ecf20Sopenharmony_ci if (pci_slot == 8 || pci_slot == 9) { 4908c2ecf20Sopenharmony_ci int is_first = (pci_slot & 1) == 0; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci itv->card_name = is_first ? "WinTV PVR 500 (unit #1)" : 4938c2ecf20Sopenharmony_ci "WinTV PVR 500 (unit #2)"; 4948c2ecf20Sopenharmony_ci if (!is_first) { 4958c2ecf20Sopenharmony_ci IVTV_INFO("Correcting tveeprom data: no radio present on second unit\n"); 4968c2ecf20Sopenharmony_ci tv.has_radio = 0; 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci } 5008c2ecf20Sopenharmony_ci IVTV_INFO("Autodetected %s\n", itv->card_name); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci switch (tv.tuner_hauppauge_model) { 5038c2ecf20Sopenharmony_ci case 85: 5048c2ecf20Sopenharmony_ci case 99: 5058c2ecf20Sopenharmony_ci case 112: 5068c2ecf20Sopenharmony_ci itv->pvr150_workaround = 1; 5078c2ecf20Sopenharmony_ci break; 5088c2ecf20Sopenharmony_ci default: 5098c2ecf20Sopenharmony_ci break; 5108c2ecf20Sopenharmony_ci } 5118c2ecf20Sopenharmony_ci if (tv.tuner_type == TUNER_ABSENT) 5128c2ecf20Sopenharmony_ci IVTV_ERR("tveeprom cannot autodetect tuner!\n"); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci if (itv->options.tuner == -1) 5158c2ecf20Sopenharmony_ci itv->options.tuner = tv.tuner_type; 5168c2ecf20Sopenharmony_ci if (itv->options.radio == -1) 5178c2ecf20Sopenharmony_ci itv->options.radio = (tv.has_radio != 0); 5188c2ecf20Sopenharmony_ci /* only enable newi2c if an IR blaster is present */ 5198c2ecf20Sopenharmony_ci if (itv->options.newi2c == -1 && tv.has_ir) { 5208c2ecf20Sopenharmony_ci itv->options.newi2c = (tv.has_ir & 4) ? 1 : 0; 5218c2ecf20Sopenharmony_ci if (itv->options.newi2c) { 5228c2ecf20Sopenharmony_ci IVTV_INFO("Reopen i2c bus for IR-blaster support\n"); 5238c2ecf20Sopenharmony_ci exit_ivtv_i2c(itv); 5248c2ecf20Sopenharmony_ci init_ivtv_i2c(itv); 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci if (itv->std != 0) 5298c2ecf20Sopenharmony_ci /* user specified tuner standard */ 5308c2ecf20Sopenharmony_ci return; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci /* autodetect tuner standard */ 5338c2ecf20Sopenharmony_ci if (tv.tuner_formats & V4L2_STD_PAL) { 5348c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("PAL tuner detected\n"); 5358c2ecf20Sopenharmony_ci itv->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H; 5368c2ecf20Sopenharmony_ci } else if (tv.tuner_formats & V4L2_STD_NTSC) { 5378c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("NTSC tuner detected\n"); 5388c2ecf20Sopenharmony_ci itv->std |= V4L2_STD_NTSC_M; 5398c2ecf20Sopenharmony_ci } else if (tv.tuner_formats & V4L2_STD_SECAM) { 5408c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("SECAM tuner detected\n"); 5418c2ecf20Sopenharmony_ci itv->std |= V4L2_STD_SECAM_L; 5428c2ecf20Sopenharmony_ci } else { 5438c2ecf20Sopenharmony_ci IVTV_INFO("No tuner detected, default to NTSC-M\n"); 5448c2ecf20Sopenharmony_ci itv->std |= V4L2_STD_NTSC_M; 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic v4l2_std_id ivtv_parse_std(struct ivtv *itv) 5498c2ecf20Sopenharmony_ci{ 5508c2ecf20Sopenharmony_ci switch (pal[0]) { 5518c2ecf20Sopenharmony_ci case '6': 5528c2ecf20Sopenharmony_ci tunertype = 0; 5538c2ecf20Sopenharmony_ci return V4L2_STD_PAL_60; 5548c2ecf20Sopenharmony_ci case 'b': 5558c2ecf20Sopenharmony_ci case 'B': 5568c2ecf20Sopenharmony_ci case 'g': 5578c2ecf20Sopenharmony_ci case 'G': 5588c2ecf20Sopenharmony_ci case 'h': 5598c2ecf20Sopenharmony_ci case 'H': 5608c2ecf20Sopenharmony_ci tunertype = 0; 5618c2ecf20Sopenharmony_ci return V4L2_STD_PAL_BG | V4L2_STD_PAL_H; 5628c2ecf20Sopenharmony_ci case 'n': 5638c2ecf20Sopenharmony_ci case 'N': 5648c2ecf20Sopenharmony_ci tunertype = 1; 5658c2ecf20Sopenharmony_ci if (pal[1] == 'c' || pal[1] == 'C') 5668c2ecf20Sopenharmony_ci return V4L2_STD_PAL_Nc; 5678c2ecf20Sopenharmony_ci return V4L2_STD_PAL_N; 5688c2ecf20Sopenharmony_ci case 'i': 5698c2ecf20Sopenharmony_ci case 'I': 5708c2ecf20Sopenharmony_ci tunertype = 0; 5718c2ecf20Sopenharmony_ci return V4L2_STD_PAL_I; 5728c2ecf20Sopenharmony_ci case 'd': 5738c2ecf20Sopenharmony_ci case 'D': 5748c2ecf20Sopenharmony_ci case 'k': 5758c2ecf20Sopenharmony_ci case 'K': 5768c2ecf20Sopenharmony_ci tunertype = 0; 5778c2ecf20Sopenharmony_ci return V4L2_STD_PAL_DK; 5788c2ecf20Sopenharmony_ci case 'M': 5798c2ecf20Sopenharmony_ci case 'm': 5808c2ecf20Sopenharmony_ci tunertype = 1; 5818c2ecf20Sopenharmony_ci return V4L2_STD_PAL_M; 5828c2ecf20Sopenharmony_ci case '-': 5838c2ecf20Sopenharmony_ci break; 5848c2ecf20Sopenharmony_ci default: 5858c2ecf20Sopenharmony_ci IVTV_WARN("pal= argument not recognised\n"); 5868c2ecf20Sopenharmony_ci return 0; 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci switch (secam[0]) { 5908c2ecf20Sopenharmony_ci case 'b': 5918c2ecf20Sopenharmony_ci case 'B': 5928c2ecf20Sopenharmony_ci case 'g': 5938c2ecf20Sopenharmony_ci case 'G': 5948c2ecf20Sopenharmony_ci case 'h': 5958c2ecf20Sopenharmony_ci case 'H': 5968c2ecf20Sopenharmony_ci tunertype = 0; 5978c2ecf20Sopenharmony_ci return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; 5988c2ecf20Sopenharmony_ci case 'd': 5998c2ecf20Sopenharmony_ci case 'D': 6008c2ecf20Sopenharmony_ci case 'k': 6018c2ecf20Sopenharmony_ci case 'K': 6028c2ecf20Sopenharmony_ci tunertype = 0; 6038c2ecf20Sopenharmony_ci return V4L2_STD_SECAM_DK; 6048c2ecf20Sopenharmony_ci case 'l': 6058c2ecf20Sopenharmony_ci case 'L': 6068c2ecf20Sopenharmony_ci tunertype = 0; 6078c2ecf20Sopenharmony_ci if (secam[1] == 'C' || secam[1] == 'c') 6088c2ecf20Sopenharmony_ci return V4L2_STD_SECAM_LC; 6098c2ecf20Sopenharmony_ci return V4L2_STD_SECAM_L; 6108c2ecf20Sopenharmony_ci case '-': 6118c2ecf20Sopenharmony_ci break; 6128c2ecf20Sopenharmony_ci default: 6138c2ecf20Sopenharmony_ci IVTV_WARN("secam= argument not recognised\n"); 6148c2ecf20Sopenharmony_ci return 0; 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci switch (ntsc[0]) { 6188c2ecf20Sopenharmony_ci case 'm': 6198c2ecf20Sopenharmony_ci case 'M': 6208c2ecf20Sopenharmony_ci tunertype = 1; 6218c2ecf20Sopenharmony_ci return V4L2_STD_NTSC_M; 6228c2ecf20Sopenharmony_ci case 'j': 6238c2ecf20Sopenharmony_ci case 'J': 6248c2ecf20Sopenharmony_ci tunertype = 1; 6258c2ecf20Sopenharmony_ci return V4L2_STD_NTSC_M_JP; 6268c2ecf20Sopenharmony_ci case 'k': 6278c2ecf20Sopenharmony_ci case 'K': 6288c2ecf20Sopenharmony_ci tunertype = 1; 6298c2ecf20Sopenharmony_ci return V4L2_STD_NTSC_M_KR; 6308c2ecf20Sopenharmony_ci case '-': 6318c2ecf20Sopenharmony_ci break; 6328c2ecf20Sopenharmony_ci default: 6338c2ecf20Sopenharmony_ci IVTV_WARN("ntsc= argument not recognised\n"); 6348c2ecf20Sopenharmony_ci return 0; 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci /* no match found */ 6388c2ecf20Sopenharmony_ci return 0; 6398c2ecf20Sopenharmony_ci} 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_cistatic void ivtv_process_options(struct ivtv *itv) 6428c2ecf20Sopenharmony_ci{ 6438c2ecf20Sopenharmony_ci const char *chipname; 6448c2ecf20Sopenharmony_ci int i, j; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers * 1024; 6478c2ecf20Sopenharmony_ci itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers * 1024; 6488c2ecf20Sopenharmony_ci itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers * 1024; 6498c2ecf20Sopenharmony_ci itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers; 6508c2ecf20Sopenharmony_ci itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers * 1024; 6518c2ecf20Sopenharmony_ci itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers * 1024; 6528c2ecf20Sopenharmony_ci itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers; 6538c2ecf20Sopenharmony_ci itv->options.cardtype = cardtype[itv->instance]; 6548c2ecf20Sopenharmony_ci itv->options.tuner = tuner[itv->instance]; 6558c2ecf20Sopenharmony_ci itv->options.radio = radio[itv->instance]; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci itv->options.i2c_clock_period = i2c_clock_period[itv->instance]; 6588c2ecf20Sopenharmony_ci if (itv->options.i2c_clock_period == -1) 6598c2ecf20Sopenharmony_ci itv->options.i2c_clock_period = IVTV_DEFAULT_I2C_CLOCK_PERIOD; 6608c2ecf20Sopenharmony_ci else if (itv->options.i2c_clock_period < 10) 6618c2ecf20Sopenharmony_ci itv->options.i2c_clock_period = 10; 6628c2ecf20Sopenharmony_ci else if (itv->options.i2c_clock_period > 4500) 6638c2ecf20Sopenharmony_ci itv->options.i2c_clock_period = 4500; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci itv->options.newi2c = newi2c; 6668c2ecf20Sopenharmony_ci if (tunertype < -1 || tunertype > 1) { 6678c2ecf20Sopenharmony_ci IVTV_WARN("Invalid tunertype argument, will autodetect instead\n"); 6688c2ecf20Sopenharmony_ci tunertype = -1; 6698c2ecf20Sopenharmony_ci } 6708c2ecf20Sopenharmony_ci itv->std = ivtv_parse_std(itv); 6718c2ecf20Sopenharmony_ci if (itv->std == 0 && tunertype >= 0) 6728c2ecf20Sopenharmony_ci itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN); 6738c2ecf20Sopenharmony_ci itv->has_cx23415 = (itv->pdev->device == PCI_DEVICE_ID_IVTV15); 6748c2ecf20Sopenharmony_ci chipname = itv->has_cx23415 ? "cx23415" : "cx23416"; 6758c2ecf20Sopenharmony_ci if (itv->options.cardtype == -1) { 6768c2ecf20Sopenharmony_ci IVTV_INFO("Ignore card (detected %s based chip)\n", chipname); 6778c2ecf20Sopenharmony_ci return; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci if ((itv->card = ivtv_get_card(itv->options.cardtype - 1))) { 6808c2ecf20Sopenharmony_ci IVTV_INFO("User specified %s card (detected %s based chip)\n", 6818c2ecf20Sopenharmony_ci itv->card->name, chipname); 6828c2ecf20Sopenharmony_ci } else if (itv->options.cardtype != 0) { 6838c2ecf20Sopenharmony_ci IVTV_ERR("Unknown user specified type, trying to autodetect card\n"); 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci if (itv->card == NULL) { 6868c2ecf20Sopenharmony_ci if (itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE || 6878c2ecf20Sopenharmony_ci itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 || 6888c2ecf20Sopenharmony_ci itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) { 6898c2ecf20Sopenharmony_ci itv->card = ivtv_get_card(itv->has_cx23415 ? IVTV_CARD_PVR_350 : IVTV_CARD_PVR_150); 6908c2ecf20Sopenharmony_ci IVTV_INFO("Autodetected Hauppauge card (%s based)\n", 6918c2ecf20Sopenharmony_ci chipname); 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci if (itv->card == NULL) { 6958c2ecf20Sopenharmony_ci for (i = 0; (itv->card = ivtv_get_card(i)); i++) { 6968c2ecf20Sopenharmony_ci if (itv->card->pci_list == NULL) 6978c2ecf20Sopenharmony_ci continue; 6988c2ecf20Sopenharmony_ci for (j = 0; itv->card->pci_list[j].device; j++) { 6998c2ecf20Sopenharmony_ci if (itv->pdev->device != 7008c2ecf20Sopenharmony_ci itv->card->pci_list[j].device) 7018c2ecf20Sopenharmony_ci continue; 7028c2ecf20Sopenharmony_ci if (itv->pdev->subsystem_vendor != 7038c2ecf20Sopenharmony_ci itv->card->pci_list[j].subsystem_vendor) 7048c2ecf20Sopenharmony_ci continue; 7058c2ecf20Sopenharmony_ci if (itv->pdev->subsystem_device != 7068c2ecf20Sopenharmony_ci itv->card->pci_list[j].subsystem_device) 7078c2ecf20Sopenharmony_ci continue; 7088c2ecf20Sopenharmony_ci IVTV_INFO("Autodetected %s card (%s based)\n", 7098c2ecf20Sopenharmony_ci itv->card->name, chipname); 7108c2ecf20Sopenharmony_ci goto done; 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_cidone: 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci if (itv->card == NULL) { 7178c2ecf20Sopenharmony_ci itv->card = ivtv_get_card(IVTV_CARD_PVR_150); 7188c2ecf20Sopenharmony_ci IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n", 7198c2ecf20Sopenharmony_ci itv->pdev->vendor, itv->pdev->device); 7208c2ecf20Sopenharmony_ci IVTV_ERR(" subsystem vendor/device: [%04x:%04x]\n", 7218c2ecf20Sopenharmony_ci itv->pdev->subsystem_vendor, itv->pdev->subsystem_device); 7228c2ecf20Sopenharmony_ci IVTV_ERR(" %s based\n", chipname); 7238c2ecf20Sopenharmony_ci IVTV_ERR("Defaulting to %s card\n", itv->card->name); 7248c2ecf20Sopenharmony_ci IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); 7258c2ecf20Sopenharmony_ci IVTV_ERR("card you have to the linux-media mailinglist (www.linuxtv.org)\n"); 7268c2ecf20Sopenharmony_ci IVTV_ERR("Prefix your subject line with [UNKNOWN IVTV CARD].\n"); 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci itv->v4l2_cap = itv->card->v4l2_capabilities; 7298c2ecf20Sopenharmony_ci itv->card_name = itv->card->name; 7308c2ecf20Sopenharmony_ci itv->card_i2c = itv->card->i2c; 7318c2ecf20Sopenharmony_ci} 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci/* Precondition: the ivtv structure has been memset to 0. Only 7348c2ecf20Sopenharmony_ci the dev and num fields have been filled in. 7358c2ecf20Sopenharmony_ci No assumptions on the card type may be made here (see ivtv_init_struct2 7368c2ecf20Sopenharmony_ci for that). 7378c2ecf20Sopenharmony_ci */ 7388c2ecf20Sopenharmony_cistatic int ivtv_init_struct1(struct ivtv *itv) 7398c2ecf20Sopenharmony_ci{ 7408c2ecf20Sopenharmony_ci itv->base_addr = pci_resource_start(itv->pdev, 0); 7418c2ecf20Sopenharmony_ci itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ 7428c2ecf20Sopenharmony_ci itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci mutex_init(&itv->serialize_lock); 7458c2ecf20Sopenharmony_ci mutex_init(&itv->i2c_bus_lock); 7468c2ecf20Sopenharmony_ci mutex_init(&itv->udma.lock); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci spin_lock_init(&itv->lock); 7498c2ecf20Sopenharmony_ci spin_lock_init(&itv->dma_reg_lock); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci kthread_init_worker(&itv->irq_worker); 7528c2ecf20Sopenharmony_ci itv->irq_worker_task = kthread_run(kthread_worker_fn, &itv->irq_worker, 7538c2ecf20Sopenharmony_ci "%s", itv->v4l2_dev.name); 7548c2ecf20Sopenharmony_ci if (IS_ERR(itv->irq_worker_task)) { 7558c2ecf20Sopenharmony_ci IVTV_ERR("Could not create ivtv task\n"); 7568c2ecf20Sopenharmony_ci return -1; 7578c2ecf20Sopenharmony_ci } 7588c2ecf20Sopenharmony_ci /* must use the FIFO scheduler as it is realtime sensitive */ 7598c2ecf20Sopenharmony_ci sched_set_fifo(itv->irq_worker_task); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci kthread_init_work(&itv->irq_work, ivtv_irq_work_handler); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci /* Initial settings */ 7648c2ecf20Sopenharmony_ci itv->cxhdl.port = CX2341X_PORT_MEMORY; 7658c2ecf20Sopenharmony_ci itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI; 7668c2ecf20Sopenharmony_ci init_waitqueue_head(&itv->eos_waitq); 7678c2ecf20Sopenharmony_ci init_waitqueue_head(&itv->event_waitq); 7688c2ecf20Sopenharmony_ci init_waitqueue_head(&itv->vsync_waitq); 7698c2ecf20Sopenharmony_ci init_waitqueue_head(&itv->dma_waitq); 7708c2ecf20Sopenharmony_ci timer_setup(&itv->dma_timer, ivtv_unfinished_dma, 0); 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci itv->cur_dma_stream = -1; 7738c2ecf20Sopenharmony_ci itv->cur_pio_stream = -1; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci /* Ctrls */ 7768c2ecf20Sopenharmony_ci itv->speed = 1000; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci /* VBI */ 7798c2ecf20Sopenharmony_ci itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; 7808c2ecf20Sopenharmony_ci itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci /* Init the sg table for osd/yuv output */ 7838c2ecf20Sopenharmony_ci sg_init_table(itv->udma.SGlist, IVTV_DMA_SG_OSD_ENT); 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci /* OSD */ 7868c2ecf20Sopenharmony_ci itv->osd_global_alpha_state = 1; 7878c2ecf20Sopenharmony_ci itv->osd_global_alpha = 255; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci /* YUV */ 7908c2ecf20Sopenharmony_ci atomic_set(&itv->yuv_info.next_dma_frame, -1); 7918c2ecf20Sopenharmony_ci itv->yuv_info.lace_mode = ivtv_yuv_mode; 7928c2ecf20Sopenharmony_ci itv->yuv_info.lace_threshold = ivtv_yuv_threshold; 7938c2ecf20Sopenharmony_ci itv->yuv_info.max_frames_buffered = 3; 7948c2ecf20Sopenharmony_ci itv->yuv_info.track_osd = 1; 7958c2ecf20Sopenharmony_ci return 0; 7968c2ecf20Sopenharmony_ci} 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci/* Second initialization part. Here the card type has been 7998c2ecf20Sopenharmony_ci autodetected. */ 8008c2ecf20Sopenharmony_cistatic void ivtv_init_struct2(struct ivtv *itv) 8018c2ecf20Sopenharmony_ci{ 8028c2ecf20Sopenharmony_ci int i; 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++) 8058c2ecf20Sopenharmony_ci if (itv->card->video_inputs[i].video_type == 0) 8068c2ecf20Sopenharmony_ci break; 8078c2ecf20Sopenharmony_ci itv->nof_inputs = i; 8088c2ecf20Sopenharmony_ci for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++) 8098c2ecf20Sopenharmony_ci if (itv->card->audio_inputs[i].audio_type == 0) 8108c2ecf20Sopenharmony_ci break; 8118c2ecf20Sopenharmony_ci itv->nof_audio_inputs = i; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci if (itv->card->hw_all & IVTV_HW_CX25840) { 8148c2ecf20Sopenharmony_ci itv->vbi.sliced_size = 288; /* multiple of 16, real size = 284 */ 8158c2ecf20Sopenharmony_ci } else { 8168c2ecf20Sopenharmony_ci itv->vbi.sliced_size = 64; /* multiple of 16, real size = 52 */ 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci /* Find tuner input */ 8208c2ecf20Sopenharmony_ci for (i = 0; i < itv->nof_inputs; i++) { 8218c2ecf20Sopenharmony_ci if (itv->card->video_inputs[i].video_type == 8228c2ecf20Sopenharmony_ci IVTV_CARD_INPUT_VID_TUNER) 8238c2ecf20Sopenharmony_ci break; 8248c2ecf20Sopenharmony_ci } 8258c2ecf20Sopenharmony_ci if (i >= itv->nof_inputs) 8268c2ecf20Sopenharmony_ci i = 0; 8278c2ecf20Sopenharmony_ci itv->active_input = i; 8288c2ecf20Sopenharmony_ci itv->audio_input = itv->card->video_inputs[i].audio_index; 8298c2ecf20Sopenharmony_ci} 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_cistatic int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, 8328c2ecf20Sopenharmony_ci const struct pci_device_id *pci_id) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci u16 cmd; 8358c2ecf20Sopenharmony_ci unsigned char pci_latency; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("Enabling pci device\n"); 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci if (pci_enable_device(pdev)) { 8408c2ecf20Sopenharmony_ci IVTV_ERR("Can't enable device!\n"); 8418c2ecf20Sopenharmony_ci return -EIO; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { 8448c2ecf20Sopenharmony_ci IVTV_ERR("No suitable DMA available.\n"); 8458c2ecf20Sopenharmony_ci return -EIO; 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) { 8488c2ecf20Sopenharmony_ci IVTV_ERR("Cannot request encoder memory region.\n"); 8498c2ecf20Sopenharmony_ci return -EIO; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET, 8538c2ecf20Sopenharmony_ci IVTV_REG_SIZE, "ivtv registers")) { 8548c2ecf20Sopenharmony_ci IVTV_ERR("Cannot request register memory region.\n"); 8558c2ecf20Sopenharmony_ci release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); 8568c2ecf20Sopenharmony_ci return -EIO; 8578c2ecf20Sopenharmony_ci } 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci if (itv->has_cx23415 && 8608c2ecf20Sopenharmony_ci !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, 8618c2ecf20Sopenharmony_ci IVTV_DECODER_SIZE, "ivtv decoder")) { 8628c2ecf20Sopenharmony_ci IVTV_ERR("Cannot request decoder memory region.\n"); 8638c2ecf20Sopenharmony_ci release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); 8648c2ecf20Sopenharmony_ci release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); 8658c2ecf20Sopenharmony_ci return -EIO; 8668c2ecf20Sopenharmony_ci } 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci /* Check for bus mastering */ 8698c2ecf20Sopenharmony_ci pci_read_config_word(pdev, PCI_COMMAND, &cmd); 8708c2ecf20Sopenharmony_ci if (!(cmd & PCI_COMMAND_MASTER)) { 8718c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("Attempting to enable Bus Mastering\n"); 8728c2ecf20Sopenharmony_ci pci_set_master(pdev); 8738c2ecf20Sopenharmony_ci pci_read_config_word(pdev, PCI_COMMAND, &cmd); 8748c2ecf20Sopenharmony_ci if (!(cmd & PCI_COMMAND_MASTER)) { 8758c2ecf20Sopenharmony_ci IVTV_ERR("Bus Mastering is not enabled\n"); 8768c2ecf20Sopenharmony_ci return -ENXIO; 8778c2ecf20Sopenharmony_ci } 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("Bus Mastering Enabled.\n"); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (pci_latency < 64 && ivtv_pci_latency) { 8848c2ecf20Sopenharmony_ci IVTV_INFO("Unreasonably low latency timer, setting to 64 (was %d)\n", 8858c2ecf20Sopenharmony_ci pci_latency); 8868c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); 8878c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci /* This config space value relates to DMA latencies. The 8908c2ecf20Sopenharmony_ci default value 0x8080 is too low however and will lead 8918c2ecf20Sopenharmony_ci to DMA errors. 0xffff is the max value which solves 8928c2ecf20Sopenharmony_ci these problems. */ 8938c2ecf20Sopenharmony_ci pci_write_config_dword(pdev, 0x40, 0xffff); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, irq: %d, latency: %d, memory: 0x%llx\n", 8968c2ecf20Sopenharmony_ci pdev->device, pdev->revision, pdev->bus->number, 8978c2ecf20Sopenharmony_ci PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), 8988c2ecf20Sopenharmony_ci pdev->irq, pci_latency, (u64)itv->base_addr); 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci return 0; 9018c2ecf20Sopenharmony_ci} 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_cistatic void ivtv_load_and_init_modules(struct ivtv *itv) 9048c2ecf20Sopenharmony_ci{ 9058c2ecf20Sopenharmony_ci u32 hw = itv->card->hw_all; 9068c2ecf20Sopenharmony_ci unsigned i; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci /* check which i2c devices are actually found */ 9098c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) { 9108c2ecf20Sopenharmony_ci u32 device = BIT(i); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci if (!(device & hw)) 9138c2ecf20Sopenharmony_ci continue; 9148c2ecf20Sopenharmony_ci if (device == IVTV_HW_GPIO || device == IVTV_HW_TVEEPROM) { 9158c2ecf20Sopenharmony_ci /* GPIO and TVEEPROM do not use i2c probing */ 9168c2ecf20Sopenharmony_ci itv->hw_flags |= device; 9178c2ecf20Sopenharmony_ci continue; 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci if (ivtv_i2c_register(itv, i) == 0) 9208c2ecf20Sopenharmony_ci itv->hw_flags |= device; 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci /* probe for legacy IR controllers that aren't in card definitions */ 9248c2ecf20Sopenharmony_ci if ((itv->hw_flags & IVTV_HW_IR_ANY) == 0) 9258c2ecf20Sopenharmony_ci ivtv_i2c_new_ir_legacy(itv); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci if (itv->card->hw_all & IVTV_HW_CX25840) 9288c2ecf20Sopenharmony_ci itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840); 9298c2ecf20Sopenharmony_ci else if (itv->card->hw_all & IVTV_HW_SAA717X) 9308c2ecf20Sopenharmony_ci itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA717X); 9318c2ecf20Sopenharmony_ci else if (itv->card->hw_all & IVTV_HW_SAA7114) 9328c2ecf20Sopenharmony_ci itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7114); 9338c2ecf20Sopenharmony_ci else 9348c2ecf20Sopenharmony_ci itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7115); 9358c2ecf20Sopenharmony_ci itv->sd_audio = ivtv_find_hw(itv, itv->card->hw_audio_ctrl); 9368c2ecf20Sopenharmony_ci itv->sd_muxer = ivtv_find_hw(itv, itv->card->hw_muxer); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci hw = itv->hw_flags; 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci if (itv->card->type == IVTV_CARD_CX23416GYC) { 9418c2ecf20Sopenharmony_ci /* Several variations of this card exist, detect which card 9428c2ecf20Sopenharmony_ci type should be used. */ 9438c2ecf20Sopenharmony_ci if ((hw & (IVTV_HW_UPD64031A | IVTV_HW_UPD6408X)) == 0) 9448c2ecf20Sopenharmony_ci itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGRYCS); 9458c2ecf20Sopenharmony_ci else if ((hw & IVTV_HW_UPD64031A) == 0) 9468c2ecf20Sopenharmony_ci itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGR); 9478c2ecf20Sopenharmony_ci } 9488c2ecf20Sopenharmony_ci else if (itv->card->type == IVTV_CARD_GV_MVPRX || 9498c2ecf20Sopenharmony_ci itv->card->type == IVTV_CARD_GV_MVPRX2E) { 9508c2ecf20Sopenharmony_ci /* The crystal frequency of GVMVPRX is 24.576MHz */ 9518c2ecf20Sopenharmony_ci v4l2_subdev_call(itv->sd_video, video, s_crystal_freq, 9528c2ecf20Sopenharmony_ci SAA7115_FREQ_24_576_MHZ, SAA7115_FREQ_FL_UCGC); 9538c2ecf20Sopenharmony_ci } 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci if (hw & IVTV_HW_CX25840) { 9568c2ecf20Sopenharmony_ci itv->vbi.raw_decoder_line_size = 1444; 9578c2ecf20Sopenharmony_ci itv->vbi.raw_decoder_sav_odd_field = 0x20; 9588c2ecf20Sopenharmony_ci itv->vbi.raw_decoder_sav_even_field = 0x60; 9598c2ecf20Sopenharmony_ci itv->vbi.sliced_decoder_line_size = 272; 9608c2ecf20Sopenharmony_ci itv->vbi.sliced_decoder_sav_odd_field = 0xB0; 9618c2ecf20Sopenharmony_ci itv->vbi.sliced_decoder_sav_even_field = 0xF0; 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci if (hw & IVTV_HW_SAA711X) { 9658c2ecf20Sopenharmony_ci /* determine the exact saa711x model */ 9668c2ecf20Sopenharmony_ci itv->hw_flags &= ~IVTV_HW_SAA711X; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci if (strstr(itv->sd_video->name, "saa7114")) { 9698c2ecf20Sopenharmony_ci itv->hw_flags |= IVTV_HW_SAA7114; 9708c2ecf20Sopenharmony_ci /* VBI is not yet supported by the saa7114 driver. */ 9718c2ecf20Sopenharmony_ci itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE); 9728c2ecf20Sopenharmony_ci } else { 9738c2ecf20Sopenharmony_ci itv->hw_flags |= IVTV_HW_SAA7115; 9748c2ecf20Sopenharmony_ci } 9758c2ecf20Sopenharmony_ci itv->vbi.raw_decoder_line_size = 1443; 9768c2ecf20Sopenharmony_ci itv->vbi.raw_decoder_sav_odd_field = 0x25; 9778c2ecf20Sopenharmony_ci itv->vbi.raw_decoder_sav_even_field = 0x62; 9788c2ecf20Sopenharmony_ci itv->vbi.sliced_decoder_line_size = 51; 9798c2ecf20Sopenharmony_ci itv->vbi.sliced_decoder_sav_odd_field = 0xAB; 9808c2ecf20Sopenharmony_ci itv->vbi.sliced_decoder_sav_even_field = 0xEC; 9818c2ecf20Sopenharmony_ci } 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci if (hw & IVTV_HW_SAA717X) { 9848c2ecf20Sopenharmony_ci itv->vbi.raw_decoder_line_size = 1443; 9858c2ecf20Sopenharmony_ci itv->vbi.raw_decoder_sav_odd_field = 0x25; 9868c2ecf20Sopenharmony_ci itv->vbi.raw_decoder_sav_even_field = 0x62; 9878c2ecf20Sopenharmony_ci itv->vbi.sliced_decoder_line_size = 51; 9888c2ecf20Sopenharmony_ci itv->vbi.sliced_decoder_sav_odd_field = 0xAB; 9898c2ecf20Sopenharmony_ci itv->vbi.sliced_decoder_sav_even_field = 0xEC; 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci} 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_cistatic int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) 9948c2ecf20Sopenharmony_ci{ 9958c2ecf20Sopenharmony_ci int retval = 0; 9968c2ecf20Sopenharmony_ci int vbi_buf_size; 9978c2ecf20Sopenharmony_ci struct ivtv *itv; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci itv = kzalloc(sizeof(struct ivtv), GFP_KERNEL); 10008c2ecf20Sopenharmony_ci if (itv == NULL) 10018c2ecf20Sopenharmony_ci return -ENOMEM; 10028c2ecf20Sopenharmony_ci itv->pdev = pdev; 10038c2ecf20Sopenharmony_ci itv->instance = v4l2_device_set_name(&itv->v4l2_dev, "ivtv", 10048c2ecf20Sopenharmony_ci &ivtv_instance); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev); 10078c2ecf20Sopenharmony_ci if (retval) { 10088c2ecf20Sopenharmony_ci kfree(itv); 10098c2ecf20Sopenharmony_ci return retval; 10108c2ecf20Sopenharmony_ci } 10118c2ecf20Sopenharmony_ci IVTV_INFO("Initializing card %d\n", itv->instance); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci ivtv_process_options(itv); 10148c2ecf20Sopenharmony_ci if (itv->options.cardtype == -1) { 10158c2ecf20Sopenharmony_ci retval = -ENODEV; 10168c2ecf20Sopenharmony_ci goto err; 10178c2ecf20Sopenharmony_ci } 10188c2ecf20Sopenharmony_ci if (ivtv_init_struct1(itv)) { 10198c2ecf20Sopenharmony_ci retval = -ENOMEM; 10208c2ecf20Sopenharmony_ci goto err; 10218c2ecf20Sopenharmony_ci } 10228c2ecf20Sopenharmony_ci retval = cx2341x_handler_init(&itv->cxhdl, 50); 10238c2ecf20Sopenharmony_ci if (retval) 10248c2ecf20Sopenharmony_ci goto err; 10258c2ecf20Sopenharmony_ci itv->v4l2_dev.ctrl_handler = &itv->cxhdl.hdl; 10268c2ecf20Sopenharmony_ci itv->cxhdl.ops = &ivtv_cxhdl_ops; 10278c2ecf20Sopenharmony_ci itv->cxhdl.priv = itv; 10288c2ecf20Sopenharmony_ci itv->cxhdl.func = ivtv_api_func; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("base addr: 0x%llx\n", (u64)itv->base_addr); 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci /* PCI Device Setup */ 10338c2ecf20Sopenharmony_ci retval = ivtv_setup_pci(itv, pdev, pci_id); 10348c2ecf20Sopenharmony_ci if (retval == -EIO) 10358c2ecf20Sopenharmony_ci goto free_worker; 10368c2ecf20Sopenharmony_ci if (retval == -ENXIO) 10378c2ecf20Sopenharmony_ci goto free_mem; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci /* map io memory */ 10408c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", 10418c2ecf20Sopenharmony_ci (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE); 10428c2ecf20Sopenharmony_ci itv->enc_mem = ioremap(itv->base_addr + IVTV_ENCODER_OFFSET, 10438c2ecf20Sopenharmony_ci IVTV_ENCODER_SIZE); 10448c2ecf20Sopenharmony_ci if (!itv->enc_mem) { 10458c2ecf20Sopenharmony_ci IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 encoder memory\n"); 10468c2ecf20Sopenharmony_ci IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of vmalloc address space for this window\n"); 10478c2ecf20Sopenharmony_ci IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); 10488c2ecf20Sopenharmony_ci IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n"); 10498c2ecf20Sopenharmony_ci retval = -ENOMEM; 10508c2ecf20Sopenharmony_ci goto free_mem; 10518c2ecf20Sopenharmony_ci } 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci if (itv->has_cx23415) { 10548c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", 10558c2ecf20Sopenharmony_ci (u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); 10568c2ecf20Sopenharmony_ci itv->dec_mem = ioremap(itv->base_addr + IVTV_DECODER_OFFSET, 10578c2ecf20Sopenharmony_ci IVTV_DECODER_SIZE); 10588c2ecf20Sopenharmony_ci if (!itv->dec_mem) { 10598c2ecf20Sopenharmony_ci IVTV_ERR("ioremap failed. Can't get a window into CX23415 decoder memory\n"); 10608c2ecf20Sopenharmony_ci IVTV_ERR("Each capture card with a CX23415 needs 8 MB of vmalloc address space for this window\n"); 10618c2ecf20Sopenharmony_ci IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); 10628c2ecf20Sopenharmony_ci IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n"); 10638c2ecf20Sopenharmony_ci retval = -ENOMEM; 10648c2ecf20Sopenharmony_ci goto free_mem; 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci } 10678c2ecf20Sopenharmony_ci else { 10688c2ecf20Sopenharmony_ci itv->dec_mem = itv->enc_mem; 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci /* map registers memory */ 10728c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", 10738c2ecf20Sopenharmony_ci (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); 10748c2ecf20Sopenharmony_ci itv->reg_mem = 10758c2ecf20Sopenharmony_ci ioremap(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); 10768c2ecf20Sopenharmony_ci if (!itv->reg_mem) { 10778c2ecf20Sopenharmony_ci IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 register space\n"); 10788c2ecf20Sopenharmony_ci IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of vmalloc address space for this window\n"); 10798c2ecf20Sopenharmony_ci IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); 10808c2ecf20Sopenharmony_ci IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n"); 10818c2ecf20Sopenharmony_ci retval = -ENOMEM; 10828c2ecf20Sopenharmony_ci goto free_io; 10838c2ecf20Sopenharmony_ci } 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci retval = ivtv_gpio_init(itv); 10868c2ecf20Sopenharmony_ci if (retval) 10878c2ecf20Sopenharmony_ci goto free_io; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci /* active i2c */ 10908c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("activating i2c...\n"); 10918c2ecf20Sopenharmony_ci if (init_ivtv_i2c(itv)) { 10928c2ecf20Sopenharmony_ci IVTV_ERR("Could not initialize i2c\n"); 10938c2ecf20Sopenharmony_ci goto free_io; 10948c2ecf20Sopenharmony_ci } 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci if (itv->card->hw_all & IVTV_HW_TVEEPROM) { 10978c2ecf20Sopenharmony_ci /* Based on the model number the cardtype may be changed. 10988c2ecf20Sopenharmony_ci The PCI IDs are not always reliable. */ 10998c2ecf20Sopenharmony_ci ivtv_process_eeprom(itv); 11008c2ecf20Sopenharmony_ci } 11018c2ecf20Sopenharmony_ci if (itv->card->comment) 11028c2ecf20Sopenharmony_ci IVTV_INFO("%s", itv->card->comment); 11038c2ecf20Sopenharmony_ci if (itv->card->v4l2_capabilities == 0) { 11048c2ecf20Sopenharmony_ci /* card was detected but is not supported */ 11058c2ecf20Sopenharmony_ci retval = -ENODEV; 11068c2ecf20Sopenharmony_ci goto free_i2c; 11078c2ecf20Sopenharmony_ci } 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci if (itv->std == 0) { 11108c2ecf20Sopenharmony_ci itv->std = V4L2_STD_NTSC_M; 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci if (itv->options.tuner == -1) { 11148c2ecf20Sopenharmony_ci int i; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci for (i = 0; i < IVTV_CARD_MAX_TUNERS; i++) { 11178c2ecf20Sopenharmony_ci if ((itv->std & itv->card->tuners[i].std) == 0) 11188c2ecf20Sopenharmony_ci continue; 11198c2ecf20Sopenharmony_ci itv->options.tuner = itv->card->tuners[i].tuner; 11208c2ecf20Sopenharmony_ci break; 11218c2ecf20Sopenharmony_ci } 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci /* if no tuner was found, then pick the first tuner in the card list */ 11248c2ecf20Sopenharmony_ci if (itv->options.tuner == -1 && itv->card->tuners[0].std) { 11258c2ecf20Sopenharmony_ci itv->std = itv->card->tuners[0].std; 11268c2ecf20Sopenharmony_ci if (itv->std & V4L2_STD_PAL) 11278c2ecf20Sopenharmony_ci itv->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H; 11288c2ecf20Sopenharmony_ci else if (itv->std & V4L2_STD_NTSC) 11298c2ecf20Sopenharmony_ci itv->std = V4L2_STD_NTSC_M; 11308c2ecf20Sopenharmony_ci else if (itv->std & V4L2_STD_SECAM) 11318c2ecf20Sopenharmony_ci itv->std = V4L2_STD_SECAM_L; 11328c2ecf20Sopenharmony_ci itv->options.tuner = itv->card->tuners[0].tuner; 11338c2ecf20Sopenharmony_ci } 11348c2ecf20Sopenharmony_ci if (itv->options.radio == -1) 11358c2ecf20Sopenharmony_ci itv->options.radio = (itv->card->radio_input.audio_type != 0); 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci /* The card is now fully identified, continue with card-specific 11388c2ecf20Sopenharmony_ci initialization. */ 11398c2ecf20Sopenharmony_ci ivtv_init_struct2(itv); 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci ivtv_load_and_init_modules(itv); 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci if (itv->std & V4L2_STD_525_60) { 11448c2ecf20Sopenharmony_ci itv->is_60hz = 1; 11458c2ecf20Sopenharmony_ci itv->is_out_60hz = 1; 11468c2ecf20Sopenharmony_ci } else { 11478c2ecf20Sopenharmony_ci itv->is_50hz = 1; 11488c2ecf20Sopenharmony_ci itv->is_out_50hz = 1; 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci itv->yuv_info.osd_full_w = 720; 11528c2ecf20Sopenharmony_ci itv->yuv_info.osd_full_h = itv->is_out_50hz ? 576 : 480; 11538c2ecf20Sopenharmony_ci itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w; 11548c2ecf20Sopenharmony_ci itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h; 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz); 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000; 11598c2ecf20Sopenharmony_ci itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200; 11608c2ecf20Sopenharmony_ci itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_MPG] = 0x10000; 11618c2ecf20Sopenharmony_ci itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = 0x10000; 11628c2ecf20Sopenharmony_ci itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = 0x08000; 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci /* Setup VBI Raw Size. Should be big enough to hold PAL. 11658c2ecf20Sopenharmony_ci It is possible to switch between PAL and NTSC, so we need to 11668c2ecf20Sopenharmony_ci take the largest size here. */ 11678c2ecf20Sopenharmony_ci /* 1456 is multiple of 16, real size = 1444 */ 11688c2ecf20Sopenharmony_ci itv->vbi.raw_size = 1456; 11698c2ecf20Sopenharmony_ci /* We use a buffer size of 1/2 of the total size needed for a 11708c2ecf20Sopenharmony_ci frame. This is actually very useful, since we now receive 11718c2ecf20Sopenharmony_ci a field at a time and that makes 'compressing' the raw data 11728c2ecf20Sopenharmony_ci down to size by stripping off the SAV codes a lot easier. 11738c2ecf20Sopenharmony_ci Note: having two different buffer sizes prevents standard 11748c2ecf20Sopenharmony_ci switching on the fly. We need to find a better solution... */ 11758c2ecf20Sopenharmony_ci vbi_buf_size = itv->vbi.raw_size * (itv->is_60hz ? 24 : 36) / 2; 11768c2ecf20Sopenharmony_ci itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_VBI] = vbi_buf_size; 11778c2ecf20Sopenharmony_ci itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_VBI] = sizeof(struct v4l2_sliced_vbi_data) * 36; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci if (itv->options.radio > 0) 11808c2ecf20Sopenharmony_ci itv->v4l2_cap |= V4L2_CAP_RADIO; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci if (itv->options.tuner > -1) { 11838c2ecf20Sopenharmony_ci struct tuner_setup setup; 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci setup.addr = ADDR_UNSET; 11868c2ecf20Sopenharmony_ci setup.type = itv->options.tuner; 11878c2ecf20Sopenharmony_ci setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ 11888c2ecf20Sopenharmony_ci if (itv->options.radio > 0) 11898c2ecf20Sopenharmony_ci setup.mode_mask |= T_RADIO; 11908c2ecf20Sopenharmony_ci setup.tuner_callback = (setup.type == TUNER_XC2028) ? 11918c2ecf20Sopenharmony_ci ivtv_reset_tuner_gpio : NULL; 11928c2ecf20Sopenharmony_ci ivtv_call_all(itv, tuner, s_type_addr, &setup); 11938c2ecf20Sopenharmony_ci if (setup.type == TUNER_XC2028) { 11948c2ecf20Sopenharmony_ci static struct xc2028_ctrl ctrl = { 11958c2ecf20Sopenharmony_ci .fname = XC2028_DEFAULT_FIRMWARE, 11968c2ecf20Sopenharmony_ci .max_len = 64, 11978c2ecf20Sopenharmony_ci }; 11988c2ecf20Sopenharmony_ci struct v4l2_priv_tun_config cfg = { 11998c2ecf20Sopenharmony_ci .tuner = itv->options.tuner, 12008c2ecf20Sopenharmony_ci .priv = &ctrl, 12018c2ecf20Sopenharmony_ci }; 12028c2ecf20Sopenharmony_ci ivtv_call_all(itv, tuner, s_config, &cfg); 12038c2ecf20Sopenharmony_ci } 12048c2ecf20Sopenharmony_ci } 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) 12078c2ecf20Sopenharmony_ci are not. */ 12088c2ecf20Sopenharmony_ci itv->tuner_std = itv->std; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { 12118c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler; 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, 12148c2ecf20Sopenharmony_ci V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 0, 0); 12158c2ecf20Sopenharmony_ci itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, 12168c2ecf20Sopenharmony_ci V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0, 0, 0); 12178c2ecf20Sopenharmony_ci /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported, 12188c2ecf20Sopenharmony_ci mask that menu item. */ 12198c2ecf20Sopenharmony_ci itv->ctrl_audio_playback = 12208c2ecf20Sopenharmony_ci v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, 12218c2ecf20Sopenharmony_ci V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, 12228c2ecf20Sopenharmony_ci V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, 12238c2ecf20Sopenharmony_ci 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, 12248c2ecf20Sopenharmony_ci V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO); 12258c2ecf20Sopenharmony_ci itv->ctrl_audio_multilingual_playback = 12268c2ecf20Sopenharmony_ci v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, 12278c2ecf20Sopenharmony_ci V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, 12288c2ecf20Sopenharmony_ci V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, 12298c2ecf20Sopenharmony_ci 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, 12308c2ecf20Sopenharmony_ci V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT); 12318c2ecf20Sopenharmony_ci if (hdl->error) { 12328c2ecf20Sopenharmony_ci retval = hdl->error; 12338c2ecf20Sopenharmony_ci goto free_i2c; 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci v4l2_ctrl_cluster(2, &itv->ctrl_pts); 12368c2ecf20Sopenharmony_ci v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback); 12378c2ecf20Sopenharmony_ci ivtv_call_all(itv, video, s_std_output, itv->std); 12388c2ecf20Sopenharmony_ci /* Turn off the output signal. The mpeg decoder is not yet 12398c2ecf20Sopenharmony_ci active so without this you would get a green image until the 12408c2ecf20Sopenharmony_ci mpeg decoder becomes active. */ 12418c2ecf20Sopenharmony_ci ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0); 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci /* clear interrupt mask, effectively disabling interrupts */ 12458c2ecf20Sopenharmony_ci ivtv_set_irq_mask(itv, 0xffffffff); 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci /* Register IRQ */ 12488c2ecf20Sopenharmony_ci retval = request_irq(itv->pdev->irq, ivtv_irq_handler, 12498c2ecf20Sopenharmony_ci IRQF_SHARED, itv->v4l2_dev.name, (void *)itv); 12508c2ecf20Sopenharmony_ci if (retval) { 12518c2ecf20Sopenharmony_ci IVTV_ERR("Failed to register irq %d\n", retval); 12528c2ecf20Sopenharmony_ci goto free_i2c; 12538c2ecf20Sopenharmony_ci } 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci retval = ivtv_streams_setup(itv); 12568c2ecf20Sopenharmony_ci if (retval) { 12578c2ecf20Sopenharmony_ci IVTV_ERR("Error %d setting up streams\n", retval); 12588c2ecf20Sopenharmony_ci goto free_irq; 12598c2ecf20Sopenharmony_ci } 12608c2ecf20Sopenharmony_ci retval = ivtv_streams_register(itv); 12618c2ecf20Sopenharmony_ci if (retval) { 12628c2ecf20Sopenharmony_ci IVTV_ERR("Error %d registering devices\n", retval); 12638c2ecf20Sopenharmony_ci goto free_streams; 12648c2ecf20Sopenharmony_ci } 12658c2ecf20Sopenharmony_ci IVTV_INFO("Initialized card: %s\n", itv->card_name); 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci /* Load ivtv submodules (ivtv-alsa) */ 12688c2ecf20Sopenharmony_ci request_modules(itv); 12698c2ecf20Sopenharmony_ci return 0; 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_cifree_streams: 12728c2ecf20Sopenharmony_ci ivtv_streams_cleanup(itv); 12738c2ecf20Sopenharmony_cifree_irq: 12748c2ecf20Sopenharmony_ci free_irq(itv->pdev->irq, (void *)itv); 12758c2ecf20Sopenharmony_cifree_i2c: 12768c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(&itv->cxhdl.hdl); 12778c2ecf20Sopenharmony_ci exit_ivtv_i2c(itv); 12788c2ecf20Sopenharmony_cifree_io: 12798c2ecf20Sopenharmony_ci ivtv_iounmap(itv); 12808c2ecf20Sopenharmony_cifree_mem: 12818c2ecf20Sopenharmony_ci release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); 12828c2ecf20Sopenharmony_ci release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); 12838c2ecf20Sopenharmony_ci if (itv->has_cx23415) 12848c2ecf20Sopenharmony_ci release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); 12858c2ecf20Sopenharmony_cifree_worker: 12868c2ecf20Sopenharmony_ci kthread_stop(itv->irq_worker_task); 12878c2ecf20Sopenharmony_cierr: 12888c2ecf20Sopenharmony_ci if (retval == 0) 12898c2ecf20Sopenharmony_ci retval = -ENODEV; 12908c2ecf20Sopenharmony_ci IVTV_ERR("Error %d on initialization\n", retval); 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci v4l2_device_unregister(&itv->v4l2_dev); 12938c2ecf20Sopenharmony_ci kfree(itv); 12948c2ecf20Sopenharmony_ci return retval; 12958c2ecf20Sopenharmony_ci} 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ciint ivtv_init_on_first_open(struct ivtv *itv) 12988c2ecf20Sopenharmony_ci{ 12998c2ecf20Sopenharmony_ci struct v4l2_frequency vf; 13008c2ecf20Sopenharmony_ci /* Needed to call ioctls later */ 13018c2ecf20Sopenharmony_ci struct ivtv_open_id fh; 13028c2ecf20Sopenharmony_ci int fw_retry_count = 3; 13038c2ecf20Sopenharmony_ci int video_input; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci fh.itv = itv; 13068c2ecf20Sopenharmony_ci fh.type = IVTV_ENC_STREAM_TYPE_MPG; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci if (test_bit(IVTV_F_I_FAILED, &itv->i_flags)) 13098c2ecf20Sopenharmony_ci return -ENXIO; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci if (test_and_set_bit(IVTV_F_I_INITED, &itv->i_flags)) 13128c2ecf20Sopenharmony_ci return 0; 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci while (--fw_retry_count > 0) { 13158c2ecf20Sopenharmony_ci /* load firmware */ 13168c2ecf20Sopenharmony_ci if (ivtv_firmware_init(itv) == 0) 13178c2ecf20Sopenharmony_ci break; 13188c2ecf20Sopenharmony_ci if (fw_retry_count > 1) 13198c2ecf20Sopenharmony_ci IVTV_WARN("Retry loading firmware\n"); 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci if (fw_retry_count == 0) { 13238c2ecf20Sopenharmony_ci set_bit(IVTV_F_I_FAILED, &itv->i_flags); 13248c2ecf20Sopenharmony_ci return -ENXIO; 13258c2ecf20Sopenharmony_ci } 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci /* Try and get firmware versions */ 13288c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("Getting firmware version..\n"); 13298c2ecf20Sopenharmony_ci ivtv_firmware_versions(itv); 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci if (itv->card->hw_all & IVTV_HW_CX25840) 13328c2ecf20Sopenharmony_ci v4l2_subdev_call(itv->sd_video, core, load_fw); 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci vf.tuner = 0; 13358c2ecf20Sopenharmony_ci vf.type = V4L2_TUNER_ANALOG_TV; 13368c2ecf20Sopenharmony_ci vf.frequency = 6400; /* the tuner 'baseline' frequency */ 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci /* Set initial frequency. For PAL/SECAM broadcasts no 13398c2ecf20Sopenharmony_ci 'default' channel exists AFAIK. */ 13408c2ecf20Sopenharmony_ci if (itv->std == V4L2_STD_NTSC_M_JP) { 13418c2ecf20Sopenharmony_ci vf.frequency = 1460; /* ch. 1 91250*16/1000 */ 13428c2ecf20Sopenharmony_ci } 13438c2ecf20Sopenharmony_ci else if (itv->std & V4L2_STD_NTSC_M) { 13448c2ecf20Sopenharmony_ci vf.frequency = 1076; /* ch. 4 67250*16/1000 */ 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci video_input = itv->active_input; 13488c2ecf20Sopenharmony_ci itv->active_input++; /* Force update of input */ 13498c2ecf20Sopenharmony_ci ivtv_s_input(NULL, &fh, video_input); 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code 13528c2ecf20Sopenharmony_ci in one place. */ 13538c2ecf20Sopenharmony_ci itv->std++; /* Force full standard initialization */ 13548c2ecf20Sopenharmony_ci itv->std_out = itv->std; 13558c2ecf20Sopenharmony_ci ivtv_s_frequency(NULL, &fh, &vf); 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) { 13588c2ecf20Sopenharmony_ci /* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes 13598c2ecf20Sopenharmony_ci the mpeg decoder so now the saa7127 receives a proper 13608c2ecf20Sopenharmony_ci signal. */ 13618c2ecf20Sopenharmony_ci ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); 13628c2ecf20Sopenharmony_ci ivtv_init_mpeg_decoder(itv); 13638c2ecf20Sopenharmony_ci } 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci /* On a cx23416 this seems to be able to enable DMA to the chip? */ 13668c2ecf20Sopenharmony_ci if (!itv->has_cx23415) 13678c2ecf20Sopenharmony_ci write_reg_sync(0x03, IVTV_REG_DMACONTROL); 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci ivtv_s_std_enc(itv, itv->tuner_std); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci /* Default interrupts enabled. For the PVR350 this includes the 13728c2ecf20Sopenharmony_ci decoder VSYNC interrupt, which is always on. It is not only used 13738c2ecf20Sopenharmony_ci during decoding but also by the OSD. 13748c2ecf20Sopenharmony_ci Some old PVR250 cards had a cx23415, so testing for that is too 13758c2ecf20Sopenharmony_ci general. Instead test if the card has video output capability. */ 13768c2ecf20Sopenharmony_ci if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { 13778c2ecf20Sopenharmony_ci ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC); 13788c2ecf20Sopenharmony_ci ivtv_set_osd_alpha(itv); 13798c2ecf20Sopenharmony_ci ivtv_s_std_dec(itv, itv->tuner_std); 13808c2ecf20Sopenharmony_ci } else { 13818c2ecf20Sopenharmony_ci ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); 13828c2ecf20Sopenharmony_ci } 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci /* Setup initial controls */ 13858c2ecf20Sopenharmony_ci cx2341x_handler_setup(&itv->cxhdl); 13868c2ecf20Sopenharmony_ci return 0; 13878c2ecf20Sopenharmony_ci} 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_cistatic void ivtv_remove(struct pci_dev *pdev) 13908c2ecf20Sopenharmony_ci{ 13918c2ecf20Sopenharmony_ci struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); 13928c2ecf20Sopenharmony_ci struct ivtv *itv = to_ivtv(v4l2_dev); 13938c2ecf20Sopenharmony_ci int i; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("Removing card\n"); 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci flush_request_modules(itv); 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) { 14008c2ecf20Sopenharmony_ci /* Stop all captures */ 14018c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("Stopping all streams\n"); 14028c2ecf20Sopenharmony_ci if (atomic_read(&itv->capturing) > 0) 14038c2ecf20Sopenharmony_ci ivtv_stop_all_captures(itv); 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci /* Stop all decoding */ 14068c2ecf20Sopenharmony_ci IVTV_DEBUG_INFO("Stopping decoding\n"); 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci /* Turn off the TV-out */ 14098c2ecf20Sopenharmony_ci if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) 14108c2ecf20Sopenharmony_ci ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0); 14118c2ecf20Sopenharmony_ci if (atomic_read(&itv->decoding) > 0) { 14128c2ecf20Sopenharmony_ci int type; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) 14158c2ecf20Sopenharmony_ci type = IVTV_DEC_STREAM_TYPE_YUV; 14168c2ecf20Sopenharmony_ci else 14178c2ecf20Sopenharmony_ci type = IVTV_DEC_STREAM_TYPE_MPG; 14188c2ecf20Sopenharmony_ci ivtv_stop_v4l2_decode_stream(&itv->streams[type], 14198c2ecf20Sopenharmony_ci V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); 14208c2ecf20Sopenharmony_ci } 14218c2ecf20Sopenharmony_ci ivtv_halt_firmware(itv); 14228c2ecf20Sopenharmony_ci } 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ci /* Interrupts */ 14258c2ecf20Sopenharmony_ci ivtv_set_irq_mask(itv, 0xffffffff); 14268c2ecf20Sopenharmony_ci del_timer_sync(&itv->dma_timer); 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci /* Kill irq worker */ 14298c2ecf20Sopenharmony_ci kthread_flush_worker(&itv->irq_worker); 14308c2ecf20Sopenharmony_ci kthread_stop(itv->irq_worker_task); 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci ivtv_streams_cleanup(itv); 14338c2ecf20Sopenharmony_ci ivtv_udma_free(itv); 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(&itv->cxhdl.hdl); 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci exit_ivtv_i2c(itv); 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci free_irq(itv->pdev->irq, (void *)itv); 14408c2ecf20Sopenharmony_ci ivtv_iounmap(itv); 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); 14438c2ecf20Sopenharmony_ci release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); 14448c2ecf20Sopenharmony_ci if (itv->has_cx23415) 14458c2ecf20Sopenharmony_ci release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci pci_disable_device(itv->pdev); 14488c2ecf20Sopenharmony_ci for (i = 0; i < IVTV_VBI_FRAMES; i++) 14498c2ecf20Sopenharmony_ci kfree(itv->vbi.sliced_mpeg_data[i]); 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci pr_info("Removed %s\n", itv->card_name); 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci v4l2_device_unregister(&itv->v4l2_dev); 14548c2ecf20Sopenharmony_ci kfree(itv); 14558c2ecf20Sopenharmony_ci} 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci/* define a pci_driver for card detection */ 14588c2ecf20Sopenharmony_cistatic struct pci_driver ivtv_pci_driver = { 14598c2ecf20Sopenharmony_ci .name = "ivtv", 14608c2ecf20Sopenharmony_ci .id_table = ivtv_pci_tbl, 14618c2ecf20Sopenharmony_ci .probe = ivtv_probe, 14628c2ecf20Sopenharmony_ci .remove = ivtv_remove, 14638c2ecf20Sopenharmony_ci}; 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_cistatic int __init module_start(void) 14668c2ecf20Sopenharmony_ci{ 14678c2ecf20Sopenharmony_ci pr_info("Start initialization, version %s\n", IVTV_VERSION); 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci /* Validate parameters */ 14708c2ecf20Sopenharmony_ci if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) { 14718c2ecf20Sopenharmony_ci pr_err("Exiting, ivtv_first_minor must be between 0 and %d\n", 14728c2ecf20Sopenharmony_ci IVTV_MAX_CARDS - 1); 14738c2ecf20Sopenharmony_ci return -1; 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci if (ivtv_debug < 0 || ivtv_debug > 2047) { 14778c2ecf20Sopenharmony_ci ivtv_debug = 0; 14788c2ecf20Sopenharmony_ci pr_info("Debug value must be >= 0 and <= 2047\n"); 14798c2ecf20Sopenharmony_ci } 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci if (pci_register_driver(&ivtv_pci_driver)) { 14828c2ecf20Sopenharmony_ci pr_err("Error detecting PCI card\n"); 14838c2ecf20Sopenharmony_ci return -ENODEV; 14848c2ecf20Sopenharmony_ci } 14858c2ecf20Sopenharmony_ci pr_info("End initialization\n"); 14868c2ecf20Sopenharmony_ci return 0; 14878c2ecf20Sopenharmony_ci} 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_cistatic void __exit module_cleanup(void) 14908c2ecf20Sopenharmony_ci{ 14918c2ecf20Sopenharmony_ci pci_unregister_driver(&ivtv_pci_driver); 14928c2ecf20Sopenharmony_ci} 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci/* Note: These symbols are exported because they are used by the ivtvfb 14958c2ecf20Sopenharmony_ci framebuffer module and an infrared module for the IR-blaster. */ 14968c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_set_irq_mask); 14978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_api); 14988c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_vapi); 14998c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_vapi_result); 15008c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_clear_irq_mask); 15018c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_debug); 15028c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG 15038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_fw_debug); 15048c2ecf20Sopenharmony_ci#endif 15058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_reset_ir_gpio); 15068c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_udma_setup); 15078c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_udma_unmap); 15088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_udma_alloc); 15098c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_udma_prepare); 15108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_init_on_first_open); 15118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ivtv_firmware_check); 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_cimodule_init(module_start); 15148c2ecf20Sopenharmony_cimodule_exit(module_cleanup); 1515