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