blob: c3e564e9f8ca467dccfe6232fb03ff41dce1da8c [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>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 *
18 * 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 Vargaf4312e2f2011-06-04 12:08:29 -030042MODULE_PARM_DESC(debug, "\n\t\tDebugging 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 Varga5272f6b2011-06-04 12:03:03 -030046MODULE_PARM_DESC(no_poweroff, "\n\t\t1: keep device energized and with tuner "
47 "ready all the times.\n"
48 "\t\tFaster, but consumes more power and keeps the device hotter.\n"
49 "\t\t2: powers device off when not used.\n"
50 "\t\t0 (default): use device-specific default mode.");
Davide Ferri8d009a02009-06-23 22:34:06 -030051
Istvan Varga923137a2011-06-04 12:15:51 -030052#define XC4000_AUDIO_STD_B 1
53#define XC4000_AUDIO_STD_A2 2
54#define XC4000_AUDIO_STD_K3 4
55#define XC4000_AUDIO_STD_L 8
56#define XC4000_AUDIO_STD_INPUT1 16
57#define XC4000_AUDIO_STD_MONO 32
58
59static int audio_std;
60module_param(audio_std, int, 0644);
61MODULE_PARM_DESC(audio_std, "\n\t\tAudio standard. XC4000 audio decoder "
62 "explicitly needs to know\n"
63 "\t\twhat audio standard is needed for some video standards with\n"
64 "\t\taudio A2 or NICAM.\n"
65 "\t\tThe valid settings are a sum of:\n"
66 "\t\t 1: use NICAM/B or A2/B instead of NICAM/A or A2/A\n"
67 "\t\t 2: use A2 instead of NICAM or BTSC\n"
68 "\t\t 4: use SECAM/K3 instead of K1\n"
69 "\t\t 8: use PAL-D/K audio for SECAM-D/K\n"
70 "\t\t16: use FM radio input 1 instead of input 2\n"
71 "\t\t32: use mono audio (the lower three bits are ignored)");
72
Istvan Vargafa285bc2011-06-04 11:48:16 -030073#define XC4000_DEFAULT_FIRMWARE "xc4000.fw"
74
75static char firmware_name[30];
76module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
77MODULE_PARM_DESC(firmware_name, "\n\t\tFirmware file name. Allows overriding "
78 "the default firmware\n"
79 "\t\tname.");
80
Davide Ferri8d009a02009-06-23 22:34:06 -030081static DEFINE_MUTEX(xc4000_list_mutex);
82static LIST_HEAD(hybrid_tuner_instance_list);
83
84#define dprintk(level, fmt, arg...) if (debug >= level) \
85 printk(KERN_INFO "%s: " fmt, "xc4000", ## arg)
86
Devin Heitmueller11091a32009-07-20 00:54:57 -030087/* struct for storing firmware table */
88struct firmware_description {
89 unsigned int type;
90 v4l2_std_id id;
91 __u16 int_freq;
92 unsigned char *ptr;
93 unsigned int size;
94};
95
96struct firmware_properties {
97 unsigned int type;
98 v4l2_std_id id;
99 v4l2_std_id std_req;
100 __u16 int_freq;
101 unsigned int scode_table;
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300102 int scode_nr;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300103};
Davide Ferri8d009a02009-06-23 22:34:06 -0300104
105struct xc4000_priv {
106 struct tuner_i2c_props i2c_props;
107 struct list_head hybrid_tuner_instance_list;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300108 struct firmware_description *firm;
Istvan Vargafbe4a292011-06-03 10:11:48 -0300109 int firm_size;
110 __u16 firm_version;
111 u32 if_khz;
112 u32 freq_hz;
113 u32 bandwidth;
114 u8 video_standard;
115 u8 rf_mode;
Istvan Varga0b402132011-06-03 09:38:04 -0300116 u8 card_type;
Istvan Vargafbe4a292011-06-03 10:11:48 -0300117 u8 ignore_i2c_write_errors;
118 /* struct xc2028_ctrl ctrl; */
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300119 struct firmware_properties cur_fw;
Istvan Vargafbe4a292011-06-03 10:11:48 -0300120 __u16 hwmodel;
121 __u16 hwvers;
Istvan Varga56149422011-06-03 12:23:33 -0300122 struct mutex lock;
Davide Ferri8d009a02009-06-23 22:34:06 -0300123};
124
125/* Misc Defines */
Istvan Varga49110852011-06-03 10:55:24 -0300126#define MAX_TV_STANDARD 24
Davide Ferri8d009a02009-06-23 22:34:06 -0300127#define XC_MAX_I2C_WRITE_LENGTH 64
Istvan Varga5272f6b2011-06-04 12:03:03 -0300128#define XC_POWERED_DOWN 0x80000000U
Davide Ferri8d009a02009-06-23 22:34:06 -0300129
130/* Signal Types */
131#define XC_RF_MODE_AIR 0
132#define XC_RF_MODE_CABLE 1
133
134/* Result codes */
135#define XC_RESULT_SUCCESS 0
136#define XC_RESULT_RESET_FAILURE 1
137#define XC_RESULT_I2C_WRITE_FAILURE 2
138#define XC_RESULT_I2C_READ_FAILURE 3
139#define XC_RESULT_OUT_OF_RANGE 5
140
141/* Product id */
142#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300143#define XC_PRODUCT_ID_FW_LOADED 0x0FA0
Davide Ferri8d009a02009-06-23 22:34:06 -0300144
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300145/* Registers (Write-only) */
Davide Ferri8d009a02009-06-23 22:34:06 -0300146#define XREG_INIT 0x00
147#define XREG_VIDEO_MODE 0x01
148#define XREG_AUDIO_MODE 0x02
149#define XREG_RF_FREQ 0x03
150#define XREG_D_CODE 0x04
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300151#define XREG_DIRECTSITTING_MODE 0x05
152#define XREG_SEEK_MODE 0x06
153#define XREG_POWER_DOWN 0x08
154#define XREG_SIGNALSOURCE 0x0A
Istvan Varga30f544e2011-06-04 12:12:42 -0300155#define XREG_SMOOTHEDCVBS 0x0E
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300156#define XREG_AMPLITUDE 0x10
Davide Ferri8d009a02009-06-23 22:34:06 -0300157
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300158/* Registers (Read-only) */
Davide Ferri8d009a02009-06-23 22:34:06 -0300159#define XREG_ADC_ENV 0x00
160#define XREG_QUALITY 0x01
161#define XREG_FRAME_LINES 0x02
162#define XREG_HSYNC_FREQ 0x03
163#define XREG_LOCK 0x04
164#define XREG_FREQ_ERROR 0x05
165#define XREG_SNR 0x06
166#define XREG_VERSION 0x07
167#define XREG_PRODUCT_ID 0x08
Davide Ferri8d009a02009-06-23 22:34:06 -0300168
169/*
170 Basic firmware description. This will remain with
171 the driver for documentation purposes.
172
173 This represents an I2C firmware file encoded as a
174 string of unsigned char. Format is as follows:
175
176 char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB
177 char[1 ]=len0_LSB -> length of first write transaction
178 char[2 ]=data0 -> first byte to be sent
179 char[3 ]=data1
180 char[4 ]=data2
181 char[ ]=...
182 char[M ]=dataN -> last byte to be sent
183 char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB
184 char[M+2]=len1_LSB -> length of second write transaction
185 char[M+3]=data0
186 char[M+4]=data1
187 ...
188 etc.
189
190 The [len] value should be interpreted as follows:
191
192 len= len_MSB _ len_LSB
193 len=1111_1111_1111_1111 : End of I2C_SEQUENCE
194 len=0000_0000_0000_0000 : Reset command: Do hardware reset
195 len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767)
196 len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms
197
198 For the RESET and WAIT commands, the two following bytes will contain
199 immediately the length of the following transaction.
Davide Ferri8d009a02009-06-23 22:34:06 -0300200*/
Istvan Vargafbe4a292011-06-03 10:11:48 -0300201
Davide Ferri8d009a02009-06-23 22:34:06 -0300202struct XC_TV_STANDARD {
Istvan Vargafbe4a292011-06-03 10:11:48 -0300203 const char *Name;
204 u16 AudioMode;
205 u16 VideoMode;
Istvan Varga49110852011-06-03 10:55:24 -0300206 u16 int_freq;
Davide Ferri8d009a02009-06-23 22:34:06 -0300207};
208
209/* Tuner standards */
Devin Heitmuellered23db32009-10-05 01:27:14 -0300210#define XC4000_MN_NTSC_PAL_BTSC 0
211#define XC4000_MN_NTSC_PAL_A2 1
212#define XC4000_MN_NTSC_PAL_EIAJ 2
213#define XC4000_MN_NTSC_PAL_Mono 3
214#define XC4000_BG_PAL_A2 4
215#define XC4000_BG_PAL_NICAM 5
216#define XC4000_BG_PAL_MONO 6
217#define XC4000_I_PAL_NICAM 7
218#define XC4000_I_PAL_NICAM_MONO 8
219#define XC4000_DK_PAL_A2 9
220#define XC4000_DK_PAL_NICAM 10
221#define XC4000_DK_PAL_MONO 11
222#define XC4000_DK_SECAM_A2DK1 12
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300223#define XC4000_DK_SECAM_A2LDK3 13
224#define XC4000_DK_SECAM_A2MONO 14
Istvan Varga49110852011-06-03 10:55:24 -0300225#define XC4000_DK_SECAM_NICAM 15
226#define XC4000_L_SECAM_NICAM 16
227#define XC4000_LC_SECAM_NICAM 17
228#define XC4000_DTV6 18
229#define XC4000_DTV8 19
230#define XC4000_DTV7_8 20
231#define XC4000_DTV7 21
232#define XC4000_FM_Radio_INPUT2 22
233#define XC4000_FM_Radio_INPUT1 23
Davide Ferri8d009a02009-06-23 22:34:06 -0300234
Davide Ferri8d009a02009-06-23 22:34:06 -0300235static struct XC_TV_STANDARD XC4000_Standard[MAX_TV_STANDARD] = {
Istvan Varga49110852011-06-03 10:55:24 -0300236 {"M/N-NTSC/PAL-BTSC", 0x0000, 0x80A0, 4500},
237 {"M/N-NTSC/PAL-A2", 0x0000, 0x80A0, 4600},
238 {"M/N-NTSC/PAL-EIAJ", 0x0040, 0x80A0, 4500},
239 {"M/N-NTSC/PAL-Mono", 0x0078, 0x80A0, 4500},
240 {"B/G-PAL-A2", 0x0000, 0x8159, 5640},
241 {"B/G-PAL-NICAM", 0x0004, 0x8159, 5740},
242 {"B/G-PAL-MONO", 0x0078, 0x8159, 5500},
243 {"I-PAL-NICAM", 0x0080, 0x8049, 6240},
244 {"I-PAL-NICAM-MONO", 0x0078, 0x8049, 6000},
245 {"D/K-PAL-A2", 0x0000, 0x8049, 6380},
246 {"D/K-PAL-NICAM", 0x0080, 0x8049, 6200},
247 {"D/K-PAL-MONO", 0x0078, 0x8049, 6500},
248 {"D/K-SECAM-A2 DK1", 0x0000, 0x8049, 6340},
249 {"D/K-SECAM-A2 L/DK3", 0x0000, 0x8049, 6000},
250 {"D/K-SECAM-A2 MONO", 0x0078, 0x8049, 6500},
251 {"D/K-SECAM-NICAM", 0x0080, 0x8049, 6200},
252 {"L-SECAM-NICAM", 0x8080, 0x0009, 6200},
253 {"L'-SECAM-NICAM", 0x8080, 0x4009, 6200},
254 {"DTV6", 0x00C0, 0x8002, 0},
255 {"DTV8", 0x00C0, 0x800B, 0},
256 {"DTV7/8", 0x00C0, 0x801B, 0},
257 {"DTV7", 0x00C0, 0x8007, 0},
258 {"FM Radio-INPUT2", 0x0008, 0x9800,10700},
259 {"FM Radio-INPUT1", 0x0008, 0x9000,10700}
Davide Ferri8d009a02009-06-23 22:34:06 -0300260};
261
Davide Ferri8d009a02009-06-23 22:34:06 -0300262static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
263static int xc4000_TunerReset(struct dvb_frontend *fe);
Istvan Vargaf4312e2f2011-06-04 12:08:29 -0300264static void xc_debug_dump(struct xc4000_priv *priv);
Davide Ferri8d009a02009-06-23 22:34:06 -0300265
266static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
267{
268 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
269 .flags = 0, .buf = buf, .len = len };
Davide Ferri8d009a02009-06-23 22:34:06 -0300270 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
Devin Heitmueller799ed112009-10-04 23:09:18 -0300271 if (priv->ignore_i2c_write_errors == 0) {
272 printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n",
273 len);
274 if (len == 4) {
275 printk("bytes %02x %02x %02x %02x\n", buf[0],
276 buf[1], buf[2], buf[3]);
277 }
278 return XC_RESULT_I2C_WRITE_FAILURE;
279 }
Davide Ferri8d009a02009-06-23 22:34:06 -0300280 }
281 return XC_RESULT_SUCCESS;
282}
283
Davide Ferri8d009a02009-06-23 22:34:06 -0300284static void xc_wait(int wait_ms)
285{
286 msleep(wait_ms);
287}
288
289static int xc4000_TunerReset(struct dvb_frontend *fe)
290{
291 struct xc4000_priv *priv = fe->tuner_priv;
292 int ret;
293
294 dprintk(1, "%s()\n", __func__);
295
296 if (fe->callback) {
297 ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
298 fe->dvb->priv :
299 priv->i2c_props.adap->algo_data,
300 DVB_FRONTEND_COMPONENT_TUNER,
301 XC4000_TUNER_RESET, 0);
302 if (ret) {
303 printk(KERN_ERR "xc4000: reset failed\n");
304 return XC_RESULT_RESET_FAILURE;
305 }
306 } else {
307 printk(KERN_ERR "xc4000: no tuner reset callback function, fatal\n");
308 return XC_RESULT_RESET_FAILURE;
309 }
310 return XC_RESULT_SUCCESS;
311}
312
313static int xc_write_reg(struct xc4000_priv *priv, u16 regAddr, u16 i2cData)
314{
315 u8 buf[4];
Davide Ferri8d009a02009-06-23 22:34:06 -0300316 int result;
317
318 buf[0] = (regAddr >> 8) & 0xFF;
319 buf[1] = regAddr & 0xFF;
320 buf[2] = (i2cData >> 8) & 0xFF;
321 buf[3] = i2cData & 0xFF;
322 result = xc_send_i2c_data(priv, buf, 4);
Davide Ferri8d009a02009-06-23 22:34:06 -0300323
324 return result;
325}
326
327static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
328{
329 struct xc4000_priv *priv = fe->tuner_priv;
330
331 int i, nbytes_to_send, result;
332 unsigned int len, pos, index;
333 u8 buf[XC_MAX_I2C_WRITE_LENGTH];
334
335 index = 0;
336 while ((i2c_sequence[index] != 0xFF) ||
337 (i2c_sequence[index + 1] != 0xFF)) {
338 len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
339 if (len == 0x0000) {
340 /* RESET command */
341 result = xc4000_TunerReset(fe);
342 index += 2;
343 if (result != XC_RESULT_SUCCESS)
344 return result;
345 } else if (len & 0x8000) {
346 /* WAIT command */
347 xc_wait(len & 0x7FFF);
348 index += 2;
349 } else {
350 /* Send i2c data whilst ensuring individual transactions
351 * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
352 */
353 index += 2;
354 buf[0] = i2c_sequence[index];
355 buf[1] = i2c_sequence[index + 1];
356 pos = 2;
357 while (pos < len) {
358 if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
359 nbytes_to_send =
360 XC_MAX_I2C_WRITE_LENGTH;
361 else
362 nbytes_to_send = (len - pos + 2);
363 for (i = 2; i < nbytes_to_send; i++) {
364 buf[i] = i2c_sequence[index + pos +
365 i - 2];
366 }
367 result = xc_send_i2c_data(priv, buf,
368 nbytes_to_send);
369
370 if (result != XC_RESULT_SUCCESS)
371 return result;
372
373 pos += nbytes_to_send - 2;
374 }
375 index += len;
376 }
377 }
378 return XC_RESULT_SUCCESS;
379}
380
Davide Ferri8d009a02009-06-23 22:34:06 -0300381static int xc_SetTVStandard(struct xc4000_priv *priv,
382 u16 VideoMode, u16 AudioMode)
383{
384 int ret;
385 dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
386 dprintk(1, "%s() Standard = %s\n",
387 __func__,
388 XC4000_Standard[priv->video_standard].Name);
389
Devin Heitmueller799ed112009-10-04 23:09:18 -0300390 /* Don't complain when the request fails because of i2c stretching */
391 priv->ignore_i2c_write_errors = 1;
392
Davide Ferri8d009a02009-06-23 22:34:06 -0300393 ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
394 if (ret == XC_RESULT_SUCCESS)
395 ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
396
Devin Heitmueller799ed112009-10-04 23:09:18 -0300397 priv->ignore_i2c_write_errors = 0;
398
Davide Ferri8d009a02009-06-23 22:34:06 -0300399 return ret;
400}
401
402static int xc_SetSignalSource(struct xc4000_priv *priv, u16 rf_mode)
403{
404 dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
405 rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
406
407 if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
408 rf_mode = XC_RF_MODE_CABLE;
409 printk(KERN_ERR
410 "%s(), Invalid mode, defaulting to CABLE",
411 __func__);
412 }
413 return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
414}
415
416static const struct dvb_tuner_ops xc4000_tuner_ops;
417
418static int xc_set_RF_frequency(struct xc4000_priv *priv, u32 freq_hz)
419{
420 u16 freq_code;
421
422 dprintk(1, "%s(%u)\n", __func__, freq_hz);
423
424 if ((freq_hz > xc4000_tuner_ops.info.frequency_max) ||
425 (freq_hz < xc4000_tuner_ops.info.frequency_min))
426 return XC_RESULT_OUT_OF_RANGE;
427
428 freq_code = (u16)(freq_hz / 15625);
429
430 /* WAS: Starting in firmware version 1.1.44, Xceive recommends using the
431 FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
432 only be used for fast scanning for channel lock) */
433 return xc_write_reg(priv, XREG_RF_FREQ, freq_code); /* WAS: XREG_FINERFREQ */
434}
435
Davide Ferri8d009a02009-06-23 22:34:06 -0300436static int xc_get_ADC_Envelope(struct xc4000_priv *priv, u16 *adc_envelope)
437{
438 return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope);
439}
440
441static int xc_get_frequency_error(struct xc4000_priv *priv, u32 *freq_error_hz)
442{
443 int result;
444 u16 regData;
445 u32 tmp;
446
447 result = xc4000_readreg(priv, XREG_FREQ_ERROR, &regData);
448 if (result != XC_RESULT_SUCCESS)
449 return result;
450
Istvan Varga1368ceb2011-06-03 12:27:30 -0300451 tmp = (u32)regData & 0xFFFFU;
452 tmp = (tmp < 0x8000U ? tmp : 0x10000U - tmp);
453 (*freq_error_hz) = tmp * 15625;
Davide Ferri8d009a02009-06-23 22:34:06 -0300454 return result;
455}
456
457static int xc_get_lock_status(struct xc4000_priv *priv, u16 *lock_status)
458{
459 return xc4000_readreg(priv, XREG_LOCK, lock_status);
460}
461
462static int xc_get_version(struct xc4000_priv *priv,
463 u8 *hw_majorversion, u8 *hw_minorversion,
464 u8 *fw_majorversion, u8 *fw_minorversion)
465{
466 u16 data;
467 int result;
468
469 result = xc4000_readreg(priv, XREG_VERSION, &data);
470 if (result != XC_RESULT_SUCCESS)
471 return result;
472
473 (*hw_majorversion) = (data >> 12) & 0x0F;
474 (*hw_minorversion) = (data >> 8) & 0x0F;
475 (*fw_majorversion) = (data >> 4) & 0x0F;
476 (*fw_minorversion) = data & 0x0F;
477
478 return 0;
479}
480
Davide Ferri8d009a02009-06-23 22:34:06 -0300481static int xc_get_hsync_freq(struct xc4000_priv *priv, u32 *hsync_freq_hz)
482{
483 u16 regData;
484 int result;
485
486 result = xc4000_readreg(priv, XREG_HSYNC_FREQ, &regData);
487 if (result != XC_RESULT_SUCCESS)
488 return result;
489
490 (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
491 return result;
492}
493
494static int xc_get_frame_lines(struct xc4000_priv *priv, u16 *frame_lines)
495{
496 return xc4000_readreg(priv, XREG_FRAME_LINES, frame_lines);
497}
498
499static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
500{
501 return xc4000_readreg(priv, XREG_QUALITY, quality);
502}
503
504static u16 WaitForLock(struct xc4000_priv *priv)
505{
506 u16 lockState = 0;
507 int watchDogCount = 40;
508
509 while ((lockState == 0) && (watchDogCount > 0)) {
510 xc_get_lock_status(priv, &lockState);
511 if (lockState != 1) {
512 xc_wait(5);
513 watchDogCount--;
514 }
515 }
516 return lockState;
517}
518
Istvan Vargae75873c2011-06-04 12:18:41 -0300519static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz)
Davide Ferri8d009a02009-06-23 22:34:06 -0300520{
Istvan Vargae75873c2011-06-04 12:18:41 -0300521 int found = 1;
522 int result;
Davide Ferri8d009a02009-06-23 22:34:06 -0300523
524 dprintk(1, "%s(%u)\n", __func__, freq_hz);
525
Devin Heitmueller799ed112009-10-04 23:09:18 -0300526 /* Don't complain when the request fails because of i2c stretching */
527 priv->ignore_i2c_write_errors = 1;
528 result = xc_set_RF_frequency(priv, freq_hz);
529 priv->ignore_i2c_write_errors = 0;
530
531 if (result != XC_RESULT_SUCCESS)
Davide Ferri8d009a02009-06-23 22:34:06 -0300532 return 0;
533
Istvan Vargae75873c2011-06-04 12:18:41 -0300534 /* wait for lock only in analog TV mode */
535 if ((priv->cur_fw.type & (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) {
536 if (WaitForLock(priv) != 1)
537 found = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -0300538 }
539
Istvan Vargaf4312e2f2011-06-04 12:08:29 -0300540 /* Wait for stats to stabilize.
541 * Frame Lines needs two frame times after initial lock
542 * before it is valid.
543 */
544 xc_wait(debug ? 100 : 10);
545
546 if (debug)
547 xc_debug_dump(priv);
548
Davide Ferri8d009a02009-06-23 22:34:06 -0300549 return found;
550}
551
552static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val)
553{
554 u8 buf[2] = { reg >> 8, reg & 0xff };
555 u8 bval[2] = { 0, 0 };
556 struct i2c_msg msg[2] = {
557 { .addr = priv->i2c_props.addr,
558 .flags = 0, .buf = &buf[0], .len = 2 },
559 { .addr = priv->i2c_props.addr,
560 .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
561 };
562
563 if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
564 printk(KERN_WARNING "xc4000: I2C read failed\n");
565 return -EREMOTEIO;
566 }
567
568 *val = (bval[0] << 8) | bval[1];
569 return XC_RESULT_SUCCESS;
570}
571
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300572#define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0)
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300573static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
574{
575 if (type & BASE)
576 printk("BASE ");
577 if (type & INIT1)
578 printk("INIT1 ");
579 if (type & F8MHZ)
580 printk("F8MHZ ");
581 if (type & MTS)
582 printk("MTS ");
583 if (type & D2620)
584 printk("D2620 ");
585 if (type & D2633)
586 printk("D2633 ");
587 if (type & DTV6)
588 printk("DTV6 ");
589 if (type & QAM)
590 printk("QAM ");
591 if (type & DTV7)
592 printk("DTV7 ");
593 if (type & DTV78)
594 printk("DTV78 ");
595 if (type & DTV8)
596 printk("DTV8 ");
597 if (type & FM)
598 printk("FM ");
599 if (type & INPUT1)
600 printk("INPUT1 ");
601 if (type & LCD)
602 printk("LCD ");
603 if (type & NOGD)
604 printk("NOGD ");
605 if (type & MONO)
606 printk("MONO ");
607 if (type & ATSC)
608 printk("ATSC ");
609 if (type & IF)
610 printk("IF ");
611 if (type & LG60)
612 printk("LG60 ");
613 if (type & ATI638)
614 printk("ATI638 ");
615 if (type & OREN538)
616 printk("OREN538 ");
617 if (type & OREN36)
618 printk("OREN36 ");
619 if (type & TOYOTA388)
620 printk("TOYOTA388 ");
621 if (type & TOYOTA794)
622 printk("TOYOTA794 ");
623 if (type & DIBCOM52)
624 printk("DIBCOM52 ");
625 if (type & ZARLINK456)
626 printk("ZARLINK456 ");
627 if (type & CHINA)
628 printk("CHINA ");
629 if (type & F6MHZ)
630 printk("F6MHZ ");
631 if (type & INPUT2)
632 printk("INPUT2 ");
633 if (type & SCODE)
634 printk("SCODE ");
635 if (type & HAS_IF)
636 printk("HAS_IF_%d ", int_freq);
637}
638
Devin Heitmueller11091a32009-07-20 00:54:57 -0300639static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
640 v4l2_std_id *id)
641{
642 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Varga3db95702011-06-04 11:52:34 -0300643 int i, best_i = -1;
644 unsigned int best_nr_diffs = 255U;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300645
Devin Heitmueller11091a32009-07-20 00:54:57 -0300646 if (!priv->firm) {
647 printk("Error! firmware not loaded\n");
648 return -EINVAL;
649 }
650
651 if (((type & ~SCODE) == 0) && (*id == 0))
652 *id = V4L2_STD_PAL;
653
Devin Heitmueller11091a32009-07-20 00:54:57 -0300654 /* Seek for generic video standard match */
655 for (i = 0; i < priv->firm_size; i++) {
Istvan Varga3db95702011-06-04 11:52:34 -0300656 v4l2_std_id id_diff_mask =
657 (priv->firm[i].id ^ (*id)) & (*id);
658 unsigned int type_diff_mask =
659 (priv->firm[i].type ^ type)
660 & (BASE_TYPES | DTV_TYPES | LCD | NOGD | MONO | SCODE);
661 unsigned int nr_diffs;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300662
Istvan Varga3db95702011-06-04 11:52:34 -0300663 if (type_diff_mask
664 & (BASE | INIT1 | FM | DTV6 | DTV7 | DTV78 | DTV8 | SCODE))
Devin Heitmueller11091a32009-07-20 00:54:57 -0300665 continue;
666
Istvan Varga3db95702011-06-04 11:52:34 -0300667 nr_diffs = hweight64(id_diff_mask) + hweight32(type_diff_mask);
668 if (!nr_diffs) /* Supports all the requested standards */
669 goto found;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300670
Istvan Varga3db95702011-06-04 11:52:34 -0300671 if (nr_diffs < best_nr_diffs) {
672 best_nr_diffs = nr_diffs;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300673 best_i = i;
674 }
675 }
676
Istvan Varga3db95702011-06-04 11:52:34 -0300677 /* FIXME: Would make sense to seek for type "hint" match ? */
678 if (best_i < 0) {
679 i = -ENOENT;
680 goto ret;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300681 }
682
Istvan Varga3db95702011-06-04 11:52:34 -0300683 if (best_nr_diffs > 0U) {
684 printk("Selecting best matching firmware (%u bits differ) for "
685 "type=", best_nr_diffs);
686 printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
687 i = best_i;
688 }
Devin Heitmueller11091a32009-07-20 00:54:57 -0300689
690found:
691 *id = priv->firm[i].id;
692
693ret:
Devin Heitmueller11091a32009-07-20 00:54:57 -0300694 if (debug) {
Devin Heitmuellerb6cdb5b2009-12-27 18:15:14 -0300695 printk("%s firmware for type=", (i < 0) ? "Can't find" :
696 "Found");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300697 dump_firm_type(type);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300698 printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
699 }
700 return i;
701}
702
703static int load_firmware(struct dvb_frontend *fe, unsigned int type,
704 v4l2_std_id *id)
705{
706 struct xc4000_priv *priv = fe->tuner_priv;
707 int pos, rc;
Devin Heitmueller31f880e2009-07-20 02:15:31 -0300708 unsigned char *p;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300709
Devin Heitmueller11091a32009-07-20 00:54:57 -0300710 pos = seek_firmware(fe, type, id);
711 if (pos < 0)
712 return pos;
713
Devin Heitmueller11091a32009-07-20 00:54:57 -0300714 p = priv->firm[pos].ptr;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300715
Devin Heitmueller799ed112009-10-04 23:09:18 -0300716 /* Don't complain when the request fails because of i2c stretching */
717 priv->ignore_i2c_write_errors = 1;
718
Devin Heitmueller31f880e2009-07-20 02:15:31 -0300719 rc = xc_load_i2c_sequence(fe, p);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300720
Devin Heitmueller799ed112009-10-04 23:09:18 -0300721 priv->ignore_i2c_write_errors = 0;
722
Devin Heitmueller31f880e2009-07-20 02:15:31 -0300723 return rc;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300724}
725
Davide Ferri8d009a02009-06-23 22:34:06 -0300726static int xc4000_fwupload(struct dvb_frontend *fe)
727{
728 struct xc4000_priv *priv = fe->tuner_priv;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300729 const struct firmware *fw = NULL;
730 const unsigned char *p, *endp;
731 int rc = 0;
732 int n, n_array;
733 char name[33];
Istvan Vargafbe4a292011-06-03 10:11:48 -0300734 const char *fname;
Davide Ferri8d009a02009-06-23 22:34:06 -0300735
Istvan Vargafa285bc2011-06-04 11:48:16 -0300736 if (firmware_name[0] != '\0')
737 fname = firmware_name;
738 else
739 fname = XC4000_DEFAULT_FIRMWARE;
Devin Heitmueller11091a32009-07-20 00:54:57 -0300740
741 printk("Reading firmware %s\n", fname);
742 rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
743 if (rc < 0) {
744 if (rc == -ENOENT)
745 printk("Error: firmware %s not found.\n",
746 fname);
747 else
748 printk("Error %d while requesting firmware %s \n",
749 rc, fname);
750
751 return rc;
752 }
753 p = fw->data;
754 endp = p + fw->size;
755
756 if (fw->size < sizeof(name) - 1 + 2 + 2) {
757 printk("Error: firmware file %s has invalid size!\n",
Istvan Vargafbe4a292011-06-03 10:11:48 -0300758 fname);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300759 goto corrupt;
Davide Ferri8d009a02009-06-23 22:34:06 -0300760 }
761
Devin Heitmueller11091a32009-07-20 00:54:57 -0300762 memcpy(name, p, sizeof(name) - 1);
763 name[sizeof(name) - 1] = 0;
764 p += sizeof(name) - 1;
765
766 priv->firm_version = get_unaligned_le16(p);
767 p += 2;
768
769 n_array = get_unaligned_le16(p);
770 p += 2;
771
Devin Heitmuellerb6cdb5b2009-12-27 18:15:14 -0300772 dprintk(1, "Loading %d firmware images from %s, type: %s, ver %d.%d\n",
773 n_array, fname, name,
774 priv->firm_version >> 8, priv->firm_version & 0xff);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300775
776 priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
777 if (priv->firm == NULL) {
778 printk("Not enough memory to load firmware file.\n");
779 rc = -ENOMEM;
780 goto err;
781 }
782 priv->firm_size = n_array;
783
784 n = -1;
785 while (p < endp) {
786 __u32 type, size;
787 v4l2_std_id id;
788 __u16 int_freq = 0;
789
790 n++;
791 if (n >= n_array) {
792 printk("More firmware images in file than "
Istvan Vargafbe4a292011-06-03 10:11:48 -0300793 "were expected!\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300794 goto corrupt;
795 }
796
797 /* Checks if there's enough bytes to read */
798 if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
799 goto header;
800
801 type = get_unaligned_le32(p);
802 p += sizeof(type);
803
804 id = get_unaligned_le64(p);
805 p += sizeof(id);
806
807 if (type & HAS_IF) {
808 int_freq = get_unaligned_le16(p);
809 p += sizeof(int_freq);
810 if (endp - p < sizeof(size))
811 goto header;
812 }
813
814 size = get_unaligned_le32(p);
815 p += sizeof(size);
816
817 if (!size || size > endp - p) {
Istvan Vargaffce6262011-06-04 11:56:18 -0300818 printk("Firmware type (%x), id %llx is corrupted "
Devin Heitmueller11091a32009-07-20 00:54:57 -0300819 "(size=%d, expected %d)\n",
820 type, (unsigned long long)id,
821 (unsigned)(endp - p), size);
822 goto corrupt;
823 }
824
825 priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
826 if (priv->firm[n].ptr == NULL) {
827 printk("Not enough memory to load firmware file.\n");
828 rc = -ENOMEM;
829 goto err;
830 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300831
Devin Heitmueller11091a32009-07-20 00:54:57 -0300832 if (debug) {
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300833 printk("Reading firmware type ");
834 dump_firm_type_and_int_freq(type, int_freq);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300835 printk("(%x), id %llx, size=%d.\n",
836 type, (unsigned long long)id, size);
837 }
838
839 memcpy(priv->firm[n].ptr, p, size);
840 priv->firm[n].type = type;
841 priv->firm[n].id = id;
842 priv->firm[n].size = size;
843 priv->firm[n].int_freq = int_freq;
844
845 p += size;
Davide Ferri8d009a02009-06-23 22:34:06 -0300846 }
847
Devin Heitmueller11091a32009-07-20 00:54:57 -0300848 if (n + 1 != priv->firm_size) {
849 printk("Firmware file is incomplete!\n");
850 goto corrupt;
851 }
852
853 goto done;
854
855header:
856 printk("Firmware header is incomplete!\n");
857corrupt:
858 rc = -EINVAL;
859 printk("Error: firmware file is corrupted!\n");
860
861err:
862 printk("Releasing partially loaded firmware file.\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300863
864done:
Davide Ferri8d009a02009-06-23 22:34:06 -0300865 release_firmware(fw);
Devin Heitmueller11091a32009-07-20 00:54:57 -0300866 if (rc == 0)
Devin Heitmuellerb6cdb5b2009-12-27 18:15:14 -0300867 dprintk(1, "Firmware files loaded.\n");
Devin Heitmueller11091a32009-07-20 00:54:57 -0300868
869 return rc;
Davide Ferri8d009a02009-06-23 22:34:06 -0300870}
871
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300872static int load_scode(struct dvb_frontend *fe, unsigned int type,
873 v4l2_std_id *id, __u16 int_freq, int scode)
874{
875 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Vargaffce6262011-06-04 11:56:18 -0300876 int pos, rc;
877 unsigned char *p;
878 u8 scode_buf[13];
879 u8 indirect_mode[5];
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300880
Devin Heitmuellerfe830362009-07-28 00:04:27 -0300881 dprintk(1, "%s called int_freq=%d\n", __func__, int_freq);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300882
883 if (!int_freq) {
884 pos = seek_firmware(fe, type, id);
885 if (pos < 0)
886 return pos;
887 } else {
888 for (pos = 0; pos < priv->firm_size; pos++) {
889 if ((priv->firm[pos].int_freq == int_freq) &&
890 (priv->firm[pos].type & HAS_IF))
891 break;
892 }
893 if (pos == priv->firm_size)
894 return -ENOENT;
895 }
896
897 p = priv->firm[pos].ptr;
898
Istvan Vargaffce6262011-06-04 11:56:18 -0300899 if (priv->firm[pos].size != 12 * 16 || scode >= 16)
900 return -EINVAL;
901 p += 12 * scode;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300902
903 tuner_info("Loading SCODE for type=");
904 dump_firm_type_and_int_freq(priv->firm[pos].type,
905 priv->firm[pos].int_freq);
906 printk("(%x), id %016llx.\n", priv->firm[pos].type,
907 (unsigned long long)*id);
908
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300909 scode_buf[0] = 0x00;
910 memcpy(&scode_buf[1], p, 12);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300911
912 /* Enter direct-mode */
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300913 rc = xc_write_reg(priv, XREG_DIRECTSITTING_MODE, 0);
914 if (rc < 0) {
915 printk("failed to put device into direct mode!\n");
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300916 return -EIO;
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300917 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300918
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300919 rc = xc_send_i2c_data(priv, scode_buf, 13);
920 if (rc != XC_RESULT_SUCCESS) {
921 /* Even if the send failed, make sure we set back to indirect
922 mode */
923 printk("Failed to set scode %d\n", rc);
924 }
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300925
926 /* Switch back to indirect-mode */
927 memset(indirect_mode, 0, sizeof(indirect_mode));
928 indirect_mode[4] = 0x88;
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -0300929 xc_send_i2c_data(priv, indirect_mode, sizeof(indirect_mode));
930 msleep(10);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300931
932 return 0;
933}
934
935static int check_firmware(struct dvb_frontend *fe, unsigned int type,
936 v4l2_std_id std, __u16 int_freq)
937{
938 struct xc4000_priv *priv = fe->tuner_priv;
939 struct firmware_properties new_fw;
940 int rc = 0, is_retry = 0;
Istvan Varga595a83f2011-06-04 11:59:54 -0300941 u16 version = 0, hwmodel;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300942 v4l2_std_id std0;
Mauro Carvalho Chehabe3bb7c62011-06-02 11:36:56 -0300943 u8 hw_major, hw_minor, fw_major, fw_minor;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300944
945 dprintk(1, "%s called\n", __func__);
946
947 if (!priv->firm) {
948 rc = xc4000_fwupload(fe);
949 if (rc < 0)
950 return rc;
951 }
952
953#ifdef DJH_DEBUG
954 if (priv->ctrl.mts && !(type & FM))
955 type |= MTS;
956#endif
957
958retry:
959 new_fw.type = type;
960 new_fw.id = std;
961 new_fw.std_req = std;
Istvan Vargafbe4a292011-06-03 10:11:48 -0300962 new_fw.scode_table = SCODE /* | priv->ctrl.scode_table */;
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300963 new_fw.scode_nr = 0;
964 new_fw.int_freq = int_freq;
965
966 dprintk(1, "checking firmware, user requested type=");
967 if (debug) {
968 dump_firm_type(new_fw.type);
969 printk("(%x), id %016llx, ", new_fw.type,
970 (unsigned long long)new_fw.std_req);
971 if (!int_freq) {
972 printk("scode_tbl ");
973#ifdef DJH_DEBUG
974 dump_firm_type(priv->ctrl.scode_table);
975 printk("(%x), ", priv->ctrl.scode_table);
976#endif
977 } else
978 printk("int_freq %d, ", new_fw.int_freq);
979 printk("scode_nr %d\n", new_fw.scode_nr);
980 }
981
982 /* No need to reload base firmware if it matches */
Istvan Varga595a83f2011-06-04 11:59:54 -0300983 if (priv->cur_fw.type & BASE) {
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300984 dprintk(1, "BASE firmware not changed.\n");
985 goto skip_base;
986 }
987
988 /* Updating BASE - forget about all currently loaded firmware */
989 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
990
991 /* Reset is needed before loading firmware */
992 rc = xc4000_TunerReset(fe);
993 if (rc < 0)
994 goto fail;
995
996 /* BASE firmwares are all std0 */
997 std0 = 0;
Istvan Varga595a83f2011-06-04 11:59:54 -0300998 rc = load_firmware(fe, BASE, &std0);
Devin Heitmuellerd0962382009-07-25 17:39:54 -0300999 if (rc < 0) {
1000 printk("Error %d while loading base firmware\n", rc);
1001 goto fail;
1002 }
1003
1004 /* Load INIT1, if needed */
1005 dprintk(1, "Load init1 firmware, if exists\n");
1006
Istvan Varga595a83f2011-06-04 11:59:54 -03001007 rc = load_firmware(fe, BASE | INIT1, &std0);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001008 if (rc == -ENOENT)
Istvan Varga595a83f2011-06-04 11:59:54 -03001009 rc = load_firmware(fe, BASE | INIT1, &std0);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001010 if (rc < 0 && rc != -ENOENT) {
1011 tuner_err("Error %d while loading init1 firmware\n",
1012 rc);
1013 goto fail;
1014 }
1015
1016skip_base:
1017 /*
1018 * No need to reload standard specific firmware if base firmware
1019 * was not reloaded and requested video standards have not changed.
1020 */
1021 if (priv->cur_fw.type == (BASE | new_fw.type) &&
1022 priv->cur_fw.std_req == std) {
1023 dprintk(1, "Std-specific firmware already loaded.\n");
1024 goto skip_std_specific;
1025 }
1026
1027 /* Reloading std-specific firmware forces a SCODE update */
1028 priv->cur_fw.scode_table = 0;
1029
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -03001030 /* Load the standard firmware */
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001031 rc = load_firmware(fe, new_fw.type, &new_fw.id);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001032
1033 if (rc < 0)
1034 goto fail;
1035
1036skip_std_specific:
1037 if (priv->cur_fw.scode_table == new_fw.scode_table &&
1038 priv->cur_fw.scode_nr == new_fw.scode_nr) {
1039 dprintk(1, "SCODE firmware already loaded.\n");
1040 goto check_device;
1041 }
1042
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001043 /* Load SCODE firmware, if exists */
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001044 rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
1045 new_fw.int_freq, new_fw.scode_nr);
Devin Heitmuelleree4c3cd2009-07-27 23:51:54 -03001046 if (rc != XC_RESULT_SUCCESS)
1047 dprintk(1, "load scode failed %d\n", rc);
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001048
1049check_device:
1050 rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel);
1051
Devin Heitmueller799ed112009-10-04 23:09:18 -03001052 if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major,
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001053 &fw_minor) != XC_RESULT_SUCCESS) {
1054 printk("Unable to read tuner registers.\n");
1055 goto fail;
1056 }
1057
1058 dprintk(1, "Device is Xceive %d version %d.%d, "
1059 "firmware version %d.%d\n",
1060 hwmodel, hw_major, hw_minor, fw_major, fw_minor);
1061
1062 /* Check firmware version against what we downloaded. */
1063#ifdef DJH_DEBUG
1064 if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
1065 printk("Incorrect readback of firmware version %x.\n",
1066 (version & 0xff));
1067 goto fail;
1068 }
1069#endif
1070
1071 /* Check that the tuner hardware model remains consistent over time. */
1072 if (priv->hwmodel == 0 && hwmodel == 4000) {
1073 priv->hwmodel = hwmodel;
1074 priv->hwvers = version & 0xff00;
1075 } else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
1076 priv->hwvers != (version & 0xff00)) {
1077 printk("Read invalid device hardware information - tuner "
Istvan Vargafbe4a292011-06-03 10:11:48 -03001078 "hung?\n");
Devin Heitmuellerd0962382009-07-25 17:39:54 -03001079 goto fail;
1080 }
1081
1082 memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
1083
1084 /*
1085 * By setting BASE in cur_fw.type only after successfully loading all
1086 * firmwares, we can:
1087 * 1. Identify that BASE firmware with type=0 has been loaded;
1088 * 2. Tell whether BASE firmware was just changed the next time through.
1089 */
1090 priv->cur_fw.type |= BASE;
1091
1092 return 0;
1093
1094fail:
1095 memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
1096 if (!is_retry) {
1097 msleep(50);
1098 is_retry = 1;
1099 dprintk(1, "Retrying firmware load\n");
1100 goto retry;
1101 }
1102
1103 if (rc == -ENOENT)
1104 rc = -EINVAL;
1105 return rc;
1106}
Devin Heitmueller11091a32009-07-20 00:54:57 -03001107
Davide Ferri8d009a02009-06-23 22:34:06 -03001108static void xc_debug_dump(struct xc4000_priv *priv)
1109{
Istvan Vargafbe4a292011-06-03 10:11:48 -03001110 u16 adc_envelope;
1111 u32 freq_error_hz = 0;
1112 u16 lock_status;
1113 u32 hsync_freq_hz = 0;
1114 u16 frame_lines;
1115 u16 quality;
1116 u8 hw_majorversion = 0, hw_minorversion = 0;
1117 u8 fw_majorversion = 0, fw_minorversion = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -03001118
Istvan Vargafbe4a292011-06-03 10:11:48 -03001119 xc_get_ADC_Envelope(priv, &adc_envelope);
Davide Ferri8d009a02009-06-23 22:34:06 -03001120 dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
1121
1122 xc_get_frequency_error(priv, &freq_error_hz);
1123 dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
1124
Istvan Vargafbe4a292011-06-03 10:11:48 -03001125 xc_get_lock_status(priv, &lock_status);
Davide Ferri8d009a02009-06-23 22:34:06 -03001126 dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
1127 lock_status);
1128
Istvan Vargafbe4a292011-06-03 10:11:48 -03001129 xc_get_version(priv, &hw_majorversion, &hw_minorversion,
1130 &fw_majorversion, &fw_minorversion);
Davide Ferri8d009a02009-06-23 22:34:06 -03001131 dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
1132 hw_majorversion, hw_minorversion,
1133 fw_majorversion, fw_minorversion);
1134
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001135 if (priv->video_standard < XC4000_DTV6) {
1136 xc_get_hsync_freq(priv, &hsync_freq_hz);
1137 dprintk(1, "*** Horizontal sync frequency = %d Hz\n",
1138 hsync_freq_hz);
Davide Ferri8d009a02009-06-23 22:34:06 -03001139
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001140 xc_get_frame_lines(priv, &frame_lines);
1141 dprintk(1, "*** Frame lines = %d\n", frame_lines);
1142 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001143
Istvan Vargafbe4a292011-06-03 10:11:48 -03001144 xc_get_quality(priv, &quality);
Davide Ferri8d009a02009-06-23 22:34:06 -03001145 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
1146}
1147
1148static int xc4000_set_params(struct dvb_frontend *fe,
1149 struct dvb_frontend_parameters *params)
1150{
1151 struct xc4000_priv *priv = fe->tuner_priv;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001152 unsigned int type;
Istvan Varga56149422011-06-03 12:23:33 -03001153 int ret = -EREMOTEIO;
Davide Ferri8d009a02009-06-23 22:34:06 -03001154
Davide Ferri8d009a02009-06-23 22:34:06 -03001155 dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
1156
Istvan Varga56149422011-06-03 12:23:33 -03001157 mutex_lock(&priv->lock);
1158
Davide Ferri8d009a02009-06-23 22:34:06 -03001159 if (fe->ops.info.type == FE_ATSC) {
1160 dprintk(1, "%s() ATSC\n", __func__);
1161 switch (params->u.vsb.modulation) {
1162 case VSB_8:
1163 case VSB_16:
1164 dprintk(1, "%s() VSB modulation\n", __func__);
1165 priv->rf_mode = XC_RF_MODE_AIR;
1166 priv->freq_hz = params->frequency - 1750000;
1167 priv->bandwidth = BANDWIDTH_6_MHZ;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001168 priv->video_standard = XC4000_DTV6;
1169 type = DTV6;
Davide Ferri8d009a02009-06-23 22:34:06 -03001170 break;
1171 case QAM_64:
1172 case QAM_256:
1173 case QAM_AUTO:
1174 dprintk(1, "%s() QAM modulation\n", __func__);
1175 priv->rf_mode = XC_RF_MODE_CABLE;
1176 priv->freq_hz = params->frequency - 1750000;
1177 priv->bandwidth = BANDWIDTH_6_MHZ;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001178 priv->video_standard = XC4000_DTV6;
1179 type = DTV6;
Davide Ferri8d009a02009-06-23 22:34:06 -03001180 break;
1181 default:
Istvan Varga56149422011-06-03 12:23:33 -03001182 ret = -EINVAL;
1183 goto fail;
Davide Ferri8d009a02009-06-23 22:34:06 -03001184 }
1185 } else if (fe->ops.info.type == FE_OFDM) {
1186 dprintk(1, "%s() OFDM\n", __func__);
1187 switch (params->u.ofdm.bandwidth) {
1188 case BANDWIDTH_6_MHZ:
1189 priv->bandwidth = BANDWIDTH_6_MHZ;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001190 priv->video_standard = XC4000_DTV6;
Davide Ferri8d009a02009-06-23 22:34:06 -03001191 priv->freq_hz = params->frequency - 1750000;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001192 type = DTV6;
Davide Ferri8d009a02009-06-23 22:34:06 -03001193 break;
1194 case BANDWIDTH_7_MHZ:
Istvan Vargaf0ef7c82011-06-03 12:17:59 -03001195 priv->bandwidth = BANDWIDTH_7_MHZ;
1196 priv->video_standard = XC4000_DTV7;
1197 priv->freq_hz = params->frequency - 2250000;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001198 type = DTV7;
Istvan Vargaf0ef7c82011-06-03 12:17:59 -03001199 break;
Davide Ferri8d009a02009-06-23 22:34:06 -03001200 case BANDWIDTH_8_MHZ:
1201 priv->bandwidth = BANDWIDTH_8_MHZ;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001202 priv->video_standard = XC4000_DTV8;
Davide Ferri8d009a02009-06-23 22:34:06 -03001203 priv->freq_hz = params->frequency - 2750000;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001204 type = DTV8;
Davide Ferri8d009a02009-06-23 22:34:06 -03001205 break;
Istvan Vargaf0ef7c82011-06-03 12:17:59 -03001206 case BANDWIDTH_AUTO:
1207 if (params->frequency < 400000000) {
1208 priv->bandwidth = BANDWIDTH_7_MHZ;
1209 priv->freq_hz = params->frequency - 2250000;
1210 } else {
1211 priv->bandwidth = BANDWIDTH_8_MHZ;
1212 priv->freq_hz = params->frequency - 2750000;
1213 }
1214 priv->video_standard = XC4000_DTV7_8;
1215 type = DTV78;
1216 break;
Davide Ferri8d009a02009-06-23 22:34:06 -03001217 default:
1218 printk(KERN_ERR "xc4000 bandwidth not set!\n");
Istvan Varga56149422011-06-03 12:23:33 -03001219 ret = -EINVAL;
1220 goto fail;
Davide Ferri8d009a02009-06-23 22:34:06 -03001221 }
1222 priv->rf_mode = XC_RF_MODE_AIR;
1223 } else {
1224 printk(KERN_ERR "xc4000 modulation type not supported!\n");
Istvan Varga56149422011-06-03 12:23:33 -03001225 ret = -EINVAL;
1226 goto fail;
Davide Ferri8d009a02009-06-23 22:34:06 -03001227 }
1228
1229 dprintk(1, "%s() frequency=%d (compensated)\n",
1230 __func__, priv->freq_hz);
1231
Devin Heitmuellered23db32009-10-05 01:27:14 -03001232 /* Make sure the correct firmware type is loaded */
Istvan Varga56149422011-06-03 12:23:33 -03001233 if (check_firmware(fe, type, 0, priv->if_khz) != XC_RESULT_SUCCESS)
1234 goto fail;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001235
Davide Ferri8d009a02009-06-23 22:34:06 -03001236 ret = xc_SetSignalSource(priv, priv->rf_mode);
1237 if (ret != XC_RESULT_SUCCESS) {
1238 printk(KERN_ERR
Istvan Varga56149422011-06-03 12:23:33 -03001239 "xc4000: xc_SetSignalSource(%d) failed\n",
1240 priv->rf_mode);
1241 goto fail;
Istvan Varga30f544e2011-06-04 12:12:42 -03001242 } else {
1243 u16 video_mode, audio_mode;
1244 video_mode = XC4000_Standard[priv->video_standard].VideoMode;
1245 audio_mode = XC4000_Standard[priv->video_standard].AudioMode;
1246 if (type == DTV6 && priv->firm_version != 0x0102)
1247 video_mode |= 0x0001;
1248 ret = xc_SetTVStandard(priv, video_mode, audio_mode);
1249 if (ret != XC_RESULT_SUCCESS) {
1250 printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n");
1251 /* DJH - do not return when it fails... */
1252 /* goto fail; */
1253 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001254 }
1255
Istvan Varga30f544e2011-06-04 12:12:42 -03001256 if (priv->card_type == XC4000_CARD_WINFAST_CX88) {
1257 if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
1258 ret = 0;
1259 if (xc_write_reg(priv, XREG_AMPLITUDE,
1260 (priv->firm_version == 0x0102 ? 132 : 134))
1261 != 0)
1262 ret = -EREMOTEIO;
1263 if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
1264 ret = -EREMOTEIO;
1265 if (ret != 0) {
1266 printk(KERN_ERR "xc4000: setting registers failed\n");
1267 /* goto fail; */
1268 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001269 }
Istvan Varga30f544e2011-06-04 12:12:42 -03001270
Istvan Vargae75873c2011-06-04 12:18:41 -03001271 xc_tune_channel(priv, priv->freq_hz);
Davide Ferri8d009a02009-06-23 22:34:06 -03001272
Istvan Varga56149422011-06-03 12:23:33 -03001273 ret = 0;
1274
1275fail:
1276 mutex_unlock(&priv->lock);
1277
1278 return ret;
Davide Ferri8d009a02009-06-23 22:34:06 -03001279}
1280
Davide Ferri8d009a02009-06-23 22:34:06 -03001281static int xc4000_set_analog_params(struct dvb_frontend *fe,
1282 struct analog_parameters *params)
1283{
1284 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Varga818a1772011-06-04 12:17:22 -03001285 unsigned int type = 0;
Istvan Varga56149422011-06-03 12:23:33 -03001286 int ret = -EREMOTEIO;
Davide Ferri8d009a02009-06-23 22:34:06 -03001287
Istvan Varga818a1772011-06-04 12:17:22 -03001288 if (params->mode == V4L2_TUNER_RADIO) {
1289 dprintk(1, "%s() frequency=%d (in units of 62.5Hz)\n",
1290 __func__, params->frequency);
1291
1292 mutex_lock(&priv->lock);
1293
1294 params->std = 0;
1295 priv->freq_hz = params->frequency * 125L / 2;
1296
1297 if (audio_std & XC4000_AUDIO_STD_INPUT1) {
1298 priv->video_standard = XC4000_FM_Radio_INPUT1;
1299 type = FM | INPUT1;
1300 } else {
1301 priv->video_standard = XC4000_FM_Radio_INPUT2;
1302 type = FM | INPUT2;
1303 }
1304
1305 goto tune_channel;
1306 }
1307
Davide Ferri8d009a02009-06-23 22:34:06 -03001308 dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
1309 __func__, params->frequency);
1310
Istvan Varga56149422011-06-03 12:23:33 -03001311 mutex_lock(&priv->lock);
1312
Davide Ferri8d009a02009-06-23 22:34:06 -03001313 /* params->frequency is in units of 62.5khz */
1314 priv->freq_hz = params->frequency * 62500;
1315
Istvan Varga818a1772011-06-04 12:17:22 -03001316 params->std &= V4L2_STD_ALL;
1317 /* if std is not defined, choose one */
1318 if (!params->std)
1319 params->std = V4L2_STD_PAL_BG;
1320
1321 if (audio_std & XC4000_AUDIO_STD_MONO)
1322 type = MONO;
1323
Davide Ferri8d009a02009-06-23 22:34:06 -03001324 if (params->std & V4L2_STD_MN) {
Istvan Varga818a1772011-06-04 12:17:22 -03001325 params->std = V4L2_STD_MN;
1326 if (audio_std & XC4000_AUDIO_STD_MONO) {
1327 priv->video_standard = XC4000_MN_NTSC_PAL_Mono;
1328 } else if (audio_std & XC4000_AUDIO_STD_A2) {
1329 params->std |= V4L2_STD_A2;
1330 priv->video_standard = XC4000_MN_NTSC_PAL_A2;
1331 } else {
1332 params->std |= V4L2_STD_BTSC;
1333 priv->video_standard = XC4000_MN_NTSC_PAL_BTSC;
1334 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001335 goto tune_channel;
1336 }
1337
1338 if (params->std & V4L2_STD_PAL_BG) {
Istvan Varga818a1772011-06-04 12:17:22 -03001339 params->std = V4L2_STD_PAL_BG;
1340 if (audio_std & XC4000_AUDIO_STD_MONO) {
1341 priv->video_standard = XC4000_BG_PAL_MONO;
1342 } else if (!(audio_std & XC4000_AUDIO_STD_A2)) {
1343 if (!(audio_std & XC4000_AUDIO_STD_B)) {
1344 params->std |= V4L2_STD_NICAM_A;
1345 priv->video_standard = XC4000_BG_PAL_NICAM;
1346 } else {
1347 params->std |= V4L2_STD_NICAM_B;
1348 priv->video_standard = XC4000_BG_PAL_NICAM;
1349 }
1350 } else {
1351 if (!(audio_std & XC4000_AUDIO_STD_B)) {
1352 params->std |= V4L2_STD_A2_A;
1353 priv->video_standard = XC4000_BG_PAL_A2;
1354 } else {
1355 params->std |= V4L2_STD_A2_B;
1356 priv->video_standard = XC4000_BG_PAL_A2;
1357 }
1358 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001359 goto tune_channel;
1360 }
1361
1362 if (params->std & V4L2_STD_PAL_I) {
1363 /* default to NICAM audio standard */
Istvan Varga818a1772011-06-04 12:17:22 -03001364 params->std = V4L2_STD_PAL_I | V4L2_STD_NICAM;
1365 if (audio_std & XC4000_AUDIO_STD_MONO) {
1366 priv->video_standard = XC4000_I_PAL_NICAM_MONO;
1367 } else {
1368 priv->video_standard = XC4000_I_PAL_NICAM;
1369 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001370 goto tune_channel;
1371 }
1372
1373 if (params->std & V4L2_STD_PAL_DK) {
Istvan Varga818a1772011-06-04 12:17:22 -03001374 params->std = V4L2_STD_PAL_DK;
1375 if (audio_std & XC4000_AUDIO_STD_MONO) {
1376 priv->video_standard = XC4000_DK_PAL_MONO;
1377 } else if (audio_std & XC4000_AUDIO_STD_A2) {
1378 params->std |= V4L2_STD_A2;
1379 priv->video_standard = XC4000_DK_PAL_A2;
1380 } else {
1381 params->std |= V4L2_STD_NICAM;
1382 priv->video_standard = XC4000_DK_PAL_NICAM;
1383 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001384 goto tune_channel;
1385 }
1386
1387 if (params->std & V4L2_STD_SECAM_DK) {
Istvan Varga818a1772011-06-04 12:17:22 -03001388 /* default to A2 audio standard */
1389 params->std = V4L2_STD_SECAM_DK | V4L2_STD_A2;
1390 if (audio_std & XC4000_AUDIO_STD_L) {
1391 type = 0;
1392 priv->video_standard = XC4000_DK_SECAM_NICAM;
1393 } else if (audio_std & XC4000_AUDIO_STD_MONO) {
1394 priv->video_standard = XC4000_DK_SECAM_A2MONO;
1395 } else if (audio_std & XC4000_AUDIO_STD_K3) {
1396 params->std |= V4L2_STD_SECAM_K3;
1397 priv->video_standard = XC4000_DK_SECAM_A2LDK3;
1398 } else {
1399 priv->video_standard = XC4000_DK_SECAM_A2DK1;
1400 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001401 goto tune_channel;
1402 }
1403
1404 if (params->std & V4L2_STD_SECAM_L) {
Istvan Varga818a1772011-06-04 12:17:22 -03001405 /* default to NICAM audio standard */
1406 type = 0;
1407 params->std = V4L2_STD_SECAM_L | V4L2_STD_NICAM;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001408 priv->video_standard = XC4000_L_SECAM_NICAM;
Davide Ferri8d009a02009-06-23 22:34:06 -03001409 goto tune_channel;
1410 }
1411
1412 if (params->std & V4L2_STD_SECAM_LC) {
Istvan Varga818a1772011-06-04 12:17:22 -03001413 /* default to NICAM audio standard */
1414 type = 0;
1415 params->std = V4L2_STD_SECAM_LC | V4L2_STD_NICAM;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001416 priv->video_standard = XC4000_LC_SECAM_NICAM;
Davide Ferri8d009a02009-06-23 22:34:06 -03001417 goto tune_channel;
1418 }
1419
1420tune_channel:
Istvan Varga818a1772011-06-04 12:17:22 -03001421 /* Fix me: it could be air. */
1422 priv->rf_mode = XC_RF_MODE_CABLE;
Devin Heitmuellered23db32009-10-05 01:27:14 -03001423
Istvan Varga818a1772011-06-04 12:17:22 -03001424 if (check_firmware(fe, type, params->std,
1425 XC4000_Standard[priv->video_standard].int_freq)
1426 != XC_RESULT_SUCCESS) {
Istvan Varga56149422011-06-03 12:23:33 -03001427 goto fail;
Istvan Varga818a1772011-06-04 12:17:22 -03001428 }
Devin Heitmuellered23db32009-10-05 01:27:14 -03001429
Davide Ferri8d009a02009-06-23 22:34:06 -03001430 ret = xc_SetSignalSource(priv, priv->rf_mode);
1431 if (ret != XC_RESULT_SUCCESS) {
1432 printk(KERN_ERR
Istvan Varga56149422011-06-03 12:23:33 -03001433 "xc4000: xc_SetSignalSource(%d) failed\n",
1434 priv->rf_mode);
1435 goto fail;
Istvan Varga30f544e2011-06-04 12:12:42 -03001436 } else {
1437 u16 video_mode, audio_mode;
1438 video_mode = XC4000_Standard[priv->video_standard].VideoMode;
1439 audio_mode = XC4000_Standard[priv->video_standard].AudioMode;
1440 if (priv->video_standard < XC4000_BG_PAL_A2) {
1441 if (0 /*type & NOGD*/)
1442 video_mode &= 0xFF7F;
1443 } else if (priv->video_standard < XC4000_I_PAL_NICAM) {
1444 if (priv->card_type == XC4000_CARD_WINFAST_CX88 &&
1445 priv->firm_version == 0x0102)
1446 video_mode &= 0xFEFF;
Istvan Varga923137a2011-06-04 12:15:51 -03001447 if (audio_std & XC4000_AUDIO_STD_B)
1448 video_mode |= 0x0080;
Istvan Varga30f544e2011-06-04 12:12:42 -03001449 }
1450 ret = xc_SetTVStandard(priv, video_mode, audio_mode);
1451 if (ret != XC_RESULT_SUCCESS) {
1452 printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n");
1453 goto fail;
1454 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001455 }
1456
Istvan Varga30f544e2011-06-04 12:12:42 -03001457 if (priv->card_type == XC4000_CARD_WINFAST_CX88) {
1458 if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
1459 ret = 0;
1460 if (xc_write_reg(priv, XREG_AMPLITUDE, 1) != 0)
1461 ret = -EREMOTEIO;
1462 if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
1463 ret = -EREMOTEIO;
1464 if (ret != 0) {
1465 printk(KERN_ERR "xc4000: setting registers failed\n");
1466 goto fail;
1467 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001468 }
1469
Istvan Vargae75873c2011-06-04 12:18:41 -03001470 xc_tune_channel(priv, priv->freq_hz);
Davide Ferri8d009a02009-06-23 22:34:06 -03001471
Istvan Varga56149422011-06-03 12:23:33 -03001472 ret = 0;
1473
1474fail:
1475 mutex_unlock(&priv->lock);
1476
1477 return ret;
Davide Ferri8d009a02009-06-23 22:34:06 -03001478}
1479
1480static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
1481{
1482 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001483
Davide Ferri8d009a02009-06-23 22:34:06 -03001484 *freq = priv->freq_hz;
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001485
1486 if (debug) {
1487 mutex_lock(&priv->lock);
1488 if ((priv->cur_fw.type
1489 & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
1490 u16 snr = 0;
1491 if (xc4000_readreg(priv, XREG_SNR, &snr) == 0) {
1492 mutex_unlock(&priv->lock);
1493 dprintk(1, "%s() freq = %u, SNR = %d\n",
1494 __func__, *freq, snr);
1495 return 0;
1496 }
1497 }
1498 mutex_unlock(&priv->lock);
1499 }
1500
1501 dprintk(1, "%s()\n", __func__);
1502
Davide Ferri8d009a02009-06-23 22:34:06 -03001503 return 0;
1504}
1505
1506static int xc4000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
1507{
1508 struct xc4000_priv *priv = fe->tuner_priv;
1509 dprintk(1, "%s()\n", __func__);
1510
1511 *bw = priv->bandwidth;
1512 return 0;
1513}
1514
1515static int xc4000_get_status(struct dvb_frontend *fe, u32 *status)
1516{
1517 struct xc4000_priv *priv = fe->tuner_priv;
Istvan Vargafbe4a292011-06-03 10:11:48 -03001518 u16 lock_status = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -03001519
Istvan Varga56149422011-06-03 12:23:33 -03001520 mutex_lock(&priv->lock);
1521
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001522 if (priv->cur_fw.type & BASE)
1523 xc_get_lock_status(priv, &lock_status);
1524
1525 *status = (lock_status == 1 ?
1526 TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO : 0);
1527 if (priv->cur_fw.type & (DTV6 | DTV7 | DTV78 | DTV8))
1528 *status &= (~TUNER_STATUS_STEREO);
Davide Ferri8d009a02009-06-23 22:34:06 -03001529
Istvan Varga56149422011-06-03 12:23:33 -03001530 mutex_unlock(&priv->lock);
1531
Istvan Vargaf4312e2f2011-06-04 12:08:29 -03001532 dprintk(2, "%s() lock_status = %d\n", __func__, lock_status);
Davide Ferri8d009a02009-06-23 22:34:06 -03001533
1534 return 0;
1535}
1536
Davide Ferri8d009a02009-06-23 22:34:06 -03001537static int xc4000_sleep(struct dvb_frontend *fe)
1538{
Istvan Varga5272f6b2011-06-04 12:03:03 -03001539 struct xc4000_priv *priv = fe->tuner_priv;
1540 int ret = XC_RESULT_SUCCESS;
1541
1542 dprintk(1, "%s()\n", __func__);
1543
1544 mutex_lock(&priv->lock);
1545
1546 /* Avoid firmware reload on slow devices */
1547 if ((no_poweroff == 2 ||
1548 (no_poweroff == 0 &&
1549 priv->card_type != XC4000_CARD_WINFAST_CX88)) &&
1550 (priv->cur_fw.type & BASE) != 0) {
1551 /* force reset and firmware reload */
1552 priv->cur_fw.type = XC_POWERED_DOWN;
1553
1554 if (xc_write_reg(priv, XREG_POWER_DOWN, 0)
1555 != XC_RESULT_SUCCESS) {
1556 printk(KERN_ERR
1557 "xc4000: %s() unable to shutdown tuner\n",
1558 __func__);
1559 ret = -EREMOTEIO;
1560 }
1561 xc_wait(20);
1562 }
1563
1564 mutex_unlock(&priv->lock);
1565
1566 return ret;
Davide Ferri8d009a02009-06-23 22:34:06 -03001567}
1568
1569static int xc4000_init(struct dvb_frontend *fe)
1570{
Davide Ferri8d009a02009-06-23 22:34:06 -03001571 dprintk(1, "%s()\n", __func__);
1572
Davide Ferri8d009a02009-06-23 22:34:06 -03001573 return 0;
1574}
1575
1576static int xc4000_release(struct dvb_frontend *fe)
1577{
1578 struct xc4000_priv *priv = fe->tuner_priv;
1579
1580 dprintk(1, "%s()\n", __func__);
1581
1582 mutex_lock(&xc4000_list_mutex);
1583
1584 if (priv)
1585 hybrid_tuner_release_state(priv);
1586
1587 mutex_unlock(&xc4000_list_mutex);
1588
1589 fe->tuner_priv = NULL;
1590
1591 return 0;
1592}
1593
1594static const struct dvb_tuner_ops xc4000_tuner_ops = {
1595 .info = {
1596 .name = "Xceive XC4000",
1597 .frequency_min = 1000000,
1598 .frequency_max = 1023000000,
1599 .frequency_step = 50000,
1600 },
1601
1602 .release = xc4000_release,
1603 .init = xc4000_init,
1604 .sleep = xc4000_sleep,
1605
1606 .set_params = xc4000_set_params,
1607 .set_analog_params = xc4000_set_analog_params,
1608 .get_frequency = xc4000_get_frequency,
1609 .get_bandwidth = xc4000_get_bandwidth,
1610 .get_status = xc4000_get_status
1611};
1612
1613struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
1614 struct i2c_adapter *i2c,
1615 struct xc4000_config *cfg)
1616{
1617 struct xc4000_priv *priv = NULL;
Istvan Vargafbe4a292011-06-03 10:11:48 -03001618 int instance;
1619 u16 id = 0;
Davide Ferri8d009a02009-06-23 22:34:06 -03001620
Istvan Varga0b402132011-06-03 09:38:04 -03001621 if (cfg->card_type != XC4000_CARD_GENERIC) {
1622 if (cfg->card_type == XC4000_CARD_WINFAST_CX88) {
1623 cfg->i2c_address = 0x61;
1624 cfg->if_khz = 4560;
1625 } else { /* default to PCTV 340E */
1626 cfg->i2c_address = 0x61;
1627 cfg->if_khz = 5400;
1628 }
1629 }
1630
Davide Ferri8d009a02009-06-23 22:34:06 -03001631 dprintk(1, "%s(%d-%04x)\n", __func__,
1632 i2c ? i2c_adapter_id(i2c) : -1,
1633 cfg ? cfg->i2c_address : -1);
1634
1635 mutex_lock(&xc4000_list_mutex);
1636
1637 instance = hybrid_tuner_request_state(struct xc4000_priv, priv,
1638 hybrid_tuner_instance_list,
1639 i2c, cfg->i2c_address, "xc4000");
Istvan Varga0b402132011-06-03 09:38:04 -03001640 if (cfg->card_type != XC4000_CARD_GENERIC)
1641 priv->card_type = cfg->card_type;
Davide Ferri8d009a02009-06-23 22:34:06 -03001642 switch (instance) {
1643 case 0:
1644 goto fail;
1645 break;
1646 case 1:
1647 /* new tuner instance */
1648 priv->bandwidth = BANDWIDTH_6_MHZ;
Istvan Varga56149422011-06-03 12:23:33 -03001649 mutex_init(&priv->lock);
Davide Ferri8d009a02009-06-23 22:34:06 -03001650 fe->tuner_priv = priv;
1651 break;
1652 default:
1653 /* existing tuner instance */
1654 fe->tuner_priv = priv;
1655 break;
1656 }
1657
Istvan Varga0b402132011-06-03 09:38:04 -03001658 if (cfg->if_khz != 0) {
Davide Ferri8d009a02009-06-23 22:34:06 -03001659 /* If the IF hasn't been set yet, use the value provided by
1660 the caller (occurs in hybrid devices where the analog
1661 call to xc4000_attach occurs before the digital side) */
1662 priv->if_khz = cfg->if_khz;
1663 }
1664
1665 /* Check if firmware has been loaded. It is possible that another
1666 instance of the driver has loaded the firmware.
1667 */
1668
Istvan Varga027fd362011-06-04 12:04:51 -03001669 if (instance == 1) {
1670 if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id)
1671 != XC_RESULT_SUCCESS)
Davide Ferri8d009a02009-06-23 22:34:06 -03001672 goto fail;
Istvan Varga027fd362011-06-04 12:04:51 -03001673 } else {
1674 id = ((priv->cur_fw.type & BASE) != 0 ?
1675 priv->hwmodel : XC_PRODUCT_ID_FW_NOT_LOADED);
1676 }
Davide Ferri8d009a02009-06-23 22:34:06 -03001677
1678 switch (id) {
1679 case XC_PRODUCT_ID_FW_LOADED:
1680 printk(KERN_INFO
1681 "xc4000: Successfully identified at address 0x%02x\n",
1682 cfg->i2c_address);
1683 printk(KERN_INFO
1684 "xc4000: Firmware has been loaded previously\n");
1685 break;
1686 case XC_PRODUCT_ID_FW_NOT_LOADED:
1687 printk(KERN_INFO
1688 "xc4000: Successfully identified at address 0x%02x\n",
1689 cfg->i2c_address);
1690 printk(KERN_INFO
1691 "xc4000: Firmware has not been loaded previously\n");
1692 break;
1693 default:
1694 printk(KERN_ERR
1695 "xc4000: Device not found at addr 0x%02x (0x%x)\n",
1696 cfg->i2c_address, id);
1697 goto fail;
1698 }
1699
1700 mutex_unlock(&xc4000_list_mutex);
1701
1702 memcpy(&fe->ops.tuner_ops, &xc4000_tuner_ops,
1703 sizeof(struct dvb_tuner_ops));
1704
Istvan Varga027fd362011-06-04 12:04:51 -03001705 if (instance == 1) {
1706 int ret;
1707 mutex_lock(&priv->lock);
1708 ret = xc4000_fwupload(fe);
1709 mutex_unlock(&priv->lock);
1710 if (ret != XC_RESULT_SUCCESS)
1711 goto fail2;
1712 }
Devin Heitmueller11091a32009-07-20 00:54:57 -03001713
Davide Ferri8d009a02009-06-23 22:34:06 -03001714 return fe;
1715fail:
1716 mutex_unlock(&xc4000_list_mutex);
Istvan Varga027fd362011-06-04 12:04:51 -03001717fail2:
Davide Ferri8d009a02009-06-23 22:34:06 -03001718 xc4000_release(fe);
1719 return NULL;
1720}
1721EXPORT_SYMBOL(xc4000_attach);
1722
1723MODULE_AUTHOR("Steven Toth, Davide Ferri");
1724MODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver");
1725MODULE_LICENSE("GPL");