blob: 68397110b7d932fec46c3cdd4ecc0b9d2e99ddf4 [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;
Istvan Vargafbe4a292011-06-03 10:11:48 -030095 u32 if_khz;
96 u32 freq_hz;
97 u32 bandwidth;
98 u8 video_standard;
99 u8 rf_mode;
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -0300100 u8 default_pm;
101 u8 dvb_amplitude;
102 u8 set_smoothedcvbs;
Istvan Vargafbe4a292011-06-03 10:11:48 -0300103 u8 ignore_i2c_write_errors;
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -0300104 __u16 firm_version;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300105 struct firmware_properties cur_fw;
Istvan Vargafbe4a292011-06-03 10:11:48 -0300106 __u16 hwmodel;
107 __u16 hwvers;
Istvan Varga56149422011-06-03 12:23:33 -0300108 struct mutex lock;
Davide Ferri8d009a02009-06-23 22:34:06 -0300109};
110
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300111#define XC4000_AUDIO_STD_B 1
112#define XC4000_AUDIO_STD_A2 2
113#define XC4000_AUDIO_STD_K3 4
114#define XC4000_AUDIO_STD_L 8
115#define XC4000_AUDIO_STD_INPUT1 16
116#define XC4000_AUDIO_STD_MONO 32
117
118#define XC4000_DEFAULT_FIRMWARE "dvb-fe-xc4000-1.4.fw"
119
Davide Ferri8d009a02009-06-23 22:34:06 -0300120/* Misc Defines */
Istvan Varga49110852011-06-03 10:55:24 -0300121#define MAX_TV_STANDARD 24
Davide Ferri8d009a02009-06-23 22:34:06 -0300122#define XC_MAX_I2C_WRITE_LENGTH 64
Istvan Varga5272f6b2011-06-04 12:03:03 -0300123#define XC_POWERED_DOWN 0x80000000U
Davide Ferri8d009a02009-06-23 22:34:06 -0300124
125/* Signal Types */
126#define XC_RF_MODE_AIR 0
127#define XC_RF_MODE_CABLE 1
128
Davide Ferri8d009a02009-06-23 22:34:06 -0300129/* Product id */
130#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
Istvan Varga7db98fe2011-06-04 12:25:19 -0300131#define XC_PRODUCT_ID_XC4000 0x0FA0
132#define XC_PRODUCT_ID_XC4100 0x1004
Davide Ferri8d009a02009-06-23 22:34:06 -0300133
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300134/* Registers (Write-only) */
Davide Ferri8d009a02009-06-23 22:34:06 -0300135#define XREG_INIT 0x00
136#define XREG_VIDEO_MODE 0x01
137#define XREG_AUDIO_MODE 0x02
138#define XREG_RF_FREQ 0x03
139#define XREG_D_CODE 0x04
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300140#define XREG_DIRECTSITTING_MODE 0x05
141#define XREG_SEEK_MODE 0x06
142#define XREG_POWER_DOWN 0x08
143#define XREG_SIGNALSOURCE 0x0A
Istvan Varga30f544e2011-06-04 12:12:42 -0300144#define XREG_SMOOTHEDCVBS 0x0E
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300145#define XREG_AMPLITUDE 0x10
Davide Ferri8d009a02009-06-23 22:34:06 -0300146
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300147/* Registers (Read-only) */
Davide Ferri8d009a02009-06-23 22:34:06 -0300148#define XREG_ADC_ENV 0x00
149#define XREG_QUALITY 0x01
150#define XREG_FRAME_LINES 0x02
151#define XREG_HSYNC_FREQ 0x03
152#define XREG_LOCK 0x04
153#define XREG_FREQ_ERROR 0x05
154#define XREG_SNR 0x06
155#define XREG_VERSION 0x07
156#define XREG_PRODUCT_ID 0x08
Miroslav Slugen8a538a82011-12-20 21:18:38 -0300157#define XREG_SIGNAL_LEVEL 0x0A
158#define XREG_NOISE_LEVEL 0x0B
Davide Ferri8d009a02009-06-23 22:34:06 -0300159
160/*
161 Basic firmware description. This will remain with
162 the driver for documentation purposes.
163
164 This represents an I2C firmware file encoded as a
165 string of unsigned char. Format is as follows:
166
167 char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB
168 char[1 ]=len0_LSB -> length of first write transaction
169 char[2 ]=data0 -> first byte to be sent
170 char[3 ]=data1
171 char[4 ]=data2
172 char[ ]=...
173 char[M ]=dataN -> last byte to be sent
174 char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB
175 char[M+2]=len1_LSB -> length of second write transaction
176 char[M+3]=data0
177 char[M+4]=data1
178 ...
179 etc.
180
181 The [len] value should be interpreted as follows:
182
183 len= len_MSB _ len_LSB
184 len=1111_1111_1111_1111 : End of I2C_SEQUENCE
185 len=0000_0000_0000_0000 : Reset command: Do hardware reset
186 len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767)
187 len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms
188
189 For the RESET and WAIT commands, the two following bytes will contain
190 immediately the length of the following transaction.
Davide Ferri8d009a02009-06-23 22:34:06 -0300191*/
Istvan Vargafbe4a292011-06-03 10:11:48 -0300192
Davide Ferri8d009a02009-06-23 22:34:06 -0300193struct XC_TV_STANDARD {
Istvan Vargafbe4a292011-06-03 10:11:48 -0300194 const char *Name;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300195 u16 audio_mode;
196 u16 video_mode;
Istvan Varga49110852011-06-03 10:55:24 -0300197 u16 int_freq;
Davide Ferri8d009a02009-06-23 22:34:06 -0300198};
199
200/* Tuner standards */
Devin Heitmuellered23db32009-10-05 01:27:14 -0300201#define XC4000_MN_NTSC_PAL_BTSC 0
202#define XC4000_MN_NTSC_PAL_A2 1
203#define XC4000_MN_NTSC_PAL_EIAJ 2
204#define XC4000_MN_NTSC_PAL_Mono 3
205#define XC4000_BG_PAL_A2 4
206#define XC4000_BG_PAL_NICAM 5
207#define XC4000_BG_PAL_MONO 6
208#define XC4000_I_PAL_NICAM 7
209#define XC4000_I_PAL_NICAM_MONO 8
210#define XC4000_DK_PAL_A2 9
211#define XC4000_DK_PAL_NICAM 10
212#define XC4000_DK_PAL_MONO 11
213#define XC4000_DK_SECAM_A2DK1 12
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300214#define XC4000_DK_SECAM_A2LDK3 13
215#define XC4000_DK_SECAM_A2MONO 14
Istvan Varga49110852011-06-03 10:55:24 -0300216#define XC4000_DK_SECAM_NICAM 15
217#define XC4000_L_SECAM_NICAM 16
218#define XC4000_LC_SECAM_NICAM 17
219#define XC4000_DTV6 18
220#define XC4000_DTV8 19
221#define XC4000_DTV7_8 20
222#define XC4000_DTV7 21
223#define XC4000_FM_Radio_INPUT2 22
224#define XC4000_FM_Radio_INPUT1 23
Davide Ferri8d009a02009-06-23 22:34:06 -0300225
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300226static struct XC_TV_STANDARD xc4000_standard[MAX_TV_STANDARD] = {
Istvan Varga49110852011-06-03 10:55:24 -0300227 {"M/N-NTSC/PAL-BTSC", 0x0000, 0x80A0, 4500},
228 {"M/N-NTSC/PAL-A2", 0x0000, 0x80A0, 4600},
229 {"M/N-NTSC/PAL-EIAJ", 0x0040, 0x80A0, 4500},
230 {"M/N-NTSC/PAL-Mono", 0x0078, 0x80A0, 4500},
231 {"B/G-PAL-A2", 0x0000, 0x8159, 5640},
232 {"B/G-PAL-NICAM", 0x0004, 0x8159, 5740},
233 {"B/G-PAL-MONO", 0x0078, 0x8159, 5500},
234 {"I-PAL-NICAM", 0x0080, 0x8049, 6240},
235 {"I-PAL-NICAM-MONO", 0x0078, 0x8049, 6000},
236 {"D/K-PAL-A2", 0x0000, 0x8049, 6380},
237 {"D/K-PAL-NICAM", 0x0080, 0x8049, 6200},
238 {"D/K-PAL-MONO", 0x0078, 0x8049, 6500},
239 {"D/K-SECAM-A2 DK1", 0x0000, 0x8049, 6340},
240 {"D/K-SECAM-A2 L/DK3", 0x0000, 0x8049, 6000},
241 {"D/K-SECAM-A2 MONO", 0x0078, 0x8049, 6500},
242 {"D/K-SECAM-NICAM", 0x0080, 0x8049, 6200},
243 {"L-SECAM-NICAM", 0x8080, 0x0009, 6200},
244 {"L'-SECAM-NICAM", 0x8080, 0x4009, 6200},
245 {"DTV6", 0x00C0, 0x8002, 0},
246 {"DTV8", 0x00C0, 0x800B, 0},
247 {"DTV7/8", 0x00C0, 0x801B, 0},
248 {"DTV7", 0x00C0, 0x8007, 0},
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300249 {"FM Radio-INPUT2", 0x0008, 0x9800, 10700},
250 {"FM Radio-INPUT1", 0x0008, 0x9000, 10700}
Davide Ferri8d009a02009-06-23 22:34:06 -0300251};
252
Davide Ferri8d009a02009-06-23 22:34:06 -0300253static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300254static int xc4000_tuner_reset(struct dvb_frontend *fe);
Istvan Vargaf4312e2f2011-06-04 12:08:29 -0300255static void xc_debug_dump(struct xc4000_priv *priv);
Davide Ferri8d009a02009-06-23 22:34:06 -0300256
257static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
258{
259 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
260 .flags = 0, .buf = buf, .len = len };
Davide Ferri8d009a02009-06-23 22:34:06 -0300261 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
Devin Heitmueller799ed112009-10-04 23:09:18 -0300262 if (priv->ignore_i2c_write_errors == 0) {
263 printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n",
264 len);
265 if (len == 4) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300266 printk(KERN_ERR "bytes %02x %02x %02x %02x\n", buf[0],
Devin Heitmueller799ed112009-10-04 23:09:18 -0300267 buf[1], buf[2], buf[3]);
268 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300269 return -EREMOTEIO;
Devin Heitmueller799ed112009-10-04 23:09:18 -0300270 }
Davide Ferri8d009a02009-06-23 22:34:06 -0300271 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300272 return 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300273}
274
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300275static int xc4000_tuner_reset(struct dvb_frontend *fe)
Davide Ferri8d009a02009-06-23 22:34:06 -0300276{
277 struct xc4000_priv *priv = fe->tuner_priv;
278 int ret;
279
280 dprintk(1, "%s()\n", __func__);
281
282 if (fe->callback) {
283 ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
284 fe->dvb->priv :
285 priv->i2c_props.adap->algo_data,
286 DVB_FRONTEND_COMPONENT_TUNER,
287 XC4000_TUNER_RESET, 0);
288 if (ret) {
289 printk(KERN_ERR "xc4000: reset failed\n");
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300290 return -EREMOTEIO;
Davide Ferri8d009a02009-06-23 22:34:06 -0300291 }
292 } else {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300293 printk(KERN_ERR "xc4000: no tuner reset callback function, "
294 "fatal\n");
295 return -EINVAL;
Davide Ferri8d009a02009-06-23 22:34:06 -0300296 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300297 return 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300298}
299
300static int xc_write_reg(struct xc4000_priv *priv, u16 regAddr, u16 i2cData)
301{
302 u8 buf[4];
Davide Ferri8d009a02009-06-23 22:34:06 -0300303 int result;
304
305 buf[0] = (regAddr >> 8) & 0xFF;
306 buf[1] = regAddr & 0xFF;
307 buf[2] = (i2cData >> 8) & 0xFF;
308 buf[3] = i2cData & 0xFF;
309 result = xc_send_i2c_data(priv, buf, 4);
Davide Ferri8d009a02009-06-23 22:34:06 -0300310
311 return result;
312}
313
314static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
315{
316 struct xc4000_priv *priv = fe->tuner_priv;
317
318 int i, nbytes_to_send, result;
319 unsigned int len, pos, index;
320 u8 buf[XC_MAX_I2C_WRITE_LENGTH];
321
322 index = 0;
323 while ((i2c_sequence[index] != 0xFF) ||
324 (i2c_sequence[index + 1] != 0xFF)) {
325 len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
326 if (len == 0x0000) {
327 /* RESET command */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300328 /* NOTE: this is ignored, as the reset callback was */
329 /* already called by check_firmware() */
Davide Ferri8d009a02009-06-23 22:34:06 -0300330 index += 2;
Davide Ferri8d009a02009-06-23 22:34:06 -0300331 } else if (len & 0x8000) {
332 /* WAIT command */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300333 msleep(len & 0x7FFF);
Davide Ferri8d009a02009-06-23 22:34:06 -0300334 index += 2;
335 } else {
336 /* Send i2c data whilst ensuring individual transactions
337 * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
338 */
339 index += 2;
340 buf[0] = i2c_sequence[index];
341 buf[1] = i2c_sequence[index + 1];
342 pos = 2;
343 while (pos < len) {
344 if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
345 nbytes_to_send =
346 XC_MAX_I2C_WRITE_LENGTH;
347 else
348 nbytes_to_send = (len - pos + 2);
349 for (i = 2; i < nbytes_to_send; i++) {
350 buf[i] = i2c_sequence[index + pos +
351 i - 2];
352 }
353 result = xc_send_i2c_data(priv, buf,
354 nbytes_to_send);
355
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300356 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300357 return result;
358
359 pos += nbytes_to_send - 2;
360 }
361 index += len;
362 }
363 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300364 return 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300365}
366
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300367static int xc_set_tv_standard(struct xc4000_priv *priv,
368 u16 video_mode, u16 audio_mode)
Davide Ferri8d009a02009-06-23 22:34:06 -0300369{
370 int ret;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300371 dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, video_mode, audio_mode);
Davide Ferri8d009a02009-06-23 22:34:06 -0300372 dprintk(1, "%s() Standard = %s\n",
373 __func__,
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300374 xc4000_standard[priv->video_standard].Name);
Davide Ferri8d009a02009-06-23 22:34:06 -0300375
Devin Heitmueller799ed112009-10-04 23:09:18 -0300376 /* Don't complain when the request fails because of i2c stretching */
377 priv->ignore_i2c_write_errors = 1;
378
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300379 ret = xc_write_reg(priv, XREG_VIDEO_MODE, video_mode);
380 if (ret == 0)
381 ret = xc_write_reg(priv, XREG_AUDIO_MODE, audio_mode);
Davide Ferri8d009a02009-06-23 22:34:06 -0300382
Devin Heitmueller799ed112009-10-04 23:09:18 -0300383 priv->ignore_i2c_write_errors = 0;
384
Davide Ferri8d009a02009-06-23 22:34:06 -0300385 return ret;
386}
387
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300388static int xc_set_signal_source(struct xc4000_priv *priv, u16 rf_mode)
Davide Ferri8d009a02009-06-23 22:34:06 -0300389{
390 dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
391 rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
392
393 if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
394 rf_mode = XC_RF_MODE_CABLE;
395 printk(KERN_ERR
396 "%s(), Invalid mode, defaulting to CABLE",
397 __func__);
398 }
399 return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
400}
401
402static const struct dvb_tuner_ops xc4000_tuner_ops;
403
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300404static int xc_set_rf_frequency(struct xc4000_priv *priv, u32 freq_hz)
Davide Ferri8d009a02009-06-23 22:34:06 -0300405{
406 u16 freq_code;
407
408 dprintk(1, "%s(%u)\n", __func__, freq_hz);
409
410 if ((freq_hz > xc4000_tuner_ops.info.frequency_max) ||
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300411 (freq_hz < xc4000_tuner_ops.info.frequency_min))
412 return -EINVAL;
Davide Ferri8d009a02009-06-23 22:34:06 -0300413
414 freq_code = (u16)(freq_hz / 15625);
415
416 /* WAS: Starting in firmware version 1.1.44, Xceive recommends using the
417 FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
418 only be used for fast scanning for channel lock) */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300419 /* WAS: XREG_FINERFREQ */
420 return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
Davide Ferri8d009a02009-06-23 22:34:06 -0300421}
422
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300423static int xc_get_adc_envelope(struct xc4000_priv *priv, u16 *adc_envelope)
Davide Ferri8d009a02009-06-23 22:34:06 -0300424{
425 return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope);
426}
427
428static int xc_get_frequency_error(struct xc4000_priv *priv, u32 *freq_error_hz)
429{
430 int result;
431 u16 regData;
432 u32 tmp;
433
434 result = xc4000_readreg(priv, XREG_FREQ_ERROR, &regData);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300435 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300436 return result;
437
Istvan Varga1368ceb2011-06-03 12:27:30 -0300438 tmp = (u32)regData & 0xFFFFU;
439 tmp = (tmp < 0x8000U ? tmp : 0x10000U - tmp);
440 (*freq_error_hz) = tmp * 15625;
Davide Ferri8d009a02009-06-23 22:34:06 -0300441 return result;
442}
443
444static int xc_get_lock_status(struct xc4000_priv *priv, u16 *lock_status)
445{
446 return xc4000_readreg(priv, XREG_LOCK, lock_status);
447}
448
449static int xc_get_version(struct xc4000_priv *priv,
450 u8 *hw_majorversion, u8 *hw_minorversion,
451 u8 *fw_majorversion, u8 *fw_minorversion)
452{
453 u16 data;
454 int result;
455
456 result = xc4000_readreg(priv, XREG_VERSION, &data);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300457 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300458 return result;
459
460 (*hw_majorversion) = (data >> 12) & 0x0F;
461 (*hw_minorversion) = (data >> 8) & 0x0F;
462 (*fw_majorversion) = (data >> 4) & 0x0F;
463 (*fw_minorversion) = data & 0x0F;
464
465 return 0;
466}
467
Davide Ferri8d009a02009-06-23 22:34:06 -0300468static int xc_get_hsync_freq(struct xc4000_priv *priv, u32 *hsync_freq_hz)
469{
470 u16 regData;
471 int result;
472
473 result = xc4000_readreg(priv, XREG_HSYNC_FREQ, &regData);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300474 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300475 return result;
476
477 (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
478 return result;
479}
480
481static int xc_get_frame_lines(struct xc4000_priv *priv, u16 *frame_lines)
482{
483 return xc4000_readreg(priv, XREG_FRAME_LINES, frame_lines);
484}
485
486static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
487{
488 return xc4000_readreg(priv, XREG_QUALITY, quality);
489}
490
Miroslav Slugen8a538a82011-12-20 21:18:38 -0300491static int xc_get_signal_level(struct xc4000_priv *priv, u16 *signal)
492{
493 return xc4000_readreg(priv, XREG_SIGNAL_LEVEL, signal);
494}
495
496static int xc_get_noise_level(struct xc4000_priv *priv, u16 *noise)
497{
498 return xc4000_readreg(priv, XREG_NOISE_LEVEL, noise);
499}
500
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300501static u16 xc_wait_for_lock(struct xc4000_priv *priv)
Davide Ferri8d009a02009-06-23 22:34:06 -0300502{
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300503 u16 lock_state = 0;
504 int watchdog_count = 40;
Davide Ferri8d009a02009-06-23 22:34:06 -0300505
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300506 while ((lock_state == 0) && (watchdog_count > 0)) {
507 xc_get_lock_status(priv, &lock_state);
508 if (lock_state != 1) {
509 msleep(5);
510 watchdog_count--;
Davide Ferri8d009a02009-06-23 22:34:06 -0300511 }
512 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300513 return lock_state;
Davide Ferri8d009a02009-06-23 22:34:06 -0300514}
515
Istvan Vargae75873c2011-06-04 12:18:41 -0300516static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz)
Davide Ferri8d009a02009-06-23 22:34:06 -0300517{
Istvan Vargae75873c2011-06-04 12:18:41 -0300518 int found = 1;
519 int result;
Davide Ferri8d009a02009-06-23 22:34:06 -0300520
521 dprintk(1, "%s(%u)\n", __func__, freq_hz);
522
Devin Heitmueller799ed112009-10-04 23:09:18 -0300523 /* Don't complain when the request fails because of i2c stretching */
524 priv->ignore_i2c_write_errors = 1;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300525 result = xc_set_rf_frequency(priv, freq_hz);
Devin Heitmueller799ed112009-10-04 23:09:18 -0300526 priv->ignore_i2c_write_errors = 0;
527
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300528 if (result != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -0300529 return 0;
530
Istvan Vargae75873c2011-06-04 12:18:41 -0300531 /* wait for lock only in analog TV mode */
532 if ((priv->cur_fw.type & (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300533 if (xc_wait_for_lock(priv) != 1)
Istvan Vargae75873c2011-06-04 12:18:41 -0300534 found = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300535 }
536
Istvan Vargaf4312e2f2011-06-04 12:08:29 -0300537 /* Wait for stats to stabilize.
538 * Frame Lines needs two frame times after initial lock
539 * before it is valid.
540 */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300541 msleep(debug ? 100 : 10);
Istvan Vargaf4312e2f2011-06-04 12:08:29 -0300542
543 if (debug)
544 xc_debug_dump(priv);
545
Davide Ferri8d009a02009-06-23 22:34:06 -0300546 return found;
547}
548
549static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val)
550{
551 u8 buf[2] = { reg >> 8, reg & 0xff };
552 u8 bval[2] = { 0, 0 };
553 struct i2c_msg msg[2] = {
554 { .addr = priv->i2c_props.addr,
555 .flags = 0, .buf = &buf[0], .len = 2 },
556 { .addr = priv->i2c_props.addr,
557 .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
558 };
559
560 if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300561 printk(KERN_ERR "xc4000: I2C read failed\n");
Davide Ferri8d009a02009-06-23 22:34:06 -0300562 return -EREMOTEIO;
563 }
564
565 *val = (bval[0] << 8) | bval[1];
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300566 return 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300567}
568
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300569#define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0)
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300570static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
571{
572 if (type & BASE)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300573 printk(KERN_CONT "BASE ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300574 if (type & INIT1)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300575 printk(KERN_CONT "INIT1 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300576 if (type & F8MHZ)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300577 printk(KERN_CONT "F8MHZ ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300578 if (type & MTS)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300579 printk(KERN_CONT "MTS ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300580 if (type & D2620)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300581 printk(KERN_CONT "D2620 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300582 if (type & D2633)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300583 printk(KERN_CONT "D2633 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300584 if (type & DTV6)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300585 printk(KERN_CONT "DTV6 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300586 if (type & QAM)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300587 printk(KERN_CONT "QAM ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300588 if (type & DTV7)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300589 printk(KERN_CONT "DTV7 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300590 if (type & DTV78)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300591 printk(KERN_CONT "DTV78 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300592 if (type & DTV8)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300593 printk(KERN_CONT "DTV8 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300594 if (type & FM)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300595 printk(KERN_CONT "FM ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300596 if (type & INPUT1)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300597 printk(KERN_CONT "INPUT1 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300598 if (type & LCD)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300599 printk(KERN_CONT "LCD ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300600 if (type & NOGD)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300601 printk(KERN_CONT "NOGD ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300602 if (type & MONO)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300603 printk(KERN_CONT "MONO ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300604 if (type & ATSC)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300605 printk(KERN_CONT "ATSC ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300606 if (type & IF)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300607 printk(KERN_CONT "IF ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300608 if (type & LG60)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300609 printk(KERN_CONT "LG60 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300610 if (type & ATI638)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300611 printk(KERN_CONT "ATI638 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300612 if (type & OREN538)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300613 printk(KERN_CONT "OREN538 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300614 if (type & OREN36)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300615 printk(KERN_CONT "OREN36 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300616 if (type & TOYOTA388)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300617 printk(KERN_CONT "TOYOTA388 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300618 if (type & TOYOTA794)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300619 printk(KERN_CONT "TOYOTA794 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300620 if (type & DIBCOM52)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300621 printk(KERN_CONT "DIBCOM52 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300622 if (type & ZARLINK456)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300623 printk(KERN_CONT "ZARLINK456 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300624 if (type & CHINA)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300625 printk(KERN_CONT "CHINA ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300626 if (type & F6MHZ)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300627 printk(KERN_CONT "F6MHZ ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300628 if (type & INPUT2)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300629 printk(KERN_CONT "INPUT2 ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300630 if (type & SCODE)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300631 printk(KERN_CONT "SCODE ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300632 if (type & HAS_IF)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300633 printk(KERN_CONT "HAS_IF_%d ", int_freq);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300634}
635
Devin Heitmueller11091a32009-07-20 00:54:57 -0300636static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
637 v4l2_std_id *id)
638{
639 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Varga3db95702011-06-04 11:52:34 -0300640 int i, best_i = -1;
641 unsigned int best_nr_diffs = 255U;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300642
Devin Heitmueller11091a32009-07-20 00:54:57 -0300643 if (!priv->firm) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300644 printk(KERN_ERR "Error! firmware not loaded\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300645 return -EINVAL;
646 }
647
648 if (((type & ~SCODE) == 0) && (*id == 0))
649 *id = V4L2_STD_PAL;
650
Devin Heitmueller11091a32009-07-20 00:54:57 -0300651 /* Seek for generic video standard match */
652 for (i = 0; i < priv->firm_size; i++) {
Istvan Varga3db95702011-06-04 11:52:34 -0300653 v4l2_std_id id_diff_mask =
654 (priv->firm[i].id ^ (*id)) & (*id);
655 unsigned int type_diff_mask =
656 (priv->firm[i].type ^ type)
657 & (BASE_TYPES | DTV_TYPES | LCD | NOGD | MONO | SCODE);
658 unsigned int nr_diffs;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300659
Istvan Varga3db95702011-06-04 11:52:34 -0300660 if (type_diff_mask
661 & (BASE | INIT1 | FM | DTV6 | DTV7 | DTV78 | DTV8 | SCODE))
Devin Heitmueller11091a32009-07-20 00:54:57 -0300662 continue;
663
Istvan Varga3db95702011-06-04 11:52:34 -0300664 nr_diffs = hweight64(id_diff_mask) + hweight32(type_diff_mask);
665 if (!nr_diffs) /* Supports all the requested standards */
666 goto found;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300667
Istvan Varga3db95702011-06-04 11:52:34 -0300668 if (nr_diffs < best_nr_diffs) {
669 best_nr_diffs = nr_diffs;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300670 best_i = i;
671 }
672 }
673
Istvan Varga3db95702011-06-04 11:52:34 -0300674 /* FIXME: Would make sense to seek for type "hint" match ? */
675 if (best_i < 0) {
676 i = -ENOENT;
677 goto ret;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300678 }
679
Istvan Varga3db95702011-06-04 11:52:34 -0300680 if (best_nr_diffs > 0U) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300681 printk(KERN_WARNING
682 "Selecting best matching firmware (%u bits differ) for "
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300683 "type=(%x), id %016llx:\n",
684 best_nr_diffs, type, (unsigned long long)*id);
Istvan Varga3db95702011-06-04 11:52:34 -0300685 i = best_i;
686 }
Devin Heitmueller11091a32009-07-20 00:54:57 -0300687
688found:
689 *id = priv->firm[i].id;
690
691ret:
Devin Heitmueller11091a32009-07-20 00:54:57 -0300692 if (debug) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300693 printk(KERN_DEBUG "%s firmware for type=",
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300694 (i < 0) ? "Can't find" : "Found");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300695 dump_firm_type(type);
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300696 printk(KERN_DEBUG "(%x), id %016llx.\n", type, (unsigned long long)*id);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300697 }
698 return i;
699}
700
701static int load_firmware(struct dvb_frontend *fe, unsigned int type,
702 v4l2_std_id *id)
703{
704 struct xc4000_priv *priv = fe->tuner_priv;
705 int pos, rc;
Devin Heitmueller31f880e2009-07-20 02:15:31 -0300706 unsigned char *p;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300707
Devin Heitmueller11091a32009-07-20 00:54:57 -0300708 pos = seek_firmware(fe, type, id);
709 if (pos < 0)
710 return pos;
711
Devin Heitmueller11091a32009-07-20 00:54:57 -0300712 p = priv->firm[pos].ptr;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300713
Devin Heitmueller799ed112009-10-04 23:09:18 -0300714 /* Don't complain when the request fails because of i2c stretching */
715 priv->ignore_i2c_write_errors = 1;
716
Devin Heitmueller31f880e2009-07-20 02:15:31 -0300717 rc = xc_load_i2c_sequence(fe, p);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300718
Devin Heitmueller799ed112009-10-04 23:09:18 -0300719 priv->ignore_i2c_write_errors = 0;
720
Devin Heitmueller31f880e2009-07-20 02:15:31 -0300721 return rc;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300722}
723
Davide Ferri8d009a02009-06-23 22:34:06 -0300724static int xc4000_fwupload(struct dvb_frontend *fe)
725{
726 struct xc4000_priv *priv = fe->tuner_priv;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300727 const struct firmware *fw = NULL;
728 const unsigned char *p, *endp;
729 int rc = 0;
730 int n, n_array;
731 char name[33];
Istvan Vargafbe4a292011-06-03 10:11:48 -0300732 const char *fname;
Davide Ferri8d009a02009-06-23 22:34:06 -0300733
Istvan Vargafa285bc2011-06-04 11:48:16 -0300734 if (firmware_name[0] != '\0')
735 fname = firmware_name;
736 else
737 fname = XC4000_DEFAULT_FIRMWARE;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300738
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300739 dprintk(1, "Reading firmware %s\n", fname);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300740 rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
741 if (rc < 0) {
742 if (rc == -ENOENT)
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300743 printk(KERN_ERR "Error: firmware %s not found.\n", fname);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300744 else
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300745 printk(KERN_ERR "Error %d while requesting firmware %s\n",
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300746 rc, fname);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300747
748 return rc;
749 }
750 p = fw->data;
751 endp = p + fw->size;
752
753 if (fw->size < sizeof(name) - 1 + 2 + 2) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300754 printk(KERN_ERR "Error: firmware file %s has invalid size!\n",
755 fname);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300756 goto corrupt;
Davide Ferri8d009a02009-06-23 22:34:06 -0300757 }
758
Devin Heitmueller11091a32009-07-20 00:54:57 -0300759 memcpy(name, p, sizeof(name) - 1);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300760 name[sizeof(name) - 1] = '\0';
Devin Heitmueller11091a32009-07-20 00:54:57 -0300761 p += sizeof(name) - 1;
762
763 priv->firm_version = get_unaligned_le16(p);
764 p += 2;
765
766 n_array = get_unaligned_le16(p);
767 p += 2;
768
Devin Heitmuellerb6cdb5b2009-12-27 18:15:14 -0300769 dprintk(1, "Loading %d firmware images from %s, type: %s, ver %d.%d\n",
770 n_array, fname, name,
771 priv->firm_version >> 8, priv->firm_version & 0xff);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300772
Thomas Meyer1b7acf02011-11-29 17:08:00 -0300773 priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300774 if (priv->firm == NULL) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300775 printk(KERN_ERR "Not enough memory to load firmware file.\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300776 rc = -ENOMEM;
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300777 goto done;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300778 }
779 priv->firm_size = n_array;
780
781 n = -1;
782 while (p < endp) {
783 __u32 type, size;
784 v4l2_std_id id;
785 __u16 int_freq = 0;
786
787 n++;
788 if (n >= n_array) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300789 printk(KERN_ERR "More firmware images in file than "
Istvan Vargafbe4a292011-06-03 10:11:48 -0300790 "were expected!\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300791 goto corrupt;
792 }
793
794 /* Checks if there's enough bytes to read */
795 if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
796 goto header;
797
798 type = get_unaligned_le32(p);
799 p += sizeof(type);
800
801 id = get_unaligned_le64(p);
802 p += sizeof(id);
803
804 if (type & HAS_IF) {
805 int_freq = get_unaligned_le16(p);
806 p += sizeof(int_freq);
807 if (endp - p < sizeof(size))
808 goto header;
809 }
810
811 size = get_unaligned_le32(p);
812 p += sizeof(size);
813
814 if (!size || size > endp - p) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300815 printk(KERN_ERR "Firmware type (%x), id %llx is corrupted (size=%d, expected %d)\n",
Devin Heitmueller11091a32009-07-20 00:54:57 -0300816 type, (unsigned long long)id,
817 (unsigned)(endp - p), size);
818 goto corrupt;
819 }
820
821 priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
822 if (priv->firm[n].ptr == NULL) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300823 printk(KERN_ERR "Not enough memory to load firmware file.\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300824 rc = -ENOMEM;
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300825 goto done;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300826 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300827
Devin Heitmueller11091a32009-07-20 00:54:57 -0300828 if (debug) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300829 printk(KERN_DEBUG "Reading firmware type ");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300830 dump_firm_type_and_int_freq(type, int_freq);
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300831 printk(KERN_DEBUG "(%x), id %llx, size=%d.\n",
Devin Heitmueller11091a32009-07-20 00:54:57 -0300832 type, (unsigned long long)id, size);
833 }
834
835 memcpy(priv->firm[n].ptr, p, size);
836 priv->firm[n].type = type;
837 priv->firm[n].id = id;
838 priv->firm[n].size = size;
839 priv->firm[n].int_freq = int_freq;
840
841 p += size;
Davide Ferri8d009a02009-06-23 22:34:06 -0300842 }
843
Devin Heitmueller11091a32009-07-20 00:54:57 -0300844 if (n + 1 != priv->firm_size) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300845 printk(KERN_ERR "Firmware file is incomplete!\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300846 goto corrupt;
847 }
848
849 goto done;
850
851header:
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300852 printk(KERN_ERR "Firmware header is incomplete!\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300853corrupt:
854 rc = -EINVAL;
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300855 printk(KERN_ERR "Error: firmware file is corrupted!\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300856
857done:
Davide Ferri8d009a02009-06-23 22:34:06 -0300858 release_firmware(fw);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300859 if (rc == 0)
Devin Heitmuellerb6cdb5b2009-12-27 18:15:14 -0300860 dprintk(1, "Firmware files loaded.\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300861
862 return rc;
Davide Ferri8d009a02009-06-23 22:34:06 -0300863}
864
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300865static int load_scode(struct dvb_frontend *fe, unsigned int type,
866 v4l2_std_id *id, __u16 int_freq, int scode)
867{
868 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Vargaffce6262011-06-04 11:56:18 -0300869 int pos, rc;
870 unsigned char *p;
871 u8 scode_buf[13];
872 u8 indirect_mode[5];
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300873
Devin Heitmuellerfe830362009-07-28 00:04:27 -0300874 dprintk(1, "%s called int_freq=%d\n", __func__, int_freq);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300875
876 if (!int_freq) {
877 pos = seek_firmware(fe, type, id);
878 if (pos < 0)
879 return pos;
880 } else {
881 for (pos = 0; pos < priv->firm_size; pos++) {
882 if ((priv->firm[pos].int_freq == int_freq) &&
883 (priv->firm[pos].type & HAS_IF))
884 break;
885 }
886 if (pos == priv->firm_size)
887 return -ENOENT;
888 }
889
890 p = priv->firm[pos].ptr;
891
Istvan Vargaffce6262011-06-04 11:56:18 -0300892 if (priv->firm[pos].size != 12 * 16 || scode >= 16)
893 return -EINVAL;
894 p += 12 * scode;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300895
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300896 if (debug) {
897 tuner_info("Loading SCODE for type=");
898 dump_firm_type_and_int_freq(priv->firm[pos].type,
899 priv->firm[pos].int_freq);
900 printk(KERN_CONT "(%x), id %016llx.\n", priv->firm[pos].type,
901 (unsigned long long)*id);
902 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300903
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300904 scode_buf[0] = 0x00;
905 memcpy(&scode_buf[1], p, 12);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300906
907 /* Enter direct-mode */
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300908 rc = xc_write_reg(priv, XREG_DIRECTSITTING_MODE, 0);
909 if (rc < 0) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300910 printk(KERN_ERR "failed to put device into direct mode!\n");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300911 return -EIO;
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300912 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300913
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300914 rc = xc_send_i2c_data(priv, scode_buf, 13);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300915 if (rc != 0) {
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300916 /* Even if the send failed, make sure we set back to indirect
917 mode */
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300918 printk(KERN_ERR "Failed to set scode %d\n", rc);
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300919 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300920
921 /* Switch back to indirect-mode */
922 memset(indirect_mode, 0, sizeof(indirect_mode));
923 indirect_mode[4] = 0x88;
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300924 xc_send_i2c_data(priv, indirect_mode, sizeof(indirect_mode));
925 msleep(10);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300926
927 return 0;
928}
929
930static int check_firmware(struct dvb_frontend *fe, unsigned int type,
931 v4l2_std_id std, __u16 int_freq)
932{
933 struct xc4000_priv *priv = fe->tuner_priv;
934 struct firmware_properties new_fw;
935 int rc = 0, is_retry = 0;
istvan_v@mailbox.hu09f46342011-06-06 13:00:17 -0300936 u16 hwmodel;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300937 v4l2_std_id std0;
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300938 u8 hw_major, hw_minor, fw_major, fw_minor;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300939
940 dprintk(1, "%s called\n", __func__);
941
942 if (!priv->firm) {
943 rc = xc4000_fwupload(fe);
944 if (rc < 0)
945 return rc;
946 }
947
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300948retry:
949 new_fw.type = type;
950 new_fw.id = std;
951 new_fw.std_req = std;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300952 new_fw.scode_table = SCODE;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300953 new_fw.scode_nr = 0;
954 new_fw.int_freq = int_freq;
955
956 dprintk(1, "checking firmware, user requested type=");
957 if (debug) {
958 dump_firm_type(new_fw.type);
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300959 printk(KERN_CONT "(%x), id %016llx, ", new_fw.type,
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300960 (unsigned long long)new_fw.std_req);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300961 if (!int_freq)
962 printk(KERN_CONT "scode_tbl ");
963 else
964 printk(KERN_CONT "int_freq %d, ", new_fw.int_freq);
965 printk(KERN_CONT "scode_nr %d\n", new_fw.scode_nr);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300966 }
967
968 /* No need to reload base firmware if it matches */
Istvan Varga595a83f2011-06-04 11:59:54 -0300969 if (priv->cur_fw.type & BASE) {
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300970 dprintk(1, "BASE firmware not changed.\n");
971 goto skip_base;
972 }
973
974 /* Updating BASE - forget about all currently loaded firmware */
975 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
976
977 /* Reset is needed before loading firmware */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -0300978 rc = xc4000_tuner_reset(fe);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300979 if (rc < 0)
980 goto fail;
981
982 /* BASE firmwares are all std0 */
983 std0 = 0;
Istvan Varga595a83f2011-06-04 11:59:54 -0300984 rc = load_firmware(fe, BASE, &std0);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300985 if (rc < 0) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -0300986 printk(KERN_ERR "Error %d while loading base firmware\n", rc);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300987 goto fail;
988 }
989
990 /* Load INIT1, if needed */
991 dprintk(1, "Load init1 firmware, if exists\n");
992
Istvan Varga595a83f2011-06-04 11:59:54 -0300993 rc = load_firmware(fe, BASE | INIT1, &std0);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300994 if (rc == -ENOENT)
Istvan Varga595a83f2011-06-04 11:59:54 -0300995 rc = load_firmware(fe, BASE | INIT1, &std0);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300996 if (rc < 0 && rc != -ENOENT) {
997 tuner_err("Error %d while loading init1 firmware\n",
998 rc);
999 goto fail;
1000 }
1001
1002skip_base:
1003 /*
1004 * No need to reload standard specific firmware if base firmware
1005 * was not reloaded and requested video standards have not changed.
1006 */
1007 if (priv->cur_fw.type == (BASE | new_fw.type) &&
1008 priv->cur_fw.std_req == std) {
1009 dprintk(1, "Std-specific firmware already loaded.\n");
1010 goto skip_std_specific;
1011 }
1012
1013 /* Reloading std-specific firmware forces a SCODE update */
1014 priv->cur_fw.scode_table = 0;
1015
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -03001016 /* Load the standard firmware */
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001017 rc = load_firmware(fe, new_fw.type, &new_fw.id);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001018
1019 if (rc < 0)
1020 goto fail;
1021
1022skip_std_specific:
1023 if (priv->cur_fw.scode_table == new_fw.scode_table &&
1024 priv->cur_fw.scode_nr == new_fw.scode_nr) {
1025 dprintk(1, "SCODE firmware already loaded.\n");
1026 goto check_device;
1027 }
1028
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001029 /* Load SCODE firmware, if exists */
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001030 rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
1031 new_fw.int_freq, new_fw.scode_nr);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001032 if (rc != 0)
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -03001033 dprintk(1, "load scode failed %d\n", rc);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001034
1035check_device:
1036 rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel);
1037
Devin Heitmueller799ed112009-10-04 23:09:18 -03001038 if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major,
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001039 &fw_minor) != 0) {
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -03001040 printk(KERN_ERR "Unable to read tuner registers.\n");
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001041 goto fail;
1042 }
1043
1044 dprintk(1, "Device is Xceive %d version %d.%d, "
1045 "firmware version %d.%d\n",
1046 hwmodel, hw_major, hw_minor, fw_major, fw_minor);
1047
1048 /* Check firmware version against what we downloaded. */
istvan_v@mailbox.hu09f46342011-06-06 13:00:17 -03001049 if (priv->firm_version != ((fw_major << 8) | fw_minor)) {
1050 printk(KERN_WARNING
1051 "Incorrect readback of firmware version %d.%d.\n",
1052 fw_major, fw_minor);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001053 goto fail;
1054 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001055
1056 /* Check that the tuner hardware model remains consistent over time. */
Istvan Varga7db98fe2011-06-04 12:25:19 -03001057 if (priv->hwmodel == 0 &&
1058 (hwmodel == XC_PRODUCT_ID_XC4000 ||
1059 hwmodel == XC_PRODUCT_ID_XC4100)) {
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001060 priv->hwmodel = hwmodel;
istvan_v@mailbox.hu09f46342011-06-06 13:00:17 -03001061 priv->hwvers = (hw_major << 8) | hw_minor;
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001062 } else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
istvan_v@mailbox.hu09f46342011-06-06 13:00:17 -03001063 priv->hwvers != ((hw_major << 8) | hw_minor)) {
1064 printk(KERN_WARNING
1065 "Read invalid device hardware information - tuner "
Istvan Vargafbe4a292011-06-03 10:11:48 -03001066 "hung?\n");
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001067 goto fail;
1068 }
1069
1070 memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
1071
1072 /*
1073 * By setting BASE in cur_fw.type only after successfully loading all
1074 * firmwares, we can:
1075 * 1. Identify that BASE firmware with type=0 has been loaded;
1076 * 2. Tell whether BASE firmware was just changed the next time through.
1077 */
1078 priv->cur_fw.type |= BASE;
1079
1080 return 0;
1081
1082fail:
1083 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
1084 if (!is_retry) {
1085 msleep(50);
1086 is_retry = 1;
1087 dprintk(1, "Retrying firmware load\n");
1088 goto retry;
1089 }
1090
1091 if (rc == -ENOENT)
1092 rc = -EINVAL;
1093 return rc;
1094}
Devin Heitmueller11091a32009-07-20 00:54:57 -03001095
Davide Ferri8d009a02009-06-23 22:34:06 -03001096static void xc_debug_dump(struct xc4000_priv *priv)
1097{
Istvan Vargafbe4a292011-06-03 10:11:48 -03001098 u16 adc_envelope;
1099 u32 freq_error_hz = 0;
1100 u16 lock_status;
1101 u32 hsync_freq_hz = 0;
1102 u16 frame_lines;
1103 u16 quality;
Miroslav Slugen8a538a82011-12-20 21:18:38 -03001104 u16 signal = 0;
1105 u16 noise = 0;
Istvan Vargafbe4a292011-06-03 10:11:48 -03001106 u8 hw_majorversion = 0, hw_minorversion = 0;
1107 u8 fw_majorversion = 0, fw_minorversion = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -03001108
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001109 xc_get_adc_envelope(priv, &adc_envelope);
Davide Ferri8d009a02009-06-23 22:34:06 -03001110 dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
1111
1112 xc_get_frequency_error(priv, &freq_error_hz);
1113 dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
1114
Istvan Vargafbe4a292011-06-03 10:11:48 -03001115 xc_get_lock_status(priv, &lock_status);
Davide Ferri8d009a02009-06-23 22:34:06 -03001116 dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
1117 lock_status);
1118
Istvan Vargafbe4a292011-06-03 10:11:48 -03001119 xc_get_version(priv, &hw_majorversion, &hw_minorversion,
1120 &fw_majorversion, &fw_minorversion);
Davide Ferri8d009a02009-06-23 22:34:06 -03001121 dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
1122 hw_majorversion, hw_minorversion,
1123 fw_majorversion, fw_minorversion);
1124
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001125 if (priv->video_standard < XC4000_DTV6) {
1126 xc_get_hsync_freq(priv, &hsync_freq_hz);
1127 dprintk(1, "*** Horizontal sync frequency = %d Hz\n",
1128 hsync_freq_hz);
Davide Ferri8d009a02009-06-23 22:34:06 -03001129
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001130 xc_get_frame_lines(priv, &frame_lines);
1131 dprintk(1, "*** Frame lines = %d\n", frame_lines);
1132 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001133
Istvan Vargafbe4a292011-06-03 10:11:48 -03001134 xc_get_quality(priv, &quality);
Davide Ferri8d009a02009-06-23 22:34:06 -03001135 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
Miroslav Slugen8a538a82011-12-20 21:18:38 -03001136
1137 xc_get_signal_level(priv, &signal);
1138 dprintk(1, "*** Signal level = -%ddB (%d)\n", signal >> 8, signal);
1139
1140 xc_get_noise_level(priv, &noise);
1141 dprintk(1, "*** Noise level = %ddB (%d)\n", noise >> 8, noise);
Davide Ferri8d009a02009-06-23 22:34:06 -03001142}
1143
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001144static int xc4000_set_params(struct dvb_frontend *fe)
Davide Ferri8d009a02009-06-23 22:34:06 -03001145{
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001146 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1147 u32 delsys = c->delivery_system;
1148 u32 bw = c->bandwidth_hz;
Davide Ferri8d009a02009-06-23 22:34:06 -03001149 struct xc4000_priv *priv = fe->tuner_priv;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001150 unsigned int type;
Istvan Varga56149422011-06-03 12:23:33 -03001151 int ret = -EREMOTEIO;
Davide Ferri8d009a02009-06-23 22:34:06 -03001152
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001153 dprintk(1, "%s() frequency=%d (Hz)\n", __func__, c->frequency);
Davide Ferri8d009a02009-06-23 22:34:06 -03001154
Istvan Varga56149422011-06-03 12:23:33 -03001155 mutex_lock(&priv->lock);
1156
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001157 switch (delsys) {
1158 case SYS_ATSC:
1159 dprintk(1, "%s() VSB modulation\n", __func__);
1160 priv->rf_mode = XC_RF_MODE_AIR;
1161 priv->freq_hz = c->frequency - 1750000;
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001162 priv->video_standard = XC4000_DTV6;
1163 type = DTV6;
1164 break;
1165 case SYS_DVBC_ANNEX_B:
1166 dprintk(1, "%s() QAM modulation\n", __func__);
1167 priv->rf_mode = XC_RF_MODE_CABLE;
1168 priv->freq_hz = c->frequency - 1750000;
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001169 priv->video_standard = XC4000_DTV6;
1170 type = DTV6;
1171 break;
1172 case SYS_DVBT:
1173 case SYS_DVBT2:
Davide Ferri8d009a02009-06-23 22:34:06 -03001174 dprintk(1, "%s() OFDM\n", __func__);
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001175 if (bw == 0) {
1176 if (c->frequency < 400000000) {
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001177 priv->freq_hz = c->frequency - 2250000;
Istvan Vargaf0ef7c82011-06-03 12:17:59 -03001178 } else {
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001179 priv->freq_hz = c->frequency - 2750000;
Istvan Vargaf0ef7c82011-06-03 12:17:59 -03001180 }
1181 priv->video_standard = XC4000_DTV7_8;
1182 type = DTV78;
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001183 } else if (bw <= 6000000) {
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001184 priv->video_standard = XC4000_DTV6;
1185 priv->freq_hz = c->frequency - 1750000;
1186 type = DTV6;
1187 } else if (bw <= 7000000) {
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001188 priv->video_standard = XC4000_DTV7;
1189 priv->freq_hz = c->frequency - 2250000;
1190 type = DTV7;
1191 } else {
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001192 priv->video_standard = XC4000_DTV8;
1193 priv->freq_hz = c->frequency - 2750000;
1194 type = DTV8;
Davide Ferri8d009a02009-06-23 22:34:06 -03001195 }
1196 priv->rf_mode = XC_RF_MODE_AIR;
Mauro Carvalho Chehab40d6f2b2011-12-21 09:02:55 -03001197 break;
1198 default:
1199 printk(KERN_ERR "xc4000 delivery system not supported!\n");
Istvan Varga56149422011-06-03 12:23:33 -03001200 ret = -EINVAL;
1201 goto fail;
Davide Ferri8d009a02009-06-23 22:34:06 -03001202 }
1203
1204 dprintk(1, "%s() frequency=%d (compensated)\n",
1205 __func__, priv->freq_hz);
1206
Devin Heitmuellered23db32009-10-05 01:27:14 -03001207 /* Make sure the correct firmware type is loaded */
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001208 if (check_firmware(fe, type, 0, priv->if_khz) != 0)
Istvan Varga56149422011-06-03 12:23:33 -03001209 goto fail;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001210
Mauro Carvalho Chehabc6f56e72011-12-26 20:02:28 -03001211 priv->bandwidth = c->bandwidth_hz;
1212
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001213 ret = xc_set_signal_source(priv, priv->rf_mode);
1214 if (ret != 0) {
1215 printk(KERN_ERR "xc4000: xc_set_signal_source(%d) failed\n",
Istvan Varga56149422011-06-03 12:23:33 -03001216 priv->rf_mode);
1217 goto fail;
Istvan Varga30f544e2011-06-04 12:12:42 -03001218 } else {
1219 u16 video_mode, audio_mode;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001220 video_mode = xc4000_standard[priv->video_standard].video_mode;
1221 audio_mode = xc4000_standard[priv->video_standard].audio_mode;
Istvan Varga30f544e2011-06-04 12:12:42 -03001222 if (type == DTV6 && priv->firm_version != 0x0102)
1223 video_mode |= 0x0001;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001224 ret = xc_set_tv_standard(priv, video_mode, audio_mode);
1225 if (ret != 0) {
1226 printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n");
Istvan Varga30f544e2011-06-04 12:12:42 -03001227 /* DJH - do not return when it fails... */
1228 /* goto fail; */
1229 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001230 }
1231
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001232 if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
1233 ret = 0;
1234 if (priv->dvb_amplitude != 0) {
Istvan Varga30f544e2011-06-04 12:12:42 -03001235 if (xc_write_reg(priv, XREG_AMPLITUDE,
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001236 (priv->firm_version != 0x0102 ||
1237 priv->dvb_amplitude != 134 ?
1238 priv->dvb_amplitude : 132)) != 0)
Istvan Varga30f544e2011-06-04 12:12:42 -03001239 ret = -EREMOTEIO;
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001240 }
1241 if (priv->set_smoothedcvbs != 0) {
Istvan Varga30f544e2011-06-04 12:12:42 -03001242 if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
1243 ret = -EREMOTEIO;
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001244 }
1245 if (ret != 0) {
1246 printk(KERN_ERR "xc4000: setting registers failed\n");
1247 /* goto fail; */
Davide Ferri8d009a02009-06-23 22:34:06 -03001248 }
Istvan Varga30f544e2011-06-04 12:12:42 -03001249
Istvan Vargae75873c2011-06-04 12:18:41 -03001250 xc_tune_channel(priv, priv->freq_hz);
Davide Ferri8d009a02009-06-23 22:34:06 -03001251
Istvan Varga56149422011-06-03 12:23:33 -03001252 ret = 0;
1253
1254fail:
1255 mutex_unlock(&priv->lock);
1256
1257 return ret;
Davide Ferri8d009a02009-06-23 22:34:06 -03001258}
1259
Davide Ferri8d009a02009-06-23 22:34:06 -03001260static int xc4000_set_analog_params(struct dvb_frontend *fe,
1261 struct analog_parameters *params)
1262{
1263 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Varga818a1772011-06-04 12:17:22 -03001264 unsigned int type = 0;
Istvan Varga56149422011-06-03 12:23:33 -03001265 int ret = -EREMOTEIO;
Davide Ferri8d009a02009-06-23 22:34:06 -03001266
Istvan Varga818a1772011-06-04 12:17:22 -03001267 if (params->mode == V4L2_TUNER_RADIO) {
1268 dprintk(1, "%s() frequency=%d (in units of 62.5Hz)\n",
1269 __func__, params->frequency);
1270
1271 mutex_lock(&priv->lock);
1272
1273 params->std = 0;
1274 priv->freq_hz = params->frequency * 125L / 2;
1275
1276 if (audio_std & XC4000_AUDIO_STD_INPUT1) {
1277 priv->video_standard = XC4000_FM_Radio_INPUT1;
1278 type = FM | INPUT1;
1279 } else {
1280 priv->video_standard = XC4000_FM_Radio_INPUT2;
1281 type = FM | INPUT2;
1282 }
1283
1284 goto tune_channel;
1285 }
1286
Davide Ferri8d009a02009-06-23 22:34:06 -03001287 dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
1288 __func__, params->frequency);
1289
Istvan Varga56149422011-06-03 12:23:33 -03001290 mutex_lock(&priv->lock);
1291
Davide Ferri8d009a02009-06-23 22:34:06 -03001292 /* params->frequency is in units of 62.5khz */
1293 priv->freq_hz = params->frequency * 62500;
1294
Istvan Varga818a1772011-06-04 12:17:22 -03001295 params->std &= V4L2_STD_ALL;
1296 /* if std is not defined, choose one */
1297 if (!params->std)
1298 params->std = V4L2_STD_PAL_BG;
1299
1300 if (audio_std & XC4000_AUDIO_STD_MONO)
1301 type = MONO;
1302
Davide Ferri8d009a02009-06-23 22:34:06 -03001303 if (params->std & V4L2_STD_MN) {
Istvan Varga818a1772011-06-04 12:17:22 -03001304 params->std = V4L2_STD_MN;
1305 if (audio_std & XC4000_AUDIO_STD_MONO) {
1306 priv->video_standard = XC4000_MN_NTSC_PAL_Mono;
1307 } else if (audio_std & XC4000_AUDIO_STD_A2) {
1308 params->std |= V4L2_STD_A2;
1309 priv->video_standard = XC4000_MN_NTSC_PAL_A2;
1310 } else {
1311 params->std |= V4L2_STD_BTSC;
1312 priv->video_standard = XC4000_MN_NTSC_PAL_BTSC;
1313 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001314 goto tune_channel;
1315 }
1316
1317 if (params->std & V4L2_STD_PAL_BG) {
Istvan Varga818a1772011-06-04 12:17:22 -03001318 params->std = V4L2_STD_PAL_BG;
1319 if (audio_std & XC4000_AUDIO_STD_MONO) {
1320 priv->video_standard = XC4000_BG_PAL_MONO;
1321 } else if (!(audio_std & XC4000_AUDIO_STD_A2)) {
1322 if (!(audio_std & XC4000_AUDIO_STD_B)) {
1323 params->std |= V4L2_STD_NICAM_A;
1324 priv->video_standard = XC4000_BG_PAL_NICAM;
1325 } else {
1326 params->std |= V4L2_STD_NICAM_B;
1327 priv->video_standard = XC4000_BG_PAL_NICAM;
1328 }
1329 } else {
1330 if (!(audio_std & XC4000_AUDIO_STD_B)) {
1331 params->std |= V4L2_STD_A2_A;
1332 priv->video_standard = XC4000_BG_PAL_A2;
1333 } else {
1334 params->std |= V4L2_STD_A2_B;
1335 priv->video_standard = XC4000_BG_PAL_A2;
1336 }
1337 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001338 goto tune_channel;
1339 }
1340
1341 if (params->std & V4L2_STD_PAL_I) {
1342 /* default to NICAM audio standard */
Istvan Varga818a1772011-06-04 12:17:22 -03001343 params->std = V4L2_STD_PAL_I | V4L2_STD_NICAM;
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -03001344 if (audio_std & XC4000_AUDIO_STD_MONO)
Istvan Varga818a1772011-06-04 12:17:22 -03001345 priv->video_standard = XC4000_I_PAL_NICAM_MONO;
Mauro Carvalho Chehab941830c2011-06-06 16:51:11 -03001346 else
Istvan Varga818a1772011-06-04 12:17:22 -03001347 priv->video_standard = XC4000_I_PAL_NICAM;
Davide Ferri8d009a02009-06-23 22:34:06 -03001348 goto tune_channel;
1349 }
1350
1351 if (params->std & V4L2_STD_PAL_DK) {
Istvan Varga818a1772011-06-04 12:17:22 -03001352 params->std = V4L2_STD_PAL_DK;
1353 if (audio_std & XC4000_AUDIO_STD_MONO) {
1354 priv->video_standard = XC4000_DK_PAL_MONO;
1355 } else if (audio_std & XC4000_AUDIO_STD_A2) {
1356 params->std |= V4L2_STD_A2;
1357 priv->video_standard = XC4000_DK_PAL_A2;
1358 } else {
1359 params->std |= V4L2_STD_NICAM;
1360 priv->video_standard = XC4000_DK_PAL_NICAM;
1361 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001362 goto tune_channel;
1363 }
1364
1365 if (params->std & V4L2_STD_SECAM_DK) {
Istvan Varga818a1772011-06-04 12:17:22 -03001366 /* default to A2 audio standard */
1367 params->std = V4L2_STD_SECAM_DK | V4L2_STD_A2;
1368 if (audio_std & XC4000_AUDIO_STD_L) {
1369 type = 0;
1370 priv->video_standard = XC4000_DK_SECAM_NICAM;
1371 } else if (audio_std & XC4000_AUDIO_STD_MONO) {
1372 priv->video_standard = XC4000_DK_SECAM_A2MONO;
1373 } else if (audio_std & XC4000_AUDIO_STD_K3) {
1374 params->std |= V4L2_STD_SECAM_K3;
1375 priv->video_standard = XC4000_DK_SECAM_A2LDK3;
1376 } else {
1377 priv->video_standard = XC4000_DK_SECAM_A2DK1;
1378 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001379 goto tune_channel;
1380 }
1381
1382 if (params->std & V4L2_STD_SECAM_L) {
Istvan Varga818a1772011-06-04 12:17:22 -03001383 /* default to NICAM audio standard */
1384 type = 0;
1385 params->std = V4L2_STD_SECAM_L | V4L2_STD_NICAM;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001386 priv->video_standard = XC4000_L_SECAM_NICAM;
Davide Ferri8d009a02009-06-23 22:34:06 -03001387 goto tune_channel;
1388 }
1389
1390 if (params->std & V4L2_STD_SECAM_LC) {
Istvan Varga818a1772011-06-04 12:17:22 -03001391 /* default to NICAM audio standard */
1392 type = 0;
1393 params->std = V4L2_STD_SECAM_LC | V4L2_STD_NICAM;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001394 priv->video_standard = XC4000_LC_SECAM_NICAM;
Davide Ferri8d009a02009-06-23 22:34:06 -03001395 goto tune_channel;
1396 }
1397
1398tune_channel:
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001399 /* FIXME: it could be air. */
Istvan Varga818a1772011-06-04 12:17:22 -03001400 priv->rf_mode = XC_RF_MODE_CABLE;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001401
Istvan Varga818a1772011-06-04 12:17:22 -03001402 if (check_firmware(fe, type, params->std,
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001403 xc4000_standard[priv->video_standard].int_freq) != 0)
Istvan Varga56149422011-06-03 12:23:33 -03001404 goto fail;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001405
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001406 ret = xc_set_signal_source(priv, priv->rf_mode);
1407 if (ret != 0) {
Davide Ferri8d009a02009-06-23 22:34:06 -03001408 printk(KERN_ERR
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001409 "xc4000: xc_set_signal_source(%d) failed\n",
Istvan Varga56149422011-06-03 12:23:33 -03001410 priv->rf_mode);
1411 goto fail;
Istvan Varga30f544e2011-06-04 12:12:42 -03001412 } else {
1413 u16 video_mode, audio_mode;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001414 video_mode = xc4000_standard[priv->video_standard].video_mode;
1415 audio_mode = xc4000_standard[priv->video_standard].audio_mode;
Istvan Varga30f544e2011-06-04 12:12:42 -03001416 if (priv->video_standard < XC4000_BG_PAL_A2) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001417 if (type & NOGD)
Istvan Varga30f544e2011-06-04 12:12:42 -03001418 video_mode &= 0xFF7F;
1419 } else if (priv->video_standard < XC4000_I_PAL_NICAM) {
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001420 if (priv->firm_version == 0x0102)
Istvan Varga30f544e2011-06-04 12:12:42 -03001421 video_mode &= 0xFEFF;
Istvan Varga923137a2011-06-04 12:15:51 -03001422 if (audio_std & XC4000_AUDIO_STD_B)
1423 video_mode |= 0x0080;
Istvan Varga30f544e2011-06-04 12:12:42 -03001424 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001425 ret = xc_set_tv_standard(priv, video_mode, audio_mode);
1426 if (ret != 0) {
1427 printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n");
Istvan Varga30f544e2011-06-04 12:12:42 -03001428 goto fail;
1429 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001430 }
1431
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001432 if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
1433 ret = 0;
1434 if (xc_write_reg(priv, XREG_AMPLITUDE, 1) != 0)
1435 ret = -EREMOTEIO;
1436 if (priv->set_smoothedcvbs != 0) {
Istvan Varga30f544e2011-06-04 12:12:42 -03001437 if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
1438 ret = -EREMOTEIO;
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001439 }
1440 if (ret != 0) {
1441 printk(KERN_ERR "xc4000: setting registers failed\n");
1442 goto fail;
Davide Ferri8d009a02009-06-23 22:34:06 -03001443 }
1444
Istvan Vargae75873c2011-06-04 12:18:41 -03001445 xc_tune_channel(priv, priv->freq_hz);
Davide Ferri8d009a02009-06-23 22:34:06 -03001446
Istvan Varga56149422011-06-03 12:23:33 -03001447 ret = 0;
1448
1449fail:
1450 mutex_unlock(&priv->lock);
1451
1452 return ret;
Davide Ferri8d009a02009-06-23 22:34:06 -03001453}
1454
Miroslav Slugen8a538a82011-12-20 21:18:38 -03001455static int xc4000_get_signal(struct dvb_frontend *fe, u16 *strength)
1456{
1457 struct xc4000_priv *priv = fe->tuner_priv;
1458 u16 value = 0;
1459 int rc;
1460
1461 mutex_lock(&priv->lock);
1462 rc = xc4000_readreg(priv, XREG_SIGNAL_LEVEL, &value);
1463 mutex_unlock(&priv->lock);
1464
1465 if (rc < 0)
1466 goto ret;
1467
1468 /* Informations from real testing of DVB-T and radio part,
1469 coeficient for one dB is 0xff.
1470 */
1471 tuner_dbg("Signal strength: -%ddB (%05d)\n", value >> 8, value);
1472
1473 /* all known digital modes */
1474 if ((priv->video_standard == XC4000_DTV6) ||
1475 (priv->video_standard == XC4000_DTV7) ||
1476 (priv->video_standard == XC4000_DTV7_8) ||
1477 (priv->video_standard == XC4000_DTV8))
1478 goto digital;
1479
1480 /* Analog mode has NOISE LEVEL important, signal
1481 depends only on gain of antenna and amplifiers,
1482 but it doesn't tell anything about real quality
1483 of reception.
1484 */
1485 mutex_lock(&priv->lock);
1486 rc = xc4000_readreg(priv, XREG_NOISE_LEVEL, &value);
1487 mutex_unlock(&priv->lock);
1488
1489 tuner_dbg("Noise level: %ddB (%05d)\n", value >> 8, value);
1490
1491 /* highest noise level: 32dB */
1492 if (value >= 0x2000) {
1493 value = 0;
1494 } else {
1495 value = ~value << 3;
1496 }
1497
1498 goto ret;
1499
1500 /* Digital mode has SIGNAL LEVEL important and real
1501 noise level is stored in demodulator registers.
1502 */
1503digital:
1504 /* best signal: -50dB */
1505 if (value <= 0x3200) {
1506 value = 0xffff;
1507 /* minimum: -114dB - should be 0x7200 but real zero is 0x713A */
1508 } else if (value >= 0x713A) {
1509 value = 0;
1510 } else {
1511 value = ~(value - 0x3200) << 2;
1512 }
1513
1514ret:
1515 *strength = value;
1516
1517 return rc;
1518}
1519
Davide Ferri8d009a02009-06-23 22:34:06 -03001520static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
1521{
1522 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001523
Davide Ferri8d009a02009-06-23 22:34:06 -03001524 *freq = priv->freq_hz;
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001525
1526 if (debug) {
1527 mutex_lock(&priv->lock);
1528 if ((priv->cur_fw.type
1529 & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
1530 u16 snr = 0;
1531 if (xc4000_readreg(priv, XREG_SNR, &snr) == 0) {
1532 mutex_unlock(&priv->lock);
1533 dprintk(1, "%s() freq = %u, SNR = %d\n",
1534 __func__, *freq, snr);
1535 return 0;
1536 }
1537 }
1538 mutex_unlock(&priv->lock);
1539 }
1540
1541 dprintk(1, "%s()\n", __func__);
1542
Davide Ferri8d009a02009-06-23 22:34:06 -03001543 return 0;
1544}
1545
1546static int xc4000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
1547{
1548 struct xc4000_priv *priv = fe->tuner_priv;
1549 dprintk(1, "%s()\n", __func__);
1550
1551 *bw = priv->bandwidth;
1552 return 0;
1553}
1554
1555static int xc4000_get_status(struct dvb_frontend *fe, u32 *status)
1556{
1557 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Vargafbe4a292011-06-03 10:11:48 -03001558 u16 lock_status = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -03001559
Istvan Varga56149422011-06-03 12:23:33 -03001560 mutex_lock(&priv->lock);
1561
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001562 if (priv->cur_fw.type & BASE)
1563 xc_get_lock_status(priv, &lock_status);
1564
1565 *status = (lock_status == 1 ?
1566 TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO : 0);
1567 if (priv->cur_fw.type & (DTV6 | DTV7 | DTV78 | DTV8))
1568 *status &= (~TUNER_STATUS_STEREO);
Davide Ferri8d009a02009-06-23 22:34:06 -03001569
Istvan Varga56149422011-06-03 12:23:33 -03001570 mutex_unlock(&priv->lock);
1571
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001572 dprintk(2, "%s() lock_status = %d\n", __func__, lock_status);
Davide Ferri8d009a02009-06-23 22:34:06 -03001573
1574 return 0;
1575}
1576
Davide Ferri8d009a02009-06-23 22:34:06 -03001577static int xc4000_sleep(struct dvb_frontend *fe)
1578{
Istvan Varga5272f6b2011-06-04 12:03:03 -03001579 struct xc4000_priv *priv = fe->tuner_priv;
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001580 int ret = 0;
Istvan Varga5272f6b2011-06-04 12:03:03 -03001581
1582 dprintk(1, "%s()\n", __func__);
1583
1584 mutex_lock(&priv->lock);
1585
1586 /* Avoid firmware reload on slow devices */
1587 if ((no_poweroff == 2 ||
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001588 (no_poweroff == 0 && priv->default_pm != 0)) &&
Istvan Varga5272f6b2011-06-04 12:03:03 -03001589 (priv->cur_fw.type & BASE) != 0) {
1590 /* force reset and firmware reload */
1591 priv->cur_fw.type = XC_POWERED_DOWN;
1592
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001593 if (xc_write_reg(priv, XREG_POWER_DOWN, 0) != 0) {
Istvan Varga5272f6b2011-06-04 12:03:03 -03001594 printk(KERN_ERR
1595 "xc4000: %s() unable to shutdown tuner\n",
1596 __func__);
1597 ret = -EREMOTEIO;
1598 }
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001599 msleep(20);
Istvan Varga5272f6b2011-06-04 12:03:03 -03001600 }
1601
1602 mutex_unlock(&priv->lock);
1603
1604 return ret;
Davide Ferri8d009a02009-06-23 22:34:06 -03001605}
1606
1607static int xc4000_init(struct dvb_frontend *fe)
1608{
Davide Ferri8d009a02009-06-23 22:34:06 -03001609 dprintk(1, "%s()\n", __func__);
1610
Davide Ferri8d009a02009-06-23 22:34:06 -03001611 return 0;
1612}
1613
1614static int xc4000_release(struct dvb_frontend *fe)
1615{
1616 struct xc4000_priv *priv = fe->tuner_priv;
1617
1618 dprintk(1, "%s()\n", __func__);
1619
1620 mutex_lock(&xc4000_list_mutex);
1621
1622 if (priv)
1623 hybrid_tuner_release_state(priv);
1624
1625 mutex_unlock(&xc4000_list_mutex);
1626
1627 fe->tuner_priv = NULL;
1628
1629 return 0;
1630}
1631
1632static const struct dvb_tuner_ops xc4000_tuner_ops = {
1633 .info = {
1634 .name = "Xceive XC4000",
1635 .frequency_min = 1000000,
1636 .frequency_max = 1023000000,
1637 .frequency_step = 50000,
1638 },
1639
1640 .release = xc4000_release,
1641 .init = xc4000_init,
1642 .sleep = xc4000_sleep,
1643
1644 .set_params = xc4000_set_params,
1645 .set_analog_params = xc4000_set_analog_params,
1646 .get_frequency = xc4000_get_frequency,
Miroslav Slugen8a538a82011-12-20 21:18:38 -03001647 .get_rf_strength = xc4000_get_signal,
Davide Ferri8d009a02009-06-23 22:34:06 -03001648 .get_bandwidth = xc4000_get_bandwidth,
1649 .get_status = xc4000_get_status
1650};
1651
1652struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
1653 struct i2c_adapter *i2c,
1654 struct xc4000_config *cfg)
1655{
1656 struct xc4000_priv *priv = NULL;
Istvan Vargafbe4a292011-06-03 10:11:48 -03001657 int instance;
1658 u16 id = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -03001659
1660 dprintk(1, "%s(%d-%04x)\n", __func__,
1661 i2c ? i2c_adapter_id(i2c) : -1,
1662 cfg ? cfg->i2c_address : -1);
1663
1664 mutex_lock(&xc4000_list_mutex);
1665
1666 instance = hybrid_tuner_request_state(struct xc4000_priv, priv,
1667 hybrid_tuner_instance_list,
1668 i2c, cfg->i2c_address, "xc4000");
1669 switch (instance) {
1670 case 0:
1671 goto fail;
1672 break;
1673 case 1:
1674 /* new tuner instance */
Mauro Carvalho Chehabc6f56e72011-12-26 20:02:28 -03001675 priv->bandwidth = 6000000;
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001676 /* set default configuration */
1677 priv->if_khz = 4560;
1678 priv->default_pm = 0;
1679 priv->dvb_amplitude = 134;
1680 priv->set_smoothedcvbs = 1;
Istvan Varga56149422011-06-03 12:23:33 -03001681 mutex_init(&priv->lock);
Davide Ferri8d009a02009-06-23 22:34:06 -03001682 fe->tuner_priv = priv;
1683 break;
1684 default:
1685 /* existing tuner instance */
1686 fe->tuner_priv = priv;
1687 break;
1688 }
1689
Istvan Varga0b402132011-06-03 09:38:04 -03001690 if (cfg->if_khz != 0) {
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001691 /* copy configuration if provided by the caller */
Davide Ferri8d009a02009-06-23 22:34:06 -03001692 priv->if_khz = cfg->if_khz;
istvan_v@mailbox.hu8edeb6e2011-06-06 13:03:44 -03001693 priv->default_pm = cfg->default_pm;
1694 priv->dvb_amplitude = cfg->dvb_amplitude;
1695 priv->set_smoothedcvbs = cfg->set_smoothedcvbs;
Davide Ferri8d009a02009-06-23 22:34:06 -03001696 }
1697
1698 /* Check if firmware has been loaded. It is possible that another
1699 instance of the driver has loaded the firmware.
1700 */
1701
Istvan Varga027fd362011-06-04 12:04:51 -03001702 if (instance == 1) {
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001703 if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
Davide Ferri8d009a02009-06-23 22:34:06 -03001704 goto fail;
Istvan Varga027fd362011-06-04 12:04:51 -03001705 } else {
1706 id = ((priv->cur_fw.type & BASE) != 0 ?
1707 priv->hwmodel : XC_PRODUCT_ID_FW_NOT_LOADED);
1708 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001709
1710 switch (id) {
Istvan Varga7db98fe2011-06-04 12:25:19 -03001711 case XC_PRODUCT_ID_XC4000:
1712 case XC_PRODUCT_ID_XC4100:
Davide Ferri8d009a02009-06-23 22:34:06 -03001713 printk(KERN_INFO
1714 "xc4000: Successfully identified at address 0x%02x\n",
1715 cfg->i2c_address);
1716 printk(KERN_INFO
1717 "xc4000: Firmware has been loaded previously\n");
1718 break;
1719 case XC_PRODUCT_ID_FW_NOT_LOADED:
1720 printk(KERN_INFO
1721 "xc4000: Successfully identified at address 0x%02x\n",
1722 cfg->i2c_address);
1723 printk(KERN_INFO
1724 "xc4000: Firmware has not been loaded previously\n");
1725 break;
1726 default:
1727 printk(KERN_ERR
1728 "xc4000: Device not found at addr 0x%02x (0x%x)\n",
1729 cfg->i2c_address, id);
1730 goto fail;
1731 }
1732
1733 mutex_unlock(&xc4000_list_mutex);
1734
1735 memcpy(&fe->ops.tuner_ops, &xc4000_tuner_ops,
1736 sizeof(struct dvb_tuner_ops));
1737
Istvan Varga027fd362011-06-04 12:04:51 -03001738 if (instance == 1) {
1739 int ret;
1740 mutex_lock(&priv->lock);
1741 ret = xc4000_fwupload(fe);
1742 mutex_unlock(&priv->lock);
istvan_v@mailbox.hu341747b2011-06-06 12:54:54 -03001743 if (ret != 0)
Istvan Varga027fd362011-06-04 12:04:51 -03001744 goto fail2;
1745 }
Devin Heitmueller11091a32009-07-20 00:54:57 -03001746
Davide Ferri8d009a02009-06-23 22:34:06 -03001747 return fe;
1748fail:
1749 mutex_unlock(&xc4000_list_mutex);
Istvan Varga027fd362011-06-04 12:04:51 -03001750fail2:
Davide Ferri8d009a02009-06-23 22:34:06 -03001751 xc4000_release(fe);
1752 return NULL;
1753}
1754EXPORT_SYMBOL(xc4000_attach);
1755
1756MODULE_AUTHOR("Steven Toth, Davide Ferri");
1757MODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver");
1758MODULE_LICENSE("GPL");