blob: a053dece60ce1ee21e668b52238dc791e38c106a [file] [log] [blame]
Davide Ferri8d009a02009-06-23 22:34:06 -03001/*
2 * Driver for Xceive XC4000 "QAM/8VSB single chip tuner"
3 *
4 * Copyright (c) 2007 Xceive Corporation
5 * Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
6 * Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
7 * Copyright (c) 2009 Davide Ferri <d.ferri@zero11.it>
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03008 * Copyright (c) 2010 Istvan Varga <istvan_v@mailbox.hu>
Davide Ferri8d009a02009-06-23 22:34:06 -03009 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Davide Ferri8d009a02009-06-23 22:34:06 -030018 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/videodev2.h>
28#include <linux/delay.h>
29#include <linux/dvb/frontend.h>
30#include <linux/i2c.h>
Istvan Varga56149422011-06-03 12:23:33 -030031#include <linux/mutex.h>
Devin Heitmueller11091a32009-07-20 00:54:57 -030032#include <asm/unaligned.h>
Davide Ferri8d009a02009-06-23 22:34:06 -030033
34#include "dvb_frontend.h"
35
36#include "xc4000.h"
37#include "tuner-i2c.h"
Devin Heitmueller11091a32009-07-20 00:54:57 -030038#include "tuner-xc2028-types.h"
Davide Ferri8d009a02009-06-23 22:34:06 -030039
Devin Heitmueller4922cec2009-12-27 17:50:43 -030040static int debug;
Davide Ferri8d009a02009-06-23 22:34:06 -030041module_param(debug, int, 0644);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -030042MODULE_PARM_DESC(debug, "Debugging level (0 to 2, default: 0 (off)).");
Davide Ferri8d009a02009-06-23 22:34:06 -030043
44static int no_poweroff;
45module_param(no_poweroff, int, 0644);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -030046MODULE_PARM_DESC(no_poweroff, "Power management (1: disabled, 2: enabled, "
47 "0 (default): use device-specific default mode).");
Istvan Varga923137a2011-06-04 12:15:51 -030048
49static int audio_std;
50module_param(audio_std, int, 0644);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -030051MODULE_PARM_DESC(audio_std, "Audio standard. XC4000 audio decoder explicitly "
52 "needs to know what audio standard is needed for some video standards "
53 "with audio A2 or NICAM. The valid settings are a sum of:\n"
54 " 1: use NICAM/B or A2/B instead of NICAM/A or A2/A\n"
55 " 2: use A2 instead of NICAM or BTSC\n"
56 " 4: use SECAM/K3 instead of K1\n"
57 " 8: use PAL-D/K audio for SECAM-D/K\n"
58 "16: use FM radio input 1 instead of input 2\n"
59 "32: use mono audio (the lower three bits are ignored)");
Istvan Vargafa285bc2011-06-04 11:48:16 -030060
61static char firmware_name[30];
62module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -030063MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
64 "default firmware name.");
Istvan Vargafa285bc2011-06-04 11:48:16 -030065
Davide Ferri8d009a02009-06-23 22:34:06 -030066static DEFINE_MUTEX(xc4000_list_mutex);
67static LIST_HEAD(hybrid_tuner_instance_list);
68
69#define dprintk(level, fmt, arg...) if (debug >= level) \
70 printk(KERN_INFO "%s: " fmt, "xc4000", ## arg)
71
Devin Heitmueller11091a32009-07-20 00:54:57 -030072/* struct for storing firmware table */
73struct firmware_description {
74 unsigned int type;
75 v4l2_std_id id;
76 __u16 int_freq;
77 unsigned char *ptr;
78 unsigned int size;
79};
80
81struct firmware_properties {
82 unsigned int type;
83 v4l2_std_id id;
84 v4l2_std_id std_req;
85 __u16 int_freq;
86 unsigned int scode_table;
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -030087 int scode_nr;
Devin Heitmueller11091a32009-07-20 00:54:57 -030088};
Davide Ferri8d009a02009-06-23 22:34:06 -030089
90struct xc4000_priv {
91 struct tuner_i2c_props i2c_props;
92 struct list_head hybrid_tuner_instance_list;
Devin Heitmueller11091a32009-07-20 00:54:57 -030093 struct firmware_description *firm;
Istvan Vargafbe4a292011-06-03 10:11:48 -030094 int firm_size;
95 __u16 firm_version;
96 u32 if_khz;
97 u32 freq_hz;
98 u32 bandwidth;
99 u8 video_standard;
100 u8 rf_mode;
Istvan Varga0b402132011-06-03 09:38:04 -0300101 u8 card_type;
Istvan Vargafbe4a292011-06-03 10:11:48 -0300102 u8 ignore_i2c_write_errors;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300103 struct firmware_properties cur_fw;
Istvan Vargafbe4a292011-06-03 10:11:48 -0300104 __u16 hwmodel;
105 __u16 hwvers;
Istvan Varga56149422011-06-03 12:23:33 -0300106 struct mutex lock;
Davide Ferri8d009a02009-06-23 22:34:06 -0300107};
108
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300109#define XC4000_AUDIO_STD_B 1
110#define XC4000_AUDIO_STD_A2 2
111#define XC4000_AUDIO_STD_K3 4
112#define XC4000_AUDIO_STD_L 8
113#define XC4000_AUDIO_STD_INPUT1 16
114#define XC4000_AUDIO_STD_MONO 32
115
116#define XC4000_DEFAULT_FIRMWARE "dvb-fe-xc4000-1.4.fw"
117
Davide Ferri8d009a02009-06-23 22:34:06 -0300118/* Misc Defines */
Istvan Varga49110852011-06-03 10:55:24 -0300119#define MAX_TV_STANDARD 24
Davide Ferri8d009a02009-06-23 22:34:06 -0300120#define XC_MAX_I2C_WRITE_LENGTH 64
Istvan Varga5272f6b2011-06-04 12:03:03 -0300121#define XC_POWERED_DOWN 0x80000000U
Davide Ferri8d009a02009-06-23 22:34:06 -0300122
123/* Signal Types */
124#define XC_RF_MODE_AIR 0
125#define XC_RF_MODE_CABLE 1
126
Davide Ferri8d009a02009-06-23 22:34:06 -0300127/* Product id */
128#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
Istvan Varga7db98fe2011-06-04 12:25:19 -0300129#define XC_PRODUCT_ID_XC4000 0x0FA0
130#define XC_PRODUCT_ID_XC4100 0x1004
Davide Ferri8d009a02009-06-23 22:34:06 -0300131
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300132/* Registers (Write-only) */
Davide Ferri8d009a02009-06-23 22:34:06 -0300133#define XREG_INIT 0x00
134#define XREG_VIDEO_MODE 0x01
135#define XREG_AUDIO_MODE 0x02
136#define XREG_RF_FREQ 0x03
137#define XREG_D_CODE 0x04
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300138#define XREG_DIRECTSITTING_MODE 0x05
139#define XREG_SEEK_MODE 0x06
140#define XREG_POWER_DOWN 0x08
141#define XREG_SIGNALSOURCE 0x0A
Istvan Varga30f544e2011-06-04 12:12:42 -0300142#define XREG_SMOOTHEDCVBS 0x0E
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300143#define XREG_AMPLITUDE 0x10
Davide Ferri8d009a02009-06-23 22:34:06 -0300144
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300145/* Registers (Read-only) */
Davide Ferri8d009a02009-06-23 22:34:06 -0300146#define XREG_ADC_ENV 0x00
147#define XREG_QUALITY 0x01
148#define XREG_FRAME_LINES 0x02
149#define XREG_HSYNC_FREQ 0x03
150#define XREG_LOCK 0x04
151#define XREG_FREQ_ERROR 0x05
152#define XREG_SNR 0x06
153#define XREG_VERSION 0x07
154#define XREG_PRODUCT_ID 0x08
Davide Ferri8d009a02009-06-23 22:34:06 -0300155
156/*
157 Basic firmware description. This will remain with
158 the driver for documentation purposes.
159
160 This represents an I2C firmware file encoded as a
161 string of unsigned char. Format is as follows:
162
163 char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB
164 char[1 ]=len0_LSB -> length of first write transaction
165 char[2 ]=data0 -> first byte to be sent
166 char[3 ]=data1
167 char[4 ]=data2
168 char[ ]=...
169 char[M ]=dataN -> last byte to be sent
170 char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB
171 char[M+2]=len1_LSB -> length of second write transaction
172 char[M+3]=data0
173 char[M+4]=data1
174 ...
175 etc.
176
177 The [len] value should be interpreted as follows:
178
179 len= len_MSB _ len_LSB
180 len=1111_1111_1111_1111 : End of I2C_SEQUENCE
181 len=0000_0000_0000_0000 : Reset command: Do hardware reset
182 len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767)
183 len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms
184
185 For the RESET and WAIT commands, the two following bytes will contain
186 immediately the length of the following transaction.
Davide Ferri8d009a02009-06-23 22:34:06 -0300187*/
Istvan Vargafbe4a292011-06-03 10:11:48 -0300188
Davide Ferri8d009a02009-06-23 22:34:06 -0300189struct XC_TV_STANDARD {
Istvan Vargafbe4a292011-06-03 10:11:48 -0300190 const char *Name;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300191 u16 audio_mode;
192 u16 video_mode;
Istvan Varga49110852011-06-03 10:55:24 -0300193 u16 int_freq;
Davide Ferri8d009a02009-06-23 22:34:06 -0300194};
195
196/* Tuner standards */
Devin Heitmuellered23db32009-10-05 01:27:14 -0300197#define XC4000_MN_NTSC_PAL_BTSC 0
198#define XC4000_MN_NTSC_PAL_A2 1
199#define XC4000_MN_NTSC_PAL_EIAJ 2
200#define XC4000_MN_NTSC_PAL_Mono 3
201#define XC4000_BG_PAL_A2 4
202#define XC4000_BG_PAL_NICAM 5
203#define XC4000_BG_PAL_MONO 6
204#define XC4000_I_PAL_NICAM 7
205#define XC4000_I_PAL_NICAM_MONO 8
206#define XC4000_DK_PAL_A2 9
207#define XC4000_DK_PAL_NICAM 10
208#define XC4000_DK_PAL_MONO 11
209#define XC4000_DK_SECAM_A2DK1 12
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300210#define XC4000_DK_SECAM_A2LDK3 13
211#define XC4000_DK_SECAM_A2MONO 14
Istvan Varga49110852011-06-03 10:55:24 -0300212#define XC4000_DK_SECAM_NICAM 15
213#define XC4000_L_SECAM_NICAM 16
214#define XC4000_LC_SECAM_NICAM 17
215#define XC4000_DTV6 18
216#define XC4000_DTV8 19
217#define XC4000_DTV7_8 20
218#define XC4000_DTV7 21
219#define XC4000_FM_Radio_INPUT2 22
220#define XC4000_FM_Radio_INPUT1 23
Davide Ferri8d009a02009-06-23 22:34:06 -0300221
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300222static struct XC_TV_STANDARD xc4000_standard[MAX_TV_STANDARD] = {
Istvan Varga49110852011-06-03 10:55:24 -0300223 {"M/N-NTSC/PAL-BTSC", 0x0000, 0x80A0, 4500},
224 {"M/N-NTSC/PAL-A2", 0x0000, 0x80A0, 4600},
225 {"M/N-NTSC/PAL-EIAJ", 0x0040, 0x80A0, 4500},
226 {"M/N-NTSC/PAL-Mono", 0x0078, 0x80A0, 4500},
227 {"B/G-PAL-A2", 0x0000, 0x8159, 5640},
228 {"B/G-PAL-NICAM", 0x0004, 0x8159, 5740},
229 {"B/G-PAL-MONO", 0x0078, 0x8159, 5500},
230 {"I-PAL-NICAM", 0x0080, 0x8049, 6240},
231 {"I-PAL-NICAM-MONO", 0x0078, 0x8049, 6000},
232 {"D/K-PAL-A2", 0x0000, 0x8049, 6380},
233 {"D/K-PAL-NICAM", 0x0080, 0x8049, 6200},
234 {"D/K-PAL-MONO", 0x0078, 0x8049, 6500},
235 {"D/K-SECAM-A2 DK1", 0x0000, 0x8049, 6340},
236 {"D/K-SECAM-A2 L/DK3", 0x0000, 0x8049, 6000},
237 {"D/K-SECAM-A2 MONO", 0x0078, 0x8049, 6500},
238 {"D/K-SECAM-NICAM", 0x0080, 0x8049, 6200},
239 {"L-SECAM-NICAM", 0x8080, 0x0009, 6200},
240 {"L'-SECAM-NICAM", 0x8080, 0x4009, 6200},
241 {"DTV6", 0x00C0, 0x8002, 0},
242 {"DTV8", 0x00C0, 0x800B, 0},
243 {"DTV7/8", 0x00C0, 0x801B, 0},
244 {"DTV7", 0x00C0, 0x8007, 0},
245 {"FM Radio-INPUT2", 0x0008, 0x9800,10700},
246 {"FM Radio-INPUT1", 0x0008, 0x9000,10700}
Davide Ferri8d009a02009-06-23 22:34:06 -0300247};
248
Davide Ferri8d009a02009-06-23 22:34:06 -0300249static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300250static int xc4000_tuner_reset(struct dvb_frontend *fe);
Istvan Vargaf4312e2f2011-06-04 12:08:29 -0300251static void xc_debug_dump(struct xc4000_priv *priv);
Davide Ferri8d009a02009-06-23 22:34:06 -0300252
253static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
254{
255 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
256 .flags = 0, .buf = buf, .len = len };
Davide Ferri8d009a02009-06-23 22:34:06 -0300257 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
Devin Heitmueller799ed112009-10-04 23:09:18 -0300258 if (priv->ignore_i2c_write_errors == 0) {
259 printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n",
260 len);
261 if (len == 4) {
262 printk("bytes %02x %02x %02x %02x\n", buf[0],
263 buf[1], buf[2], buf[3]);
264 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300265 return -EREMOTEIO;
Devin Heitmueller799ed112009-10-04 23:09:18 -0300266 }
Davide Ferri8d009a02009-06-23 22:34:06 -0300267 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300268 return 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300269}
270
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300271static int xc4000_tuner_reset(struct dvb_frontend *fe)
Davide Ferri8d009a02009-06-23 22:34:06 -0300272{
273 struct xc4000_priv *priv = fe->tuner_priv;
274 int ret;
275
276 dprintk(1, "%s()\n", __func__);
277
278 if (fe->callback) {
279 ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
280 fe->dvb->priv :
281 priv->i2c_props.adap->algo_data,
282 DVB_FRONTEND_COMPONENT_TUNER,
283 XC4000_TUNER_RESET, 0);
284 if (ret) {
285 printk(KERN_ERR "xc4000: reset failed\n");
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300286 return -EREMOTEIO;
Davide Ferri8d009a02009-06-23 22:34:06 -0300287 }
288 } else {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300289 printk(KERN_ERR "xc4000: no tuner reset callback function, "
290 "fatal\n");
291 return -EINVAL;
Davide Ferri8d009a02009-06-23 22:34:06 -0300292 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300293 return 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300294}
295
296static int xc_write_reg(struct xc4000_priv *priv, u16 regAddr, u16 i2cData)
297{
298 u8 buf[4];
Davide Ferri8d009a02009-06-23 22:34:06 -0300299 int result;
300
301 buf[0] = (regAddr >> 8) & 0xFF;
302 buf[1] = regAddr & 0xFF;
303 buf[2] = (i2cData >> 8) & 0xFF;
304 buf[3] = i2cData & 0xFF;
305 result = xc_send_i2c_data(priv, buf, 4);
Davide Ferri8d009a02009-06-23 22:34:06 -0300306
307 return result;
308}
309
310static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
311{
312 struct xc4000_priv *priv = fe->tuner_priv;
313
314 int i, nbytes_to_send, result;
315 unsigned int len, pos, index;
316 u8 buf[XC_MAX_I2C_WRITE_LENGTH];
317
318 index = 0;
319 while ((i2c_sequence[index] != 0xFF) ||
320 (i2c_sequence[index + 1] != 0xFF)) {
321 len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
322 if (len == 0x0000) {
323 /* RESET command */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300324 /* NOTE: this is ignored, as the reset callback was */
325 /* already called by check_firmware() */
Davide Ferri8d009a02009-06-23 22:34:06 -0300326 index += 2;
Davide Ferri8d009a02009-06-23 22:34:06 -0300327 } else if (len & 0x8000) {
328 /* WAIT command */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300329 msleep(len & 0x7FFF);
Davide Ferri8d009a02009-06-23 22:34:06 -0300330 index += 2;
331 } else {
332 /* Send i2c data whilst ensuring individual transactions
333 * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
334 */
335 index += 2;
336 buf[0] = i2c_sequence[index];
337 buf[1] = i2c_sequence[index + 1];
338 pos = 2;
339 while (pos < len) {
340 if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
341 nbytes_to_send =
342 XC_MAX_I2C_WRITE_LENGTH;
343 else
344 nbytes_to_send = (len - pos + 2);
345 for (i = 2; i < nbytes_to_send; i++) {
346 buf[i] = i2c_sequence[index + pos +
347 i - 2];
348 }
349 result = xc_send_i2c_data(priv, buf,
350 nbytes_to_send);
351
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300352 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300353 return result;
354
355 pos += nbytes_to_send - 2;
356 }
357 index += len;
358 }
359 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300360 return 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300361}
362
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300363static int xc_set_tv_standard(struct xc4000_priv *priv,
364 u16 video_mode, u16 audio_mode)
Davide Ferri8d009a02009-06-23 22:34:06 -0300365{
366 int ret;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300367 dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, video_mode, audio_mode);
Davide Ferri8d009a02009-06-23 22:34:06 -0300368 dprintk(1, "%s() Standard = %s\n",
369 __func__,
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300370 xc4000_standard[priv->video_standard].Name);
Davide Ferri8d009a02009-06-23 22:34:06 -0300371
Devin Heitmueller799ed112009-10-04 23:09:18 -0300372 /* Don't complain when the request fails because of i2c stretching */
373 priv->ignore_i2c_write_errors = 1;
374
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300375 ret = xc_write_reg(priv, XREG_VIDEO_MODE, video_mode);
376 if (ret == 0)
377 ret = xc_write_reg(priv, XREG_AUDIO_MODE, audio_mode);
Davide Ferri8d009a02009-06-23 22:34:06 -0300378
Devin Heitmueller799ed112009-10-04 23:09:18 -0300379 priv->ignore_i2c_write_errors = 0;
380
Davide Ferri8d009a02009-06-23 22:34:06 -0300381 return ret;
382}
383
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300384static int xc_set_signal_source(struct xc4000_priv *priv, u16 rf_mode)
Davide Ferri8d009a02009-06-23 22:34:06 -0300385{
386 dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
387 rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
388
389 if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
390 rf_mode = XC_RF_MODE_CABLE;
391 printk(KERN_ERR
392 "%s(), Invalid mode, defaulting to CABLE",
393 __func__);
394 }
395 return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
396}
397
398static const struct dvb_tuner_ops xc4000_tuner_ops;
399
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300400static int xc_set_rf_frequency(struct xc4000_priv *priv, u32 freq_hz)
Davide Ferri8d009a02009-06-23 22:34:06 -0300401{
402 u16 freq_code;
403
404 dprintk(1, "%s(%u)\n", __func__, freq_hz);
405
406 if ((freq_hz > xc4000_tuner_ops.info.frequency_max) ||
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300407 (freq_hz < xc4000_tuner_ops.info.frequency_min))
408 return -EINVAL;
Davide Ferri8d009a02009-06-23 22:34:06 -0300409
410 freq_code = (u16)(freq_hz / 15625);
411
412 /* WAS: Starting in firmware version 1.1.44, Xceive recommends using the
413 FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
414 only be used for fast scanning for channel lock) */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300415 /* WAS: XREG_FINERFREQ */
416 return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
Davide Ferri8d009a02009-06-23 22:34:06 -0300417}
418
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300419static int xc_get_adc_envelope(struct xc4000_priv *priv, u16 *adc_envelope)
Davide Ferri8d009a02009-06-23 22:34:06 -0300420{
421 return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope);
422}
423
424static int xc_get_frequency_error(struct xc4000_priv *priv, u32 *freq_error_hz)
425{
426 int result;
427 u16 regData;
428 u32 tmp;
429
430 result = xc4000_readreg(priv, XREG_FREQ_ERROR, &regData);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300431 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300432 return result;
433
Istvan Varga1368ceb2011-06-03 12:27:30 -0300434 tmp = (u32)regData & 0xFFFFU;
435 tmp = (tmp < 0x8000U ? tmp : 0x10000U - tmp);
436 (*freq_error_hz) = tmp * 15625;
Davide Ferri8d009a02009-06-23 22:34:06 -0300437 return result;
438}
439
440static int xc_get_lock_status(struct xc4000_priv *priv, u16 *lock_status)
441{
442 return xc4000_readreg(priv, XREG_LOCK, lock_status);
443}
444
445static int xc_get_version(struct xc4000_priv *priv,
446 u8 *hw_majorversion, u8 *hw_minorversion,
447 u8 *fw_majorversion, u8 *fw_minorversion)
448{
449 u16 data;
450 int result;
451
452 result = xc4000_readreg(priv, XREG_VERSION, &data);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300453 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300454 return result;
455
456 (*hw_majorversion) = (data >> 12) & 0x0F;
457 (*hw_minorversion) = (data >> 8) & 0x0F;
458 (*fw_majorversion) = (data >> 4) & 0x0F;
459 (*fw_minorversion) = data & 0x0F;
460
461 return 0;
462}
463
Davide Ferri8d009a02009-06-23 22:34:06 -0300464static int xc_get_hsync_freq(struct xc4000_priv *priv, u32 *hsync_freq_hz)
465{
466 u16 regData;
467 int result;
468
469 result = xc4000_readreg(priv, XREG_HSYNC_FREQ, &regData);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300470 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300471 return result;
472
473 (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
474 return result;
475}
476
477static int xc_get_frame_lines(struct xc4000_priv *priv, u16 *frame_lines)
478{
479 return xc4000_readreg(priv, XREG_FRAME_LINES, frame_lines);
480}
481
482static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
483{
484 return xc4000_readreg(priv, XREG_QUALITY, quality);
485}
486
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300487static u16 xc_wait_for_lock(struct xc4000_priv *priv)
Davide Ferri8d009a02009-06-23 22:34:06 -0300488{
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300489 u16 lock_state = 0;
490 int watchdog_count = 40;
Davide Ferri8d009a02009-06-23 22:34:06 -0300491
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300492 while ((lock_state == 0) && (watchdog_count > 0)) {
493 xc_get_lock_status(priv, &lock_state);
494 if (lock_state != 1) {
495 msleep(5);
496 watchdog_count--;
Davide Ferri8d009a02009-06-23 22:34:06 -0300497 }
498 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300499 return lock_state;
Davide Ferri8d009a02009-06-23 22:34:06 -0300500}
501
Istvan Vargae75873c2011-06-04 12:18:41 -0300502static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz)
Davide Ferri8d009a02009-06-23 22:34:06 -0300503{
Istvan Vargae75873c2011-06-04 12:18:41 -0300504 int found = 1;
505 int result;
Davide Ferri8d009a02009-06-23 22:34:06 -0300506
507 dprintk(1, "%s(%u)\n", __func__, freq_hz);
508
Devin Heitmueller799ed112009-10-04 23:09:18 -0300509 /* Don't complain when the request fails because of i2c stretching */
510 priv->ignore_i2c_write_errors = 1;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300511 result = xc_set_rf_frequency(priv, freq_hz);
Devin Heitmueller799ed112009-10-04 23:09:18 -0300512 priv->ignore_i2c_write_errors = 0;
513
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300514 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300515 return 0;
516
Istvan Vargae75873c2011-06-04 12:18:41 -0300517 /* wait for lock only in analog TV mode */
518 if ((priv->cur_fw.type & (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300519 if (xc_wait_for_lock(priv) != 1)
Istvan Vargae75873c2011-06-04 12:18:41 -0300520 found = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300521 }
522
Istvan Vargaf4312e2f2011-06-04 12:08:29 -0300523 /* Wait for stats to stabilize.
524 * Frame Lines needs two frame times after initial lock
525 * before it is valid.
526 */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300527 msleep(debug ? 100 : 10);
Istvan Vargaf4312e2f2011-06-04 12:08:29 -0300528
529 if (debug)
530 xc_debug_dump(priv);
531
Davide Ferri8d009a02009-06-23 22:34:06 -0300532 return found;
533}
534
535static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val)
536{
537 u8 buf[2] = { reg >> 8, reg & 0xff };
538 u8 bval[2] = { 0, 0 };
539 struct i2c_msg msg[2] = {
540 { .addr = priv->i2c_props.addr,
541 .flags = 0, .buf = &buf[0], .len = 2 },
542 { .addr = priv->i2c_props.addr,
543 .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
544 };
545
546 if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
547 printk(KERN_WARNING "xc4000: I2C read failed\n");
548 return -EREMOTEIO;
549 }
550
551 *val = (bval[0] << 8) | bval[1];
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300552 return 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300553}
554
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300555#define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0)
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300556static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
557{
558 if (type & BASE)
559 printk("BASE ");
560 if (type & INIT1)
561 printk("INIT1 ");
562 if (type & F8MHZ)
563 printk("F8MHZ ");
564 if (type & MTS)
565 printk("MTS ");
566 if (type & D2620)
567 printk("D2620 ");
568 if (type & D2633)
569 printk("D2633 ");
570 if (type & DTV6)
571 printk("DTV6 ");
572 if (type & QAM)
573 printk("QAM ");
574 if (type & DTV7)
575 printk("DTV7 ");
576 if (type & DTV78)
577 printk("DTV78 ");
578 if (type & DTV8)
579 printk("DTV8 ");
580 if (type & FM)
581 printk("FM ");
582 if (type & INPUT1)
583 printk("INPUT1 ");
584 if (type & LCD)
585 printk("LCD ");
586 if (type & NOGD)
587 printk("NOGD ");
588 if (type & MONO)
589 printk("MONO ");
590 if (type & ATSC)
591 printk("ATSC ");
592 if (type & IF)
593 printk("IF ");
594 if (type & LG60)
595 printk("LG60 ");
596 if (type & ATI638)
597 printk("ATI638 ");
598 if (type & OREN538)
599 printk("OREN538 ");
600 if (type & OREN36)
601 printk("OREN36 ");
602 if (type & TOYOTA388)
603 printk("TOYOTA388 ");
604 if (type & TOYOTA794)
605 printk("TOYOTA794 ");
606 if (type & DIBCOM52)
607 printk("DIBCOM52 ");
608 if (type & ZARLINK456)
609 printk("ZARLINK456 ");
610 if (type & CHINA)
611 printk("CHINA ");
612 if (type & F6MHZ)
613 printk("F6MHZ ");
614 if (type & INPUT2)
615 printk("INPUT2 ");
616 if (type & SCODE)
617 printk("SCODE ");
618 if (type & HAS_IF)
619 printk("HAS_IF_%d ", int_freq);
620}
621
Devin Heitmueller11091a32009-07-20 00:54:57 -0300622static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
623 v4l2_std_id *id)
624{
625 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Varga3db95702011-06-04 11:52:34 -0300626 int i, best_i = -1;
627 unsigned int best_nr_diffs = 255U;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300628
Devin Heitmueller11091a32009-07-20 00:54:57 -0300629 if (!priv->firm) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300630 printk(KERN_ERR "Error! firmware not loaded\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300631 return -EINVAL;
632 }
633
634 if (((type & ~SCODE) == 0) && (*id == 0))
635 *id = V4L2_STD_PAL;
636
Devin Heitmueller11091a32009-07-20 00:54:57 -0300637 /* Seek for generic video standard match */
638 for (i = 0; i < priv->firm_size; i++) {
Istvan Varga3db95702011-06-04 11:52:34 -0300639 v4l2_std_id id_diff_mask =
640 (priv->firm[i].id ^ (*id)) & (*id);
641 unsigned int type_diff_mask =
642 (priv->firm[i].type ^ type)
643 & (BASE_TYPES | DTV_TYPES | LCD | NOGD | MONO | SCODE);
644 unsigned int nr_diffs;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300645
Istvan Varga3db95702011-06-04 11:52:34 -0300646 if (type_diff_mask
647 & (BASE | INIT1 | FM | DTV6 | DTV7 | DTV78 | DTV8 | SCODE))
Devin Heitmueller11091a32009-07-20 00:54:57 -0300648 continue;
649
Istvan Varga3db95702011-06-04 11:52:34 -0300650 nr_diffs = hweight64(id_diff_mask) + hweight32(type_diff_mask);
651 if (!nr_diffs) /* Supports all the requested standards */
652 goto found;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300653
Istvan Varga3db95702011-06-04 11:52:34 -0300654 if (nr_diffs < best_nr_diffs) {
655 best_nr_diffs = nr_diffs;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300656 best_i = i;
657 }
658 }
659
Istvan Varga3db95702011-06-04 11:52:34 -0300660 /* FIXME: Would make sense to seek for type "hint" match ? */
661 if (best_i < 0) {
662 i = -ENOENT;
663 goto ret;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300664 }
665
Istvan Varga3db95702011-06-04 11:52:34 -0300666 if (best_nr_diffs > 0U) {
667 printk("Selecting best matching firmware (%u bits differ) for "
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300668 "type=(%x), id %016llx:\n",
669 best_nr_diffs, type, (unsigned long long)*id);
Istvan Varga3db95702011-06-04 11:52:34 -0300670 i = best_i;
671 }
Devin Heitmueller11091a32009-07-20 00:54:57 -0300672
673found:
674 *id = priv->firm[i].id;
675
676ret:
Devin Heitmueller11091a32009-07-20 00:54:57 -0300677 if (debug) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300678 printk("%s firmware for type=",
679 (i < 0) ? "Can't find" : "Found");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300680 dump_firm_type(type);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300681 printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
682 }
683 return i;
684}
685
686static int load_firmware(struct dvb_frontend *fe, unsigned int type,
687 v4l2_std_id *id)
688{
689 struct xc4000_priv *priv = fe->tuner_priv;
690 int pos, rc;
Devin Heitmueller31f880e2009-07-20 02:15:31 -0300691 unsigned char *p;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300692
Devin Heitmueller11091a32009-07-20 00:54:57 -0300693 pos = seek_firmware(fe, type, id);
694 if (pos < 0)
695 return pos;
696
Devin Heitmueller11091a32009-07-20 00:54:57 -0300697 p = priv->firm[pos].ptr;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300698
Devin Heitmueller799ed112009-10-04 23:09:18 -0300699 /* Don't complain when the request fails because of i2c stretching */
700 priv->ignore_i2c_write_errors = 1;
701
Devin Heitmueller31f880e2009-07-20 02:15:31 -0300702 rc = xc_load_i2c_sequence(fe, p);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300703
Devin Heitmueller799ed112009-10-04 23:09:18 -0300704 priv->ignore_i2c_write_errors = 0;
705
Devin Heitmueller31f880e2009-07-20 02:15:31 -0300706 return rc;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300707}
708
Davide Ferri8d009a02009-06-23 22:34:06 -0300709static int xc4000_fwupload(struct dvb_frontend *fe)
710{
711 struct xc4000_priv *priv = fe->tuner_priv;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300712 const struct firmware *fw = NULL;
713 const unsigned char *p, *endp;
714 int rc = 0;
715 int n, n_array;
716 char name[33];
Istvan Vargafbe4a292011-06-03 10:11:48 -0300717 const char *fname;
Davide Ferri8d009a02009-06-23 22:34:06 -0300718
Istvan Vargafa285bc2011-06-04 11:48:16 -0300719 if (firmware_name[0] != '\0')
720 fname = firmware_name;
721 else
722 fname = XC4000_DEFAULT_FIRMWARE;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300723
724 printk("Reading firmware %s\n", fname);
725 rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
726 if (rc < 0) {
727 if (rc == -ENOENT)
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300728 printk("Error: firmware %s not found.\n", fname);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300729 else
730 printk("Error %d while requesting firmware %s \n",
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300731 rc, fname);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300732
733 return rc;
734 }
735 p = fw->data;
736 endp = p + fw->size;
737
738 if (fw->size < sizeof(name) - 1 + 2 + 2) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300739 printk("Error: firmware file %s has invalid size!\n", fname);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300740 goto corrupt;
Davide Ferri8d009a02009-06-23 22:34:06 -0300741 }
742
Devin Heitmueller11091a32009-07-20 00:54:57 -0300743 memcpy(name, p, sizeof(name) - 1);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300744 name[sizeof(name) - 1] = '\0';
Devin Heitmueller11091a32009-07-20 00:54:57 -0300745 p += sizeof(name) - 1;
746
747 priv->firm_version = get_unaligned_le16(p);
748 p += 2;
749
750 n_array = get_unaligned_le16(p);
751 p += 2;
752
Devin Heitmuellerb6cdb5b2009-12-27 18:15:14 -0300753 dprintk(1, "Loading %d firmware images from %s, type: %s, ver %d.%d\n",
754 n_array, fname, name,
755 priv->firm_version >> 8, priv->firm_version & 0xff);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300756
757 priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
758 if (priv->firm == NULL) {
759 printk("Not enough memory to load firmware file.\n");
760 rc = -ENOMEM;
761 goto err;
762 }
763 priv->firm_size = n_array;
764
765 n = -1;
766 while (p < endp) {
767 __u32 type, size;
768 v4l2_std_id id;
769 __u16 int_freq = 0;
770
771 n++;
772 if (n >= n_array) {
773 printk("More firmware images in file than "
Istvan Vargafbe4a292011-06-03 10:11:48 -0300774 "were expected!\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300775 goto corrupt;
776 }
777
778 /* Checks if there's enough bytes to read */
779 if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
780 goto header;
781
782 type = get_unaligned_le32(p);
783 p += sizeof(type);
784
785 id = get_unaligned_le64(p);
786 p += sizeof(id);
787
788 if (type & HAS_IF) {
789 int_freq = get_unaligned_le16(p);
790 p += sizeof(int_freq);
791 if (endp - p < sizeof(size))
792 goto header;
793 }
794
795 size = get_unaligned_le32(p);
796 p += sizeof(size);
797
798 if (!size || size > endp - p) {
Istvan Vargaffce6262011-06-04 11:56:18 -0300799 printk("Firmware type (%x), id %llx is corrupted "
Devin Heitmueller11091a32009-07-20 00:54:57 -0300800 "(size=%d, expected %d)\n",
801 type, (unsigned long long)id,
802 (unsigned)(endp - p), size);
803 goto corrupt;
804 }
805
806 priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
807 if (priv->firm[n].ptr == NULL) {
808 printk("Not enough memory to load firmware file.\n");
809 rc = -ENOMEM;
810 goto err;
811 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300812
Devin Heitmueller11091a32009-07-20 00:54:57 -0300813 if (debug) {
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300814 printk("Reading firmware type ");
815 dump_firm_type_and_int_freq(type, int_freq);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300816 printk("(%x), id %llx, size=%d.\n",
817 type, (unsigned long long)id, size);
818 }
819
820 memcpy(priv->firm[n].ptr, p, size);
821 priv->firm[n].type = type;
822 priv->firm[n].id = id;
823 priv->firm[n].size = size;
824 priv->firm[n].int_freq = int_freq;
825
826 p += size;
Davide Ferri8d009a02009-06-23 22:34:06 -0300827 }
828
Devin Heitmueller11091a32009-07-20 00:54:57 -0300829 if (n + 1 != priv->firm_size) {
830 printk("Firmware file is incomplete!\n");
831 goto corrupt;
832 }
833
834 goto done;
835
836header:
837 printk("Firmware header is incomplete!\n");
838corrupt:
839 rc = -EINVAL;
840 printk("Error: firmware file is corrupted!\n");
841
842err:
843 printk("Releasing partially loaded firmware file.\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300844
845done:
Davide Ferri8d009a02009-06-23 22:34:06 -0300846 release_firmware(fw);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300847 if (rc == 0)
Devin Heitmuellerb6cdb5b2009-12-27 18:15:14 -0300848 dprintk(1, "Firmware files loaded.\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300849
850 return rc;
Davide Ferri8d009a02009-06-23 22:34:06 -0300851}
852
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300853static int load_scode(struct dvb_frontend *fe, unsigned int type,
854 v4l2_std_id *id, __u16 int_freq, int scode)
855{
856 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Vargaffce6262011-06-04 11:56:18 -0300857 int pos, rc;
858 unsigned char *p;
859 u8 scode_buf[13];
860 u8 indirect_mode[5];
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300861
Devin Heitmuellerfe830362009-07-28 00:04:27 -0300862 dprintk(1, "%s called int_freq=%d\n", __func__, int_freq);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300863
864 if (!int_freq) {
865 pos = seek_firmware(fe, type, id);
866 if (pos < 0)
867 return pos;
868 } else {
869 for (pos = 0; pos < priv->firm_size; pos++) {
870 if ((priv->firm[pos].int_freq == int_freq) &&
871 (priv->firm[pos].type & HAS_IF))
872 break;
873 }
874 if (pos == priv->firm_size)
875 return -ENOENT;
876 }
877
878 p = priv->firm[pos].ptr;
879
Istvan Vargaffce6262011-06-04 11:56:18 -0300880 if (priv->firm[pos].size != 12 * 16 || scode >= 16)
881 return -EINVAL;
882 p += 12 * scode;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300883
884 tuner_info("Loading SCODE for type=");
885 dump_firm_type_and_int_freq(priv->firm[pos].type,
886 priv->firm[pos].int_freq);
887 printk("(%x), id %016llx.\n", priv->firm[pos].type,
888 (unsigned long long)*id);
889
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300890 scode_buf[0] = 0x00;
891 memcpy(&scode_buf[1], p, 12);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300892
893 /* Enter direct-mode */
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300894 rc = xc_write_reg(priv, XREG_DIRECTSITTING_MODE, 0);
895 if (rc < 0) {
896 printk("failed to put device into direct mode!\n");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300897 return -EIO;
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300898 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300899
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300900 rc = xc_send_i2c_data(priv, scode_buf, 13);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300901 if (rc != 0) {
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300902 /* Even if the send failed, make sure we set back to indirect
903 mode */
904 printk("Failed to set scode %d\n", rc);
905 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300906
907 /* Switch back to indirect-mode */
908 memset(indirect_mode, 0, sizeof(indirect_mode));
909 indirect_mode[4] = 0x88;
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300910 xc_send_i2c_data(priv, indirect_mode, sizeof(indirect_mode));
911 msleep(10);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300912
913 return 0;
914}
915
916static int check_firmware(struct dvb_frontend *fe, unsigned int type,
917 v4l2_std_id std, __u16 int_freq)
918{
919 struct xc4000_priv *priv = fe->tuner_priv;
920 struct firmware_properties new_fw;
921 int rc = 0, is_retry = 0;
istvan_v@mailbox.hu09f46342011-06-06 13:00:17 -0300922 u16 hwmodel;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300923 v4l2_std_id std0;
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300924 u8 hw_major, hw_minor, fw_major, fw_minor;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300925
926 dprintk(1, "%s called\n", __func__);
927
928 if (!priv->firm) {
929 rc = xc4000_fwupload(fe);
930 if (rc < 0)
931 return rc;
932 }
933
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300934retry:
935 new_fw.type = type;
936 new_fw.id = std;
937 new_fw.std_req = std;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300938 new_fw.scode_table = SCODE;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300939 new_fw.scode_nr = 0;
940 new_fw.int_freq = int_freq;
941
942 dprintk(1, "checking firmware, user requested type=");
943 if (debug) {
944 dump_firm_type(new_fw.type);
945 printk("(%x), id %016llx, ", new_fw.type,
946 (unsigned long long)new_fw.std_req);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300947 if (!int_freq)
948 printk(KERN_CONT "scode_tbl ");
949 else
950 printk(KERN_CONT "int_freq %d, ", new_fw.int_freq);
951 printk(KERN_CONT "scode_nr %d\n", new_fw.scode_nr);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300952 }
953
954 /* No need to reload base firmware if it matches */
Istvan Varga595a83f2011-06-04 11:59:54 -0300955 if (priv->cur_fw.type & BASE) {
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300956 dprintk(1, "BASE firmware not changed.\n");
957 goto skip_base;
958 }
959
960 /* Updating BASE - forget about all currently loaded firmware */
961 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
962
963 /* Reset is needed before loading firmware */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300964 rc = xc4000_tuner_reset(fe);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300965 if (rc < 0)
966 goto fail;
967
968 /* BASE firmwares are all std0 */
969 std0 = 0;
Istvan Varga595a83f2011-06-04 11:59:54 -0300970 rc = load_firmware(fe, BASE, &std0);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300971 if (rc < 0) {
972 printk("Error %d while loading base firmware\n", rc);
973 goto fail;
974 }
975
976 /* Load INIT1, if needed */
977 dprintk(1, "Load init1 firmware, if exists\n");
978
Istvan Varga595a83f2011-06-04 11:59:54 -0300979 rc = load_firmware(fe, BASE | INIT1, &std0);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300980 if (rc == -ENOENT)
Istvan Varga595a83f2011-06-04 11:59:54 -0300981 rc = load_firmware(fe, BASE | INIT1, &std0);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300982 if (rc < 0 && rc != -ENOENT) {
983 tuner_err("Error %d while loading init1 firmware\n",
984 rc);
985 goto fail;
986 }
987
988skip_base:
989 /*
990 * No need to reload standard specific firmware if base firmware
991 * was not reloaded and requested video standards have not changed.
992 */
993 if (priv->cur_fw.type == (BASE | new_fw.type) &&
994 priv->cur_fw.std_req == std) {
995 dprintk(1, "Std-specific firmware already loaded.\n");
996 goto skip_std_specific;
997 }
998
999 /* Reloading std-specific firmware forces a SCODE update */
1000 priv->cur_fw.scode_table = 0;
1001
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -03001002 /* Load the standard firmware */
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001003 rc = load_firmware(fe, new_fw.type, &new_fw.id);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001004
1005 if (rc < 0)
1006 goto fail;
1007
1008skip_std_specific:
1009 if (priv->cur_fw.scode_table == new_fw.scode_table &&
1010 priv->cur_fw.scode_nr == new_fw.scode_nr) {
1011 dprintk(1, "SCODE firmware already loaded.\n");
1012 goto check_device;
1013 }
1014
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001015 /* Load SCODE firmware, if exists */
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001016 rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
1017 new_fw.int_freq, new_fw.scode_nr);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001018 if (rc != 0)
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -03001019 dprintk(1, "load scode failed %d\n", rc);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001020
1021check_device:
1022 rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel);
1023
Devin Heitmueller799ed112009-10-04 23:09:18 -03001024 if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major,
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001025 &fw_minor) != 0) {
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001026 printk("Unable to read tuner registers.\n");
1027 goto fail;
1028 }
1029
1030 dprintk(1, "Device is Xceive %d version %d.%d, "
1031 "firmware version %d.%d\n",
1032 hwmodel, hw_major, hw_minor, fw_major, fw_minor);
1033
1034 /* Check firmware version against what we downloaded. */
istvan_v@mailbox.hu09f46342011-06-06 13:00:17 -03001035 if (priv->firm_version != ((fw_major << 8) | fw_minor)) {
1036 printk(KERN_WARNING
1037 "Incorrect readback of firmware version %d.%d.\n",
1038 fw_major, fw_minor);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001039 goto fail;
1040 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001041
1042 /* Check that the tuner hardware model remains consistent over time. */
Istvan Varga7db98fe2011-06-04 12:25:19 -03001043 if (priv->hwmodel == 0 &&
1044 (hwmodel == XC_PRODUCT_ID_XC4000 ||
1045 hwmodel == XC_PRODUCT_ID_XC4100)) {
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001046 priv->hwmodel = hwmodel;
istvan_v@mailbox.hu09f46342011-06-06 13:00:17 -03001047 priv->hwvers = (hw_major << 8) | hw_minor;
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001048 } else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
istvan_v@mailbox.hu09f46342011-06-06 13:00:17 -03001049 priv->hwvers != ((hw_major << 8) | hw_minor)) {
1050 printk(KERN_WARNING
1051 "Read invalid device hardware information - tuner "
Istvan Vargafbe4a292011-06-03 10:11:48 -03001052 "hung?\n");
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001053 goto fail;
1054 }
1055
1056 memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
1057
1058 /*
1059 * By setting BASE in cur_fw.type only after successfully loading all
1060 * firmwares, we can:
1061 * 1. Identify that BASE firmware with type=0 has been loaded;
1062 * 2. Tell whether BASE firmware was just changed the next time through.
1063 */
1064 priv->cur_fw.type |= BASE;
1065
1066 return 0;
1067
1068fail:
1069 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
1070 if (!is_retry) {
1071 msleep(50);
1072 is_retry = 1;
1073 dprintk(1, "Retrying firmware load\n");
1074 goto retry;
1075 }
1076
1077 if (rc == -ENOENT)
1078 rc = -EINVAL;
1079 return rc;
1080}
Devin Heitmueller11091a32009-07-20 00:54:57 -03001081
Davide Ferri8d009a02009-06-23 22:34:06 -03001082static void xc_debug_dump(struct xc4000_priv *priv)
1083{
Istvan Vargafbe4a292011-06-03 10:11:48 -03001084 u16 adc_envelope;
1085 u32 freq_error_hz = 0;
1086 u16 lock_status;
1087 u32 hsync_freq_hz = 0;
1088 u16 frame_lines;
1089 u16 quality;
1090 u8 hw_majorversion = 0, hw_minorversion = 0;
1091 u8 fw_majorversion = 0, fw_minorversion = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -03001092
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001093 xc_get_adc_envelope(priv, &adc_envelope);
Davide Ferri8d009a02009-06-23 22:34:06 -03001094 dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
1095
1096 xc_get_frequency_error(priv, &freq_error_hz);
1097 dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
1098
Istvan Vargafbe4a292011-06-03 10:11:48 -03001099 xc_get_lock_status(priv, &lock_status);
Davide Ferri8d009a02009-06-23 22:34:06 -03001100 dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
1101 lock_status);
1102
Istvan Vargafbe4a292011-06-03 10:11:48 -03001103 xc_get_version(priv, &hw_majorversion, &hw_minorversion,
1104 &fw_majorversion, &fw_minorversion);
Davide Ferri8d009a02009-06-23 22:34:06 -03001105 dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
1106 hw_majorversion, hw_minorversion,
1107 fw_majorversion, fw_minorversion);
1108
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001109 if (priv->video_standard < XC4000_DTV6) {
1110 xc_get_hsync_freq(priv, &hsync_freq_hz);
1111 dprintk(1, "*** Horizontal sync frequency = %d Hz\n",
1112 hsync_freq_hz);
Davide Ferri8d009a02009-06-23 22:34:06 -03001113
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001114 xc_get_frame_lines(priv, &frame_lines);
1115 dprintk(1, "*** Frame lines = %d\n", frame_lines);
1116 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001117
Istvan Vargafbe4a292011-06-03 10:11:48 -03001118 xc_get_quality(priv, &quality);
Davide Ferri8d009a02009-06-23 22:34:06 -03001119 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
1120}
1121
1122static int xc4000_set_params(struct dvb_frontend *fe,
1123 struct dvb_frontend_parameters *params)
1124{
1125 struct xc4000_priv *priv = fe->tuner_priv;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001126 unsigned int type;
Istvan Varga56149422011-06-03 12:23:33 -03001127 int ret = -EREMOTEIO;
Davide Ferri8d009a02009-06-23 22:34:06 -03001128
Davide Ferri8d009a02009-06-23 22:34:06 -03001129 dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
1130
Istvan Varga56149422011-06-03 12:23:33 -03001131 mutex_lock(&priv->lock);
1132
Davide Ferri8d009a02009-06-23 22:34:06 -03001133 if (fe->ops.info.type == FE_ATSC) {
1134 dprintk(1, "%s() ATSC\n", __func__);
1135 switch (params->u.vsb.modulation) {
1136 case VSB_8:
1137 case VSB_16:
1138 dprintk(1, "%s() VSB modulation\n", __func__);
1139 priv->rf_mode = XC_RF_MODE_AIR;
1140 priv->freq_hz = params->frequency - 1750000;
1141 priv->bandwidth = BANDWIDTH_6_MHZ;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001142 priv->video_standard = XC4000_DTV6;
1143 type = DTV6;
Davide Ferri8d009a02009-06-23 22:34:06 -03001144 break;
1145 case QAM_64:
1146 case QAM_256:
1147 case QAM_AUTO:
1148 dprintk(1, "%s() QAM modulation\n", __func__);
1149 priv->rf_mode = XC_RF_MODE_CABLE;
1150 priv->freq_hz = params->frequency - 1750000;
1151 priv->bandwidth = BANDWIDTH_6_MHZ;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001152 priv->video_standard = XC4000_DTV6;
1153 type = DTV6;
Davide Ferri8d009a02009-06-23 22:34:06 -03001154 break;
1155 default:
Istvan Varga56149422011-06-03 12:23:33 -03001156 ret = -EINVAL;
1157 goto fail;
Davide Ferri8d009a02009-06-23 22:34:06 -03001158 }
1159 } else if (fe->ops.info.type == FE_OFDM) {
1160 dprintk(1, "%s() OFDM\n", __func__);
1161 switch (params->u.ofdm.bandwidth) {
1162 case BANDWIDTH_6_MHZ:
1163 priv->bandwidth = BANDWIDTH_6_MHZ;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001164 priv->video_standard = XC4000_DTV6;
Davide Ferri8d009a02009-06-23 22:34:06 -03001165 priv->freq_hz = params->frequency - 1750000;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001166 type = DTV6;
Davide Ferri8d009a02009-06-23 22:34:06 -03001167 break;
1168 case BANDWIDTH_7_MHZ:
Istvan Vargaf0ef7c82011-06-03 12:17:59 -03001169 priv->bandwidth = BANDWIDTH_7_MHZ;
1170 priv->video_standard = XC4000_DTV7;
1171 priv->freq_hz = params->frequency - 2250000;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001172 type = DTV7;
Istvan Vargaf0ef7c82011-06-03 12:17:59 -03001173 break;
Davide Ferri8d009a02009-06-23 22:34:06 -03001174 case BANDWIDTH_8_MHZ:
1175 priv->bandwidth = BANDWIDTH_8_MHZ;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001176 priv->video_standard = XC4000_DTV8;
Davide Ferri8d009a02009-06-23 22:34:06 -03001177 priv->freq_hz = params->frequency - 2750000;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001178 type = DTV8;
Davide Ferri8d009a02009-06-23 22:34:06 -03001179 break;
Istvan Vargaf0ef7c82011-06-03 12:17:59 -03001180 case BANDWIDTH_AUTO:
1181 if (params->frequency < 400000000) {
1182 priv->bandwidth = BANDWIDTH_7_MHZ;
1183 priv->freq_hz = params->frequency - 2250000;
1184 } else {
1185 priv->bandwidth = BANDWIDTH_8_MHZ;
1186 priv->freq_hz = params->frequency - 2750000;
1187 }
1188 priv->video_standard = XC4000_DTV7_8;
1189 type = DTV78;
1190 break;
Davide Ferri8d009a02009-06-23 22:34:06 -03001191 default:
1192 printk(KERN_ERR "xc4000 bandwidth not set!\n");
Istvan Varga56149422011-06-03 12:23:33 -03001193 ret = -EINVAL;
1194 goto fail;
Davide Ferri8d009a02009-06-23 22:34:06 -03001195 }
1196 priv->rf_mode = XC_RF_MODE_AIR;
1197 } else {
1198 printk(KERN_ERR "xc4000 modulation type not supported!\n");
Istvan Varga56149422011-06-03 12:23:33 -03001199 ret = -EINVAL;
1200 goto fail;
Davide Ferri8d009a02009-06-23 22:34:06 -03001201 }
1202
1203 dprintk(1, "%s() frequency=%d (compensated)\n",
1204 __func__, priv->freq_hz);
1205
Devin Heitmuellered23db32009-10-05 01:27:14 -03001206 /* Make sure the correct firmware type is loaded */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001207 if (check_firmware(fe, type, 0, priv->if_khz) != 0)
Istvan Varga56149422011-06-03 12:23:33 -03001208 goto fail;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001209
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001210 ret = xc_set_signal_source(priv, priv->rf_mode);
1211 if (ret != 0) {
1212 printk(KERN_ERR "xc4000: xc_set_signal_source(%d) failed\n",
Istvan Varga56149422011-06-03 12:23:33 -03001213 priv->rf_mode);
1214 goto fail;
Istvan Varga30f544e2011-06-04 12:12:42 -03001215 } else {
1216 u16 video_mode, audio_mode;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001217 video_mode = xc4000_standard[priv->video_standard].video_mode;
1218 audio_mode = xc4000_standard[priv->video_standard].audio_mode;
Istvan Varga30f544e2011-06-04 12:12:42 -03001219 if (type == DTV6 && priv->firm_version != 0x0102)
1220 video_mode |= 0x0001;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001221 ret = xc_set_tv_standard(priv, video_mode, audio_mode);
1222 if (ret != 0) {
1223 printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n");
Istvan Varga30f544e2011-06-04 12:12:42 -03001224 /* DJH - do not return when it fails... */
1225 /* goto fail; */
1226 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001227 }
1228
Istvan Varga30f544e2011-06-04 12:12:42 -03001229 if (priv->card_type == XC4000_CARD_WINFAST_CX88) {
1230 if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
1231 ret = 0;
1232 if (xc_write_reg(priv, XREG_AMPLITUDE,
1233 (priv->firm_version == 0x0102 ? 132 : 134))
1234 != 0)
1235 ret = -EREMOTEIO;
1236 if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
1237 ret = -EREMOTEIO;
1238 if (ret != 0) {
1239 printk(KERN_ERR "xc4000: setting registers failed\n");
1240 /* goto fail; */
1241 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001242 }
Istvan Varga30f544e2011-06-04 12:12:42 -03001243
Istvan Vargae75873c2011-06-04 12:18:41 -03001244 xc_tune_channel(priv, priv->freq_hz);
Davide Ferri8d009a02009-06-23 22:34:06 -03001245
Istvan Varga56149422011-06-03 12:23:33 -03001246 ret = 0;
1247
1248fail:
1249 mutex_unlock(&priv->lock);
1250
1251 return ret;
Davide Ferri8d009a02009-06-23 22:34:06 -03001252}
1253
Davide Ferri8d009a02009-06-23 22:34:06 -03001254static int xc4000_set_analog_params(struct dvb_frontend *fe,
1255 struct analog_parameters *params)
1256{
1257 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Varga818a1772011-06-04 12:17:22 -03001258 unsigned int type = 0;
Istvan Varga56149422011-06-03 12:23:33 -03001259 int ret = -EREMOTEIO;
Davide Ferri8d009a02009-06-23 22:34:06 -03001260
Istvan Varga818a1772011-06-04 12:17:22 -03001261 if (params->mode == V4L2_TUNER_RADIO) {
1262 dprintk(1, "%s() frequency=%d (in units of 62.5Hz)\n",
1263 __func__, params->frequency);
1264
1265 mutex_lock(&priv->lock);
1266
1267 params->std = 0;
1268 priv->freq_hz = params->frequency * 125L / 2;
1269
1270 if (audio_std & XC4000_AUDIO_STD_INPUT1) {
1271 priv->video_standard = XC4000_FM_Radio_INPUT1;
1272 type = FM | INPUT1;
1273 } else {
1274 priv->video_standard = XC4000_FM_Radio_INPUT2;
1275 type = FM | INPUT2;
1276 }
1277
1278 goto tune_channel;
1279 }
1280
Davide Ferri8d009a02009-06-23 22:34:06 -03001281 dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
1282 __func__, params->frequency);
1283
Istvan Varga56149422011-06-03 12:23:33 -03001284 mutex_lock(&priv->lock);
1285
Davide Ferri8d009a02009-06-23 22:34:06 -03001286 /* params->frequency is in units of 62.5khz */
1287 priv->freq_hz = params->frequency * 62500;
1288
Istvan Varga818a1772011-06-04 12:17:22 -03001289 params->std &= V4L2_STD_ALL;
1290 /* if std is not defined, choose one */
1291 if (!params->std)
1292 params->std = V4L2_STD_PAL_BG;
1293
1294 if (audio_std & XC4000_AUDIO_STD_MONO)
1295 type = MONO;
1296
Davide Ferri8d009a02009-06-23 22:34:06 -03001297 if (params->std & V4L2_STD_MN) {
Istvan Varga818a1772011-06-04 12:17:22 -03001298 params->std = V4L2_STD_MN;
1299 if (audio_std & XC4000_AUDIO_STD_MONO) {
1300 priv->video_standard = XC4000_MN_NTSC_PAL_Mono;
1301 } else if (audio_std & XC4000_AUDIO_STD_A2) {
1302 params->std |= V4L2_STD_A2;
1303 priv->video_standard = XC4000_MN_NTSC_PAL_A2;
1304 } else {
1305 params->std |= V4L2_STD_BTSC;
1306 priv->video_standard = XC4000_MN_NTSC_PAL_BTSC;
1307 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001308 goto tune_channel;
1309 }
1310
1311 if (params->std & V4L2_STD_PAL_BG) {
Istvan Varga818a1772011-06-04 12:17:22 -03001312 params->std = V4L2_STD_PAL_BG;
1313 if (audio_std & XC4000_AUDIO_STD_MONO) {
1314 priv->video_standard = XC4000_BG_PAL_MONO;
1315 } else if (!(audio_std & XC4000_AUDIO_STD_A2)) {
1316 if (!(audio_std & XC4000_AUDIO_STD_B)) {
1317 params->std |= V4L2_STD_NICAM_A;
1318 priv->video_standard = XC4000_BG_PAL_NICAM;
1319 } else {
1320 params->std |= V4L2_STD_NICAM_B;
1321 priv->video_standard = XC4000_BG_PAL_NICAM;
1322 }
1323 } else {
1324 if (!(audio_std & XC4000_AUDIO_STD_B)) {
1325 params->std |= V4L2_STD_A2_A;
1326 priv->video_standard = XC4000_BG_PAL_A2;
1327 } else {
1328 params->std |= V4L2_STD_A2_B;
1329 priv->video_standard = XC4000_BG_PAL_A2;
1330 }
1331 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001332 goto tune_channel;
1333 }
1334
1335 if (params->std & V4L2_STD_PAL_I) {
1336 /* default to NICAM audio standard */
Istvan Varga818a1772011-06-04 12:17:22 -03001337 params->std = V4L2_STD_PAL_I | V4L2_STD_NICAM;
1338 if (audio_std & XC4000_AUDIO_STD_MONO) {
1339 priv->video_standard = XC4000_I_PAL_NICAM_MONO;
1340 } else {
1341 priv->video_standard = XC4000_I_PAL_NICAM;
1342 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001343 goto tune_channel;
1344 }
1345
1346 if (params->std & V4L2_STD_PAL_DK) {
Istvan Varga818a1772011-06-04 12:17:22 -03001347 params->std = V4L2_STD_PAL_DK;
1348 if (audio_std & XC4000_AUDIO_STD_MONO) {
1349 priv->video_standard = XC4000_DK_PAL_MONO;
1350 } else if (audio_std & XC4000_AUDIO_STD_A2) {
1351 params->std |= V4L2_STD_A2;
1352 priv->video_standard = XC4000_DK_PAL_A2;
1353 } else {
1354 params->std |= V4L2_STD_NICAM;
1355 priv->video_standard = XC4000_DK_PAL_NICAM;
1356 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001357 goto tune_channel;
1358 }
1359
1360 if (params->std & V4L2_STD_SECAM_DK) {
Istvan Varga818a1772011-06-04 12:17:22 -03001361 /* default to A2 audio standard */
1362 params->std = V4L2_STD_SECAM_DK | V4L2_STD_A2;
1363 if (audio_std & XC4000_AUDIO_STD_L) {
1364 type = 0;
1365 priv->video_standard = XC4000_DK_SECAM_NICAM;
1366 } else if (audio_std & XC4000_AUDIO_STD_MONO) {
1367 priv->video_standard = XC4000_DK_SECAM_A2MONO;
1368 } else if (audio_std & XC4000_AUDIO_STD_K3) {
1369 params->std |= V4L2_STD_SECAM_K3;
1370 priv->video_standard = XC4000_DK_SECAM_A2LDK3;
1371 } else {
1372 priv->video_standard = XC4000_DK_SECAM_A2DK1;
1373 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001374 goto tune_channel;
1375 }
1376
1377 if (params->std & V4L2_STD_SECAM_L) {
Istvan Varga818a1772011-06-04 12:17:22 -03001378 /* default to NICAM audio standard */
1379 type = 0;
1380 params->std = V4L2_STD_SECAM_L | V4L2_STD_NICAM;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001381 priv->video_standard = XC4000_L_SECAM_NICAM;
Davide Ferri8d009a02009-06-23 22:34:06 -03001382 goto tune_channel;
1383 }
1384
1385 if (params->std & V4L2_STD_SECAM_LC) {
Istvan Varga818a1772011-06-04 12:17:22 -03001386 /* default to NICAM audio standard */
1387 type = 0;
1388 params->std = V4L2_STD_SECAM_LC | V4L2_STD_NICAM;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001389 priv->video_standard = XC4000_LC_SECAM_NICAM;
Davide Ferri8d009a02009-06-23 22:34:06 -03001390 goto tune_channel;
1391 }
1392
1393tune_channel:
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001394 /* FIXME: it could be air. */
Istvan Varga818a1772011-06-04 12:17:22 -03001395 priv->rf_mode = XC_RF_MODE_CABLE;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001396
Istvan Varga818a1772011-06-04 12:17:22 -03001397 if (check_firmware(fe, type, params->std,
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001398 xc4000_standard[priv->video_standard].int_freq) != 0)
Istvan Varga56149422011-06-03 12:23:33 -03001399 goto fail;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001400
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001401 ret = xc_set_signal_source(priv, priv->rf_mode);
1402 if (ret != 0) {
Davide Ferri8d009a02009-06-23 22:34:06 -03001403 printk(KERN_ERR
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001404 "xc4000: xc_set_signal_source(%d) failed\n",
Istvan Varga56149422011-06-03 12:23:33 -03001405 priv->rf_mode);
1406 goto fail;
Istvan Varga30f544e2011-06-04 12:12:42 -03001407 } else {
1408 u16 video_mode, audio_mode;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001409 video_mode = xc4000_standard[priv->video_standard].video_mode;
1410 audio_mode = xc4000_standard[priv->video_standard].audio_mode;
Istvan Varga30f544e2011-06-04 12:12:42 -03001411 if (priv->video_standard < XC4000_BG_PAL_A2) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001412 if (type & NOGD)
Istvan Varga30f544e2011-06-04 12:12:42 -03001413 video_mode &= 0xFF7F;
1414 } else if (priv->video_standard < XC4000_I_PAL_NICAM) {
1415 if (priv->card_type == XC4000_CARD_WINFAST_CX88 &&
1416 priv->firm_version == 0x0102)
1417 video_mode &= 0xFEFF;
Istvan Varga923137a2011-06-04 12:15:51 -03001418 if (audio_std & XC4000_AUDIO_STD_B)
1419 video_mode |= 0x0080;
Istvan Varga30f544e2011-06-04 12:12:42 -03001420 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001421 ret = xc_set_tv_standard(priv, video_mode, audio_mode);
1422 if (ret != 0) {
1423 printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n");
Istvan Varga30f544e2011-06-04 12:12:42 -03001424 goto fail;
1425 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001426 }
1427
Istvan Varga30f544e2011-06-04 12:12:42 -03001428 if (priv->card_type == XC4000_CARD_WINFAST_CX88) {
1429 if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
1430 ret = 0;
1431 if (xc_write_reg(priv, XREG_AMPLITUDE, 1) != 0)
1432 ret = -EREMOTEIO;
1433 if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
1434 ret = -EREMOTEIO;
1435 if (ret != 0) {
1436 printk(KERN_ERR "xc4000: setting registers failed\n");
1437 goto fail;
1438 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001439 }
1440
Istvan Vargae75873c2011-06-04 12:18:41 -03001441 xc_tune_channel(priv, priv->freq_hz);
Davide Ferri8d009a02009-06-23 22:34:06 -03001442
Istvan Varga56149422011-06-03 12:23:33 -03001443 ret = 0;
1444
1445fail:
1446 mutex_unlock(&priv->lock);
1447
1448 return ret;
Davide Ferri8d009a02009-06-23 22:34:06 -03001449}
1450
1451static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
1452{
1453 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001454
Davide Ferri8d009a02009-06-23 22:34:06 -03001455 *freq = priv->freq_hz;
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001456
1457 if (debug) {
1458 mutex_lock(&priv->lock);
1459 if ((priv->cur_fw.type
1460 & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
1461 u16 snr = 0;
1462 if (xc4000_readreg(priv, XREG_SNR, &snr) == 0) {
1463 mutex_unlock(&priv->lock);
1464 dprintk(1, "%s() freq = %u, SNR = %d\n",
1465 __func__, *freq, snr);
1466 return 0;
1467 }
1468 }
1469 mutex_unlock(&priv->lock);
1470 }
1471
1472 dprintk(1, "%s()\n", __func__);
1473
Davide Ferri8d009a02009-06-23 22:34:06 -03001474 return 0;
1475}
1476
1477static int xc4000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
1478{
1479 struct xc4000_priv *priv = fe->tuner_priv;
1480 dprintk(1, "%s()\n", __func__);
1481
1482 *bw = priv->bandwidth;
1483 return 0;
1484}
1485
1486static int xc4000_get_status(struct dvb_frontend *fe, u32 *status)
1487{
1488 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Vargafbe4a292011-06-03 10:11:48 -03001489 u16 lock_status = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -03001490
Istvan Varga56149422011-06-03 12:23:33 -03001491 mutex_lock(&priv->lock);
1492
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001493 if (priv->cur_fw.type & BASE)
1494 xc_get_lock_status(priv, &lock_status);
1495
1496 *status = (lock_status == 1 ?
1497 TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO : 0);
1498 if (priv->cur_fw.type & (DTV6 | DTV7 | DTV78 | DTV8))
1499 *status &= (~TUNER_STATUS_STEREO);
Davide Ferri8d009a02009-06-23 22:34:06 -03001500
Istvan Varga56149422011-06-03 12:23:33 -03001501 mutex_unlock(&priv->lock);
1502
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001503 dprintk(2, "%s() lock_status = %d\n", __func__, lock_status);
Davide Ferri8d009a02009-06-23 22:34:06 -03001504
1505 return 0;
1506}
1507
Davide Ferri8d009a02009-06-23 22:34:06 -03001508static int xc4000_sleep(struct dvb_frontend *fe)
1509{
Istvan Varga5272f6b2011-06-04 12:03:03 -03001510 struct xc4000_priv *priv = fe->tuner_priv;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001511 int ret = 0;
Istvan Varga5272f6b2011-06-04 12:03:03 -03001512
1513 dprintk(1, "%s()\n", __func__);
1514
1515 mutex_lock(&priv->lock);
1516
1517 /* Avoid firmware reload on slow devices */
1518 if ((no_poweroff == 2 ||
1519 (no_poweroff == 0 &&
1520 priv->card_type != XC4000_CARD_WINFAST_CX88)) &&
1521 (priv->cur_fw.type & BASE) != 0) {
1522 /* force reset and firmware reload */
1523 priv->cur_fw.type = XC_POWERED_DOWN;
1524
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001525 if (xc_write_reg(priv, XREG_POWER_DOWN, 0) != 0) {
Istvan Varga5272f6b2011-06-04 12:03:03 -03001526 printk(KERN_ERR
1527 "xc4000: %s() unable to shutdown tuner\n",
1528 __func__);
1529 ret = -EREMOTEIO;
1530 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001531 msleep(20);
Istvan Varga5272f6b2011-06-04 12:03:03 -03001532 }
1533
1534 mutex_unlock(&priv->lock);
1535
1536 return ret;
Davide Ferri8d009a02009-06-23 22:34:06 -03001537}
1538
1539static int xc4000_init(struct dvb_frontend *fe)
1540{
Davide Ferri8d009a02009-06-23 22:34:06 -03001541 dprintk(1, "%s()\n", __func__);
1542
Davide Ferri8d009a02009-06-23 22:34:06 -03001543 return 0;
1544}
1545
1546static int xc4000_release(struct dvb_frontend *fe)
1547{
1548 struct xc4000_priv *priv = fe->tuner_priv;
1549
1550 dprintk(1, "%s()\n", __func__);
1551
1552 mutex_lock(&xc4000_list_mutex);
1553
1554 if (priv)
1555 hybrid_tuner_release_state(priv);
1556
1557 mutex_unlock(&xc4000_list_mutex);
1558
1559 fe->tuner_priv = NULL;
1560
1561 return 0;
1562}
1563
1564static const struct dvb_tuner_ops xc4000_tuner_ops = {
1565 .info = {
1566 .name = "Xceive XC4000",
1567 .frequency_min = 1000000,
1568 .frequency_max = 1023000000,
1569 .frequency_step = 50000,
1570 },
1571
1572 .release = xc4000_release,
1573 .init = xc4000_init,
1574 .sleep = xc4000_sleep,
1575
1576 .set_params = xc4000_set_params,
1577 .set_analog_params = xc4000_set_analog_params,
1578 .get_frequency = xc4000_get_frequency,
1579 .get_bandwidth = xc4000_get_bandwidth,
1580 .get_status = xc4000_get_status
1581};
1582
1583struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
1584 struct i2c_adapter *i2c,
1585 struct xc4000_config *cfg)
1586{
1587 struct xc4000_priv *priv = NULL;
Istvan Vargafbe4a292011-06-03 10:11:48 -03001588 int instance;
1589 u16 id = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -03001590
Istvan Varga0b402132011-06-03 09:38:04 -03001591 if (cfg->card_type != XC4000_CARD_GENERIC) {
1592 if (cfg->card_type == XC4000_CARD_WINFAST_CX88) {
1593 cfg->i2c_address = 0x61;
1594 cfg->if_khz = 4560;
1595 } else { /* default to PCTV 340E */
1596 cfg->i2c_address = 0x61;
1597 cfg->if_khz = 5400;
1598 }
1599 }
1600
Davide Ferri8d009a02009-06-23 22:34:06 -03001601 dprintk(1, "%s(%d-%04x)\n", __func__,
1602 i2c ? i2c_adapter_id(i2c) : -1,
1603 cfg ? cfg->i2c_address : -1);
1604
1605 mutex_lock(&xc4000_list_mutex);
1606
1607 instance = hybrid_tuner_request_state(struct xc4000_priv, priv,
1608 hybrid_tuner_instance_list,
1609 i2c, cfg->i2c_address, "xc4000");
Istvan Varga0b402132011-06-03 09:38:04 -03001610 if (cfg->card_type != XC4000_CARD_GENERIC)
1611 priv->card_type = cfg->card_type;
Davide Ferri8d009a02009-06-23 22:34:06 -03001612 switch (instance) {
1613 case 0:
1614 goto fail;
1615 break;
1616 case 1:
1617 /* new tuner instance */
1618 priv->bandwidth = BANDWIDTH_6_MHZ;
Istvan Varga56149422011-06-03 12:23:33 -03001619 mutex_init(&priv->lock);
Davide Ferri8d009a02009-06-23 22:34:06 -03001620 fe->tuner_priv = priv;
1621 break;
1622 default:
1623 /* existing tuner instance */
1624 fe->tuner_priv = priv;
1625 break;
1626 }
1627
Istvan Varga0b402132011-06-03 09:38:04 -03001628 if (cfg->if_khz != 0) {
Davide Ferri8d009a02009-06-23 22:34:06 -03001629 /* If the IF hasn't been set yet, use the value provided by
1630 the caller (occurs in hybrid devices where the analog
1631 call to xc4000_attach occurs before the digital side) */
1632 priv->if_khz = cfg->if_khz;
1633 }
1634
1635 /* Check if firmware has been loaded. It is possible that another
1636 instance of the driver has loaded the firmware.
1637 */
1638
Istvan Varga027fd362011-06-04 12:04:51 -03001639 if (instance == 1) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001640 if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -03001641 goto fail;
Istvan Varga027fd362011-06-04 12:04:51 -03001642 } else {
1643 id = ((priv->cur_fw.type & BASE) != 0 ?
1644 priv->hwmodel : XC_PRODUCT_ID_FW_NOT_LOADED);
1645 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001646
1647 switch (id) {
Istvan Varga7db98fe2011-06-04 12:25:19 -03001648 case XC_PRODUCT_ID_XC4000:
1649 case XC_PRODUCT_ID_XC4100:
Davide Ferri8d009a02009-06-23 22:34:06 -03001650 printk(KERN_INFO
1651 "xc4000: Successfully identified at address 0x%02x\n",
1652 cfg->i2c_address);
1653 printk(KERN_INFO
1654 "xc4000: Firmware has been loaded previously\n");
1655 break;
1656 case XC_PRODUCT_ID_FW_NOT_LOADED:
1657 printk(KERN_INFO
1658 "xc4000: Successfully identified at address 0x%02x\n",
1659 cfg->i2c_address);
1660 printk(KERN_INFO
1661 "xc4000: Firmware has not been loaded previously\n");
1662 break;
1663 default:
1664 printk(KERN_ERR
1665 "xc4000: Device not found at addr 0x%02x (0x%x)\n",
1666 cfg->i2c_address, id);
1667 goto fail;
1668 }
1669
1670 mutex_unlock(&xc4000_list_mutex);
1671
1672 memcpy(&fe->ops.tuner_ops, &xc4000_tuner_ops,
1673 sizeof(struct dvb_tuner_ops));
1674
Istvan Varga027fd362011-06-04 12:04:51 -03001675 if (instance == 1) {
1676 int ret;
1677 mutex_lock(&priv->lock);
1678 ret = xc4000_fwupload(fe);
1679 mutex_unlock(&priv->lock);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001680 if (ret != 0)
Istvan Varga027fd362011-06-04 12:04:51 -03001681 goto fail2;
1682 }
Devin Heitmueller11091a32009-07-20 00:54:57 -03001683
Davide Ferri8d009a02009-06-23 22:34:06 -03001684 return fe;
1685fail:
1686 mutex_unlock(&xc4000_list_mutex);
Istvan Varga027fd362011-06-04 12:04:51 -03001687fail2:
Davide Ferri8d009a02009-06-23 22:34:06 -03001688 xc4000_release(fe);
1689 return NULL;
1690}
1691EXPORT_SYMBOL(xc4000_attach);
1692
1693MODULE_AUTHOR("Steven Toth, Davide Ferri");
1694MODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver");
1695MODULE_LICENSE("GPL");