blob: 07fd80f4508e1d1aed34db2fa6f13cc7dd49bcc9 [file] [log] [blame]
Steven Tothaacb9d32007-12-18 01:55:51 -03001/*
2 * Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
3 *
4 * Copyright (c) 2007 Xceive Corporation
Steven Toth6d897612008-09-03 17:12:12 -03005 * Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
Devin Heitmuellere80858e2009-05-14 21:31:11 -03006 * Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
Steven Tothaacb9d32007-12-18 01:55:51 -03007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 *
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/moduleparam.h>
Steven Toth49170192008-01-15 21:57:14 -030026#include <linux/videodev2.h>
Steven Tothaacb9d32007-12-18 01:55:51 -030027#include <linux/delay.h>
28#include <linux/dvb/frontend.h>
29#include <linux/i2c.h>
30
31#include "dvb_frontend.h"
32
33#include "xc5000.h"
Michael Krufky89fd2852008-09-06 11:44:53 -030034#include "tuner-i2c.h"
Steven Tothaacb9d32007-12-18 01:55:51 -030035
36static int debug;
37module_param(debug, int, 0644);
38MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
39
Devin Heitmuellerb6bd5eb2009-04-28 13:53:38 -030040static int no_poweroff;
41module_param(no_poweroff, int, 0644);
42MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n"
43 "\t\t1 keep device energized and with tuner ready all the times.\n"
44 "\t\tFaster, but consumes more power and keeps the device hotter");
45
Michael Krufky89fd2852008-09-06 11:44:53 -030046static DEFINE_MUTEX(xc5000_list_mutex);
47static LIST_HEAD(hybrid_tuner_instance_list);
48
Steven Toth8f3cd532008-10-16 20:29:38 -030049#define dprintk(level, fmt, arg...) if (debug >= level) \
Steven Tothaacb9d32007-12-18 01:55:51 -030050 printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
51
Michael Krufkyffb41232008-09-06 10:52:30 -030052struct xc5000_priv {
Michael Krufky89fd2852008-09-06 11:44:53 -030053 struct tuner_i2c_props i2c_props;
54 struct list_head hybrid_tuner_instance_list;
Michael Krufkyffb41232008-09-06 10:52:30 -030055
Michael Krufky2a6003c2008-09-06 13:54:45 -030056 u32 if_khz;
Michael Krufkyffb41232008-09-06 10:52:30 -030057 u32 freq_hz;
58 u32 bandwidth;
59 u8 video_standard;
60 u8 rf_mode;
Devin Heitmueller496e9052009-09-24 13:27:24 -030061 u8 radio_input;
Michael Krufky76efb0ba2012-02-06 19:40:32 -030062
Michael Krufky6fab81d2012-02-08 14:57:39 -030063 int chip_id;
Michael Krufkyffb41232008-09-06 10:52:30 -030064};
65
Steven Tothaacb9d32007-12-18 01:55:51 -030066/* Misc Defines */
Dmitri Belimov724dcbf2011-02-01 05:25:19 -030067#define MAX_TV_STANDARD 24
Steven Tothaacb9d32007-12-18 01:55:51 -030068#define XC_MAX_I2C_WRITE_LENGTH 64
69
70/* Signal Types */
71#define XC_RF_MODE_AIR 0
72#define XC_RF_MODE_CABLE 1
73
74/* Result codes */
75#define XC_RESULT_SUCCESS 0
76#define XC_RESULT_RESET_FAILURE 1
77#define XC_RESULT_I2C_WRITE_FAILURE 2
78#define XC_RESULT_I2C_READ_FAILURE 3
79#define XC_RESULT_OUT_OF_RANGE 5
80
Steven Toth27c685a2008-01-05 16:50:14 -030081/* Product id */
82#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
83#define XC_PRODUCT_ID_FW_LOADED 0x1388
84
Steven Tothaacb9d32007-12-18 01:55:51 -030085/* Registers */
86#define XREG_INIT 0x00
87#define XREG_VIDEO_MODE 0x01
88#define XREG_AUDIO_MODE 0x02
89#define XREG_RF_FREQ 0x03
90#define XREG_D_CODE 0x04
91#define XREG_IF_OUT 0x05
92#define XREG_SEEK_MODE 0x07
Devin Heitmueller7f05b532009-04-02 22:02:39 -030093#define XREG_POWER_DOWN 0x0A /* Obsolete */
Dmitri Belimov724dcbf2011-02-01 05:25:19 -030094/* Set the output amplitude - SIF for analog, DTVP/DTVN for digital */
95#define XREG_OUTPUT_AMP 0x0B
Steven Tothaacb9d32007-12-18 01:55:51 -030096#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
97#define XREG_SMOOTHEDCVBS 0x0E
98#define XREG_XTALFREQ 0x0F
Devin Heitmueller81c4dfe72009-04-02 22:40:29 -030099#define XREG_FINERFREQ 0x10
Steven Tothaacb9d32007-12-18 01:55:51 -0300100#define XREG_DDIMODE 0x11
101
102#define XREG_ADC_ENV 0x00
103#define XREG_QUALITY 0x01
104#define XREG_FRAME_LINES 0x02
105#define XREG_HSYNC_FREQ 0x03
106#define XREG_LOCK 0x04
107#define XREG_FREQ_ERROR 0x05
108#define XREG_SNR 0x06
109#define XREG_VERSION 0x07
110#define XREG_PRODUCT_ID 0x08
111#define XREG_BUSY 0x09
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300112#define XREG_BUILD 0x0D
Steven Tothaacb9d32007-12-18 01:55:51 -0300113
114/*
115 Basic firmware description. This will remain with
116 the driver for documentation purposes.
117
118 This represents an I2C firmware file encoded as a
119 string of unsigned char. Format is as follows:
120
121 char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB
122 char[1 ]=len0_LSB -> length of first write transaction
123 char[2 ]=data0 -> first byte to be sent
124 char[3 ]=data1
125 char[4 ]=data2
126 char[ ]=...
127 char[M ]=dataN -> last byte to be sent
128 char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB
129 char[M+2]=len1_LSB -> length of second write transaction
130 char[M+3]=data0
131 char[M+4]=data1
132 ...
133 etc.
134
135 The [len] value should be interpreted as follows:
136
137 len= len_MSB _ len_LSB
138 len=1111_1111_1111_1111 : End of I2C_SEQUENCE
139 len=0000_0000_0000_0000 : Reset command: Do hardware reset
140 len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767)
141 len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms
142
143 For the RESET and WAIT commands, the two following bytes will contain
144 immediately the length of the following transaction.
145
146*/
Steven Toth8f3cd532008-10-16 20:29:38 -0300147struct XC_TV_STANDARD {
Steven Tothaacb9d32007-12-18 01:55:51 -0300148 char *Name;
Steven Tothe12671c2007-12-20 01:14:43 -0300149 u16 AudioMode;
150 u16 VideoMode;
Steven Toth8f3cd532008-10-16 20:29:38 -0300151};
Steven Tothaacb9d32007-12-18 01:55:51 -0300152
153/* Tuner standards */
Steven Toth27c685a2008-01-05 16:50:14 -0300154#define MN_NTSC_PAL_BTSC 0
155#define MN_NTSC_PAL_A2 1
156#define MN_NTSC_PAL_EIAJ 2
157#define MN_NTSC_PAL_Mono 3
158#define BG_PAL_A2 4
159#define BG_PAL_NICAM 5
160#define BG_PAL_MONO 6
161#define I_PAL_NICAM 7
162#define I_PAL_NICAM_MONO 8
163#define DK_PAL_A2 9
164#define DK_PAL_NICAM 10
165#define DK_PAL_MONO 11
166#define DK_SECAM_A2DK1 12
167#define DK_SECAM_A2LDK3 13
168#define DK_SECAM_A2MONO 14
169#define L_SECAM_NICAM 15
170#define LC_SECAM_NICAM 16
171#define DTV6 17
172#define DTV8 18
173#define DTV7_8 19
174#define DTV7 20
175#define FM_Radio_INPUT2 21
176#define FM_Radio_INPUT1 22
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300177#define FM_Radio_INPUT1_MONO 23
Steven Tothaacb9d32007-12-18 01:55:51 -0300178
Steven Toth8f3cd532008-10-16 20:29:38 -0300179static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
Steven Tothaacb9d32007-12-18 01:55:51 -0300180 {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
181 {"M/N-NTSC/PAL-A2", 0x0600, 0x8020},
182 {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
183 {"M/N-NTSC/PAL-Mono", 0x0478, 0x8020},
184 {"B/G-PAL-A2", 0x0A00, 0x8049},
185 {"B/G-PAL-NICAM", 0x0C04, 0x8049},
186 {"B/G-PAL-MONO", 0x0878, 0x8059},
187 {"I-PAL-NICAM", 0x1080, 0x8009},
188 {"I-PAL-NICAM-MONO", 0x0E78, 0x8009},
189 {"D/K-PAL-A2", 0x1600, 0x8009},
190 {"D/K-PAL-NICAM", 0x0E80, 0x8009},
191 {"D/K-PAL-MONO", 0x1478, 0x8009},
192 {"D/K-SECAM-A2 DK1", 0x1200, 0x8009},
Steven Toth8f3cd532008-10-16 20:29:38 -0300193 {"D/K-SECAM-A2 L/DK3", 0x0E00, 0x8009},
Steven Tothaacb9d32007-12-18 01:55:51 -0300194 {"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
195 {"L-SECAM-NICAM", 0x8E82, 0x0009},
196 {"L'-SECAM-NICAM", 0x8E82, 0x4009},
197 {"DTV6", 0x00C0, 0x8002},
198 {"DTV8", 0x00C0, 0x800B},
199 {"DTV7/8", 0x00C0, 0x801B},
200 {"DTV7", 0x00C0, 0x8007},
201 {"FM Radio-INPUT2", 0x9802, 0x9002},
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300202 {"FM Radio-INPUT1", 0x0208, 0x9002},
203 {"FM Radio-INPUT1_MONO", 0x0278, 0x9002}
Steven Tothaacb9d32007-12-18 01:55:51 -0300204};
205
Michael Krufkyddea4272012-02-07 02:39:36 -0300206
207struct xc5000_fw_cfg {
208 char *name;
209 u16 size;
210};
211
212static struct xc5000_fw_cfg xc5000a_1_6_114 = {
Michael Krufky76efb0ba2012-02-06 19:40:32 -0300213 .name = "dvb-fe-xc5000-1.6.114.fw",
214 .size = 12401,
215};
216
Michael Krufkyddea4272012-02-07 02:39:36 -0300217static struct xc5000_fw_cfg xc5000c_41_024_5_31875 = {
Michael Krufkyd8398802012-02-07 01:16:27 -0300218 .name = "dvb-fe-xc5000c-41.024.5-31875.fw",
219 .size = 16503,
220};
221
Michael Krufky6fab81d2012-02-08 14:57:39 -0300222static inline struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
Michael Krufkyddea4272012-02-07 02:39:36 -0300223{
Michael Krufky6fab81d2012-02-08 14:57:39 -0300224 switch (chip_id) {
Michael Krufkyddea4272012-02-07 02:39:36 -0300225 default:
Michael Krufky6fab81d2012-02-08 14:57:39 -0300226 case XC5000A:
Michael Krufkyddea4272012-02-07 02:39:36 -0300227 return &xc5000a_1_6_114;
Michael Krufky6fab81d2012-02-08 14:57:39 -0300228 case XC5000C:
Michael Krufkyddea4272012-02-07 02:39:36 -0300229 return &xc5000c_41_024_5_31875;
230 }
231}
232
Devin Heitmueller8e4c6792008-11-16 20:41:07 -0300233static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300234static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300235static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300236static int xc5000_TunerReset(struct dvb_frontend *fe);
Steven Tothaacb9d32007-12-18 01:55:51 -0300237
Steven Tothe12671c2007-12-20 01:14:43 -0300238static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
Steven Tothaacb9d32007-12-18 01:55:51 -0300239{
Devin Heitmuellerd7800d42008-11-16 20:20:06 -0300240 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
241 .flags = 0, .buf = buf, .len = len };
242
243 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
244 printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len);
245 return XC_RESULT_I2C_WRITE_FAILURE;
246 }
247 return XC_RESULT_SUCCESS;
Steven Tothaacb9d32007-12-18 01:55:51 -0300248}
249
Mauro Carvalho Chehab1cdffda2010-07-05 18:38:46 -0300250#if 0
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300251/* This routine is never used because the only time we read data from the
252 i2c bus is when we read registers, and we want that to be an atomic i2c
253 transaction in case we are on a multi-master bus */
Steven Tothe12671c2007-12-20 01:14:43 -0300254static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
Steven Tothaacb9d32007-12-18 01:55:51 -0300255{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300256 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
257 .flags = I2C_M_RD, .buf = buf, .len = len };
258
259 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
260 printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", len);
261 return -EREMOTEIO;
262 }
263 return 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300264}
Mauro Carvalho Chehab1cdffda2010-07-05 18:38:46 -0300265#endif
Steven Tothaacb9d32007-12-18 01:55:51 -0300266
Dmitri Belimov47433192010-05-18 04:30:11 -0300267static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
268{
269 u8 buf[2] = { reg >> 8, reg & 0xff };
270 u8 bval[2] = { 0, 0 };
271 struct i2c_msg msg[2] = {
272 { .addr = priv->i2c_props.addr,
273 .flags = 0, .buf = &buf[0], .len = 2 },
274 { .addr = priv->i2c_props.addr,
275 .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
276 };
277
278 if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
279 printk(KERN_WARNING "xc5000: I2C read failed\n");
280 return -EREMOTEIO;
281 }
282
283 *val = (bval[0] << 8) | bval[1];
284 return XC_RESULT_SUCCESS;
285}
286
Steven Tothe12671c2007-12-20 01:14:43 -0300287static void xc_wait(int wait_ms)
Steven Tothaacb9d32007-12-18 01:55:51 -0300288{
Steven Tothe12671c2007-12-20 01:14:43 -0300289 msleep(wait_ms);
Steven Tothaacb9d32007-12-18 01:55:51 -0300290}
291
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300292static int xc5000_TunerReset(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300293{
294 struct xc5000_priv *priv = fe->tuner_priv;
295 int ret;
296
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300297 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300298
Michael Krufkyd7cba042008-09-12 13:31:45 -0300299 if (fe->callback) {
300 ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
Michael Krufky30650962008-09-06 14:56:58 -0300301 fe->dvb->priv :
302 priv->i2c_props.adap->algo_data,
Michael Krufkyd7cba042008-09-12 13:31:45 -0300303 DVB_FRONTEND_COMPONENT_TUNER,
Michael Krufky30650962008-09-06 14:56:58 -0300304 XC5000_TUNER_RESET, 0);
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300305 if (ret) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300306 printk(KERN_ERR "xc5000: reset failed\n");
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300307 return XC_RESULT_RESET_FAILURE;
308 }
309 } else {
Steven Toth27c685a2008-01-05 16:50:14 -0300310 printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300311 return XC_RESULT_RESET_FAILURE;
312 }
313 return XC_RESULT_SUCCESS;
Steven Tothaacb9d32007-12-18 01:55:51 -0300314}
315
Steven Tothe12671c2007-12-20 01:14:43 -0300316static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
Steven Tothaacb9d32007-12-18 01:55:51 -0300317{
Steven Tothe12671c2007-12-20 01:14:43 -0300318 u8 buf[4];
Devin Heitmuellera37791c2009-05-04 23:29:17 -0300319 int WatchDogTimer = 100;
Steven Tothaacb9d32007-12-18 01:55:51 -0300320 int result;
321
322 buf[0] = (regAddr >> 8) & 0xFF;
323 buf[1] = regAddr & 0xFF;
324 buf[2] = (i2cData >> 8) & 0xFF;
325 buf[3] = i2cData & 0xFF;
326 result = xc_send_i2c_data(priv, buf, 4);
Steven Tothe12671c2007-12-20 01:14:43 -0300327 if (result == XC_RESULT_SUCCESS) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300328 /* wait for busy flag to clear */
329 while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
Mauro Carvalho Chehab1cdffda2010-07-05 18:38:46 -0300330 result = xc5000_readreg(priv, XREG_BUSY, (u16 *)buf);
Steven Tothaacb9d32007-12-18 01:55:51 -0300331 if (result == XC_RESULT_SUCCESS) {
Dmitri Belimov47433192010-05-18 04:30:11 -0300332 if ((buf[0] == 0) && (buf[1] == 0)) {
333 /* busy flag cleared */
Steven Tothaacb9d32007-12-18 01:55:51 -0300334 break;
Dmitri Belimov47433192010-05-18 04:30:11 -0300335 } else {
336 xc_wait(5); /* wait 5 ms */
337 WatchDogTimer--;
Steven Tothaacb9d32007-12-18 01:55:51 -0300338 }
339 }
340 }
341 }
342 if (WatchDogTimer < 0)
343 result = XC_RESULT_I2C_WRITE_FAILURE;
344
345 return result;
346}
347
David Woodhousec63e87e2008-05-24 00:13:34 +0100348static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
Steven Tothaacb9d32007-12-18 01:55:51 -0300349{
350 struct xc5000_priv *priv = fe->tuner_priv;
351
352 int i, nbytes_to_send, result;
353 unsigned int len, pos, index;
Steven Tothe12671c2007-12-20 01:14:43 -0300354 u8 buf[XC_MAX_I2C_WRITE_LENGTH];
Steven Tothaacb9d32007-12-18 01:55:51 -0300355
Steven Toth8f3cd532008-10-16 20:29:38 -0300356 index = 0;
357 while ((i2c_sequence[index] != 0xFF) ||
358 (i2c_sequence[index + 1] != 0xFF)) {
359 len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
Steven Tothe12671c2007-12-20 01:14:43 -0300360 if (len == 0x0000) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300361 /* RESET command */
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300362 result = xc5000_TunerReset(fe);
Steven Tothaacb9d32007-12-18 01:55:51 -0300363 index += 2;
Steven Tothe12671c2007-12-20 01:14:43 -0300364 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300365 return result;
366 } else if (len & 0x8000) {
367 /* WAIT command */
368 xc_wait(len & 0x7FFF);
369 index += 2;
370 } else {
371 /* Send i2c data whilst ensuring individual transactions
372 * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
373 */
374 index += 2;
375 buf[0] = i2c_sequence[index];
376 buf[1] = i2c_sequence[index + 1];
377 pos = 2;
378 while (pos < len) {
Steven Toth8f3cd532008-10-16 20:29:38 -0300379 if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
380 nbytes_to_send =
381 XC_MAX_I2C_WRITE_LENGTH;
382 else
Steven Tothaacb9d32007-12-18 01:55:51 -0300383 nbytes_to_send = (len - pos + 2);
Steven Toth8f3cd532008-10-16 20:29:38 -0300384 for (i = 2; i < nbytes_to_send; i++) {
385 buf[i] = i2c_sequence[index + pos +
386 i - 2];
Steven Tothaacb9d32007-12-18 01:55:51 -0300387 }
Steven Toth8f3cd532008-10-16 20:29:38 -0300388 result = xc_send_i2c_data(priv, buf,
389 nbytes_to_send);
Steven Tothaacb9d32007-12-18 01:55:51 -0300390
Steven Tothe12671c2007-12-20 01:14:43 -0300391 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300392 return result;
393
394 pos += nbytes_to_send - 2;
395 }
396 index += len;
397 }
398 }
399 return XC_RESULT_SUCCESS;
400}
401
Steven Tothe12671c2007-12-20 01:14:43 -0300402static int xc_initialize(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300403{
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300404 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300405 return xc_write_reg(priv, XREG_INIT, 0);
406}
407
Steven Tothe12671c2007-12-20 01:14:43 -0300408static int xc_SetTVStandard(struct xc5000_priv *priv,
409 u16 VideoMode, u16 AudioMode)
Steven Tothaacb9d32007-12-18 01:55:51 -0300410{
411 int ret;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300412 dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
Steven Tothaacb9d32007-12-18 01:55:51 -0300413 dprintk(1, "%s() Standard = %s\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300414 __func__,
Steven Tothaacb9d32007-12-18 01:55:51 -0300415 XC5000_Standard[priv->video_standard].Name);
416
417 ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
418 if (ret == XC_RESULT_SUCCESS)
419 ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
420
421 return ret;
422}
423
Steven Tothe12671c2007-12-20 01:14:43 -0300424static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
Steven Tothaacb9d32007-12-18 01:55:51 -0300425{
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300426 dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
Steven Tothaacb9d32007-12-18 01:55:51 -0300427 rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
428
Steven Toth8f3cd532008-10-16 20:29:38 -0300429 if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300430 rf_mode = XC_RF_MODE_CABLE;
431 printk(KERN_ERR
432 "%s(), Invalid mode, defaulting to CABLE",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300433 __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300434 }
435 return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
436}
437
Steven Tothe12671c2007-12-20 01:14:43 -0300438static const struct dvb_tuner_ops xc5000_tuner_ops;
439
440static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300441{
Steven Tothe12671c2007-12-20 01:14:43 -0300442 u16 freq_code;
Steven Tothaacb9d32007-12-18 01:55:51 -0300443
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300444 dprintk(1, "%s(%u)\n", __func__, freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300445
Steven Tothe12671c2007-12-20 01:14:43 -0300446 if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
447 (freq_hz < xc5000_tuner_ops.info.frequency_min))
448 return XC_RESULT_OUT_OF_RANGE;
Steven Tothaacb9d32007-12-18 01:55:51 -0300449
Steven Tothe12671c2007-12-20 01:14:43 -0300450 freq_code = (u16)(freq_hz / 15625);
451
Devin Heitmueller81c4dfe72009-04-02 22:40:29 -0300452 /* Starting in firmware version 1.1.44, Xceive recommends using the
453 FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
454 only be used for fast scanning for channel lock) */
455 return xc_write_reg(priv, XREG_FINERFREQ, freq_code);
Steven Tothaacb9d32007-12-18 01:55:51 -0300456}
457
Steven Tothe12671c2007-12-20 01:14:43 -0300458
459static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300460{
Steven Tothe12671c2007-12-20 01:14:43 -0300461 u32 freq_code = (freq_khz * 1024)/1000;
462 dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300463 __func__, freq_khz, freq_code);
Steven Tothe12671c2007-12-20 01:14:43 -0300464
465 return xc_write_reg(priv, XREG_IF_OUT, freq_code);
Steven Tothaacb9d32007-12-18 01:55:51 -0300466}
467
Steven Tothe12671c2007-12-20 01:14:43 -0300468
469static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
Steven Tothaacb9d32007-12-18 01:55:51 -0300470{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300471 return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope);
Steven Tothaacb9d32007-12-18 01:55:51 -0300472}
473
Steven Tothe12671c2007-12-20 01:14:43 -0300474static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300475{
476 int result;
Steven Tothe12671c2007-12-20 01:14:43 -0300477 u16 regData;
Steven Tothaacb9d32007-12-18 01:55:51 -0300478 u32 tmp;
479
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300480 result = xc5000_readreg(priv, XREG_FREQ_ERROR, &regData);
Devin Heitmueller7988fc22008-11-16 20:23:19 -0300481 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300482 return result;
483
484 tmp = (u32)regData;
Steven Tothe12671c2007-12-20 01:14:43 -0300485 (*freq_error_hz) = (tmp * 15625) / 1000;
Steven Tothaacb9d32007-12-18 01:55:51 -0300486 return result;
487}
488
Steven Tothe12671c2007-12-20 01:14:43 -0300489static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
Steven Tothaacb9d32007-12-18 01:55:51 -0300490{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300491 return xc5000_readreg(priv, XREG_LOCK, lock_status);
Steven Tothaacb9d32007-12-18 01:55:51 -0300492}
493
Steven Tothe12671c2007-12-20 01:14:43 -0300494static int xc_get_version(struct xc5000_priv *priv,
495 u8 *hw_majorversion, u8 *hw_minorversion,
496 u8 *fw_majorversion, u8 *fw_minorversion)
Steven Tothaacb9d32007-12-18 01:55:51 -0300497{
Steven Tothe12671c2007-12-20 01:14:43 -0300498 u16 data;
Steven Tothaacb9d32007-12-18 01:55:51 -0300499 int result;
500
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300501 result = xc5000_readreg(priv, XREG_VERSION, &data);
Devin Heitmueller7988fc22008-11-16 20:23:19 -0300502 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300503 return result;
504
Steven Tothe12671c2007-12-20 01:14:43 -0300505 (*hw_majorversion) = (data >> 12) & 0x0F;
506 (*hw_minorversion) = (data >> 8) & 0x0F;
507 (*fw_majorversion) = (data >> 4) & 0x0F;
508 (*fw_minorversion) = data & 0x0F;
Steven Tothaacb9d32007-12-18 01:55:51 -0300509
510 return 0;
511}
512
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300513static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev)
514{
515 return xc5000_readreg(priv, XREG_BUILD, buildrev);
516}
517
Steven Tothe12671c2007-12-20 01:14:43 -0300518static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300519{
Steven Tothe12671c2007-12-20 01:14:43 -0300520 u16 regData;
Steven Tothaacb9d32007-12-18 01:55:51 -0300521 int result;
522
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300523 result = xc5000_readreg(priv, XREG_HSYNC_FREQ, &regData);
Devin Heitmueller7988fc22008-11-16 20:23:19 -0300524 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300525 return result;
526
527 (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
528 return result;
529}
530
Steven Tothe12671c2007-12-20 01:14:43 -0300531static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
Steven Tothaacb9d32007-12-18 01:55:51 -0300532{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300533 return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines);
Steven Tothaacb9d32007-12-18 01:55:51 -0300534}
535
Steven Tothe12671c2007-12-20 01:14:43 -0300536static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
Steven Tothaacb9d32007-12-18 01:55:51 -0300537{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300538 return xc5000_readreg(priv, XREG_QUALITY, quality);
Steven Tothaacb9d32007-12-18 01:55:51 -0300539}
540
Steven Tothe12671c2007-12-20 01:14:43 -0300541static u16 WaitForLock(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300542{
Steven Tothe12671c2007-12-20 01:14:43 -0300543 u16 lockState = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300544 int watchDogCount = 40;
Steven Tothe12671c2007-12-20 01:14:43 -0300545
546 while ((lockState == 0) && (watchDogCount > 0)) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300547 xc_get_lock_status(priv, &lockState);
Steven Tothe12671c2007-12-20 01:14:43 -0300548 if (lockState != 1) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300549 xc_wait(5);
550 watchDogCount--;
551 }
552 }
553 return lockState;
554}
555
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300556#define XC_TUNE_ANALOG 0
557#define XC_TUNE_DIGITAL 1
558static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
Steven Tothaacb9d32007-12-18 01:55:51 -0300559{
560 int found = 0;
561
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300562 dprintk(1, "%s(%u)\n", __func__, freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300563
Steven Tothe12671c2007-12-20 01:14:43 -0300564 if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300565 return 0;
566
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300567 if (mode == XC_TUNE_ANALOG) {
568 if (WaitForLock(priv) == 1)
569 found = 1;
570 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300571
572 return found;
573}
574
Steven Tothaacb9d32007-12-18 01:55:51 -0300575
Steven Toth8f3cd532008-10-16 20:29:38 -0300576static int xc5000_fwupload(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300577{
578 struct xc5000_priv *priv = fe->tuner_priv;
579 const struct firmware *fw;
580 int ret;
Michael Krufky6fab81d2012-02-08 14:57:39 -0300581 struct xc5000_fw_cfg *desired_fw = xc5000_assign_firmware(priv->chip_id);
Steven Tothaacb9d32007-12-18 01:55:51 -0300582
Steven Tothe12671c2007-12-20 01:14:43 -0300583 /* request the firmware, this will block and timeout */
584 printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
Michael Krufky6fab81d2012-02-08 14:57:39 -0300585 desired_fw->name);
Steven Tothe12671c2007-12-20 01:14:43 -0300586
Michael Krufky6fab81d2012-02-08 14:57:39 -0300587 ret = request_firmware(&fw, desired_fw->name,
Jean Delvaree9785252009-04-26 05:43:59 -0300588 priv->i2c_props.adap->dev.parent);
Steven Tothaacb9d32007-12-18 01:55:51 -0300589 if (ret) {
590 printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
591 ret = XC_RESULT_RESET_FAILURE;
Steven Toth5ea60532008-01-24 22:29:46 -0300592 goto out;
Steven Tothaacb9d32007-12-18 01:55:51 -0300593 } else {
Devin Heitmueller34a0db92009-04-02 22:45:17 -0300594 printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n",
Michael Krufky3f514512007-12-21 16:20:23 -0300595 fw->size);
Steven Tothaacb9d32007-12-18 01:55:51 -0300596 ret = XC_RESULT_SUCCESS;
597 }
598
Michael Krufky6fab81d2012-02-08 14:57:39 -0300599 if (fw->size != desired_fw->size) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300600 printk(KERN_ERR "xc5000: firmware incorrect size\n");
601 ret = XC_RESULT_RESET_FAILURE;
602 } else {
Devin Heitmueller34a0db92009-04-02 22:45:17 -0300603 printk(KERN_INFO "xc5000: firmware uploading...\n");
Steven Toth8f3cd532008-10-16 20:29:38 -0300604 ret = xc_load_i2c_sequence(fe, fw->data);
Devin Heitmueller34a0db92009-04-02 22:45:17 -0300605 printk(KERN_INFO "xc5000: firmware upload complete...\n");
Steven Tothaacb9d32007-12-18 01:55:51 -0300606 }
607
Steven Toth5ea60532008-01-24 22:29:46 -0300608out:
Steven Tothaacb9d32007-12-18 01:55:51 -0300609 release_firmware(fw);
610 return ret;
611}
612
Steven Tothe12671c2007-12-20 01:14:43 -0300613static void xc_debug_dump(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300614{
Steven Tothe12671c2007-12-20 01:14:43 -0300615 u16 adc_envelope;
616 u32 freq_error_hz = 0;
617 u16 lock_status;
618 u32 hsync_freq_hz = 0;
619 u16 frame_lines;
620 u16 quality;
621 u8 hw_majorversion = 0, hw_minorversion = 0;
622 u8 fw_majorversion = 0, fw_minorversion = 0;
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300623 u16 fw_buildversion = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300624
625 /* Wait for stats to stabilize.
626 * Frame Lines needs two frame times after initial lock
627 * before it is valid.
628 */
Steven Tothe12671c2007-12-20 01:14:43 -0300629 xc_wait(100);
Steven Tothaacb9d32007-12-18 01:55:51 -0300630
Steven Tothe12671c2007-12-20 01:14:43 -0300631 xc_get_ADC_Envelope(priv, &adc_envelope);
632 dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
Steven Tothaacb9d32007-12-18 01:55:51 -0300633
Steven Tothe12671c2007-12-20 01:14:43 -0300634 xc_get_frequency_error(priv, &freq_error_hz);
635 dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300636
Steven Tothe12671c2007-12-20 01:14:43 -0300637 xc_get_lock_status(priv, &lock_status);
638 dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
Steven Tothaacb9d32007-12-18 01:55:51 -0300639 lock_status);
640
641 xc_get_version(priv, &hw_majorversion, &hw_minorversion,
Steven Tothe12671c2007-12-20 01:14:43 -0300642 &fw_majorversion, &fw_minorversion);
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300643 xc_get_buildversion(priv, &fw_buildversion);
644 dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x.%04x\n",
Steven Tothaacb9d32007-12-18 01:55:51 -0300645 hw_majorversion, hw_minorversion,
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300646 fw_majorversion, fw_minorversion, fw_buildversion);
Steven Tothaacb9d32007-12-18 01:55:51 -0300647
Steven Tothe12671c2007-12-20 01:14:43 -0300648 xc_get_hsync_freq(priv, &hsync_freq_hz);
649 dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300650
Steven Tothe12671c2007-12-20 01:14:43 -0300651 xc_get_frame_lines(priv, &frame_lines);
652 dprintk(1, "*** Frame lines = %d\n", frame_lines);
Steven Tothaacb9d32007-12-18 01:55:51 -0300653
Steven Tothe12671c2007-12-20 01:14:43 -0300654 xc_get_quality(priv, &quality);
655 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
Steven Tothaacb9d32007-12-18 01:55:51 -0300656}
657
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -0300658static int xc5000_set_params(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300659{
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300660 int ret, b;
Steven Tothaacb9d32007-12-18 01:55:51 -0300661 struct xc5000_priv *priv = fe->tuner_priv;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300662 u32 bw = fe->dtv_property_cache.bandwidth_hz;
663 u32 freq = fe->dtv_property_cache.frequency;
664 u32 delsys = fe->dtv_property_cache.delivery_system;
Steven Tothaacb9d32007-12-18 01:55:51 -0300665
Devin Heitmueller760c4662009-10-13 23:44:14 -0300666 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
667 if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
668 dprintk(1, "Unable to load firmware and init tuner\n");
669 return -EINVAL;
670 }
671 }
Devin Heitmueller8e4c6792008-11-16 20:41:07 -0300672
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300673 dprintk(1, "%s() frequency=%d (Hz)\n", __func__, freq);
Steven Tothaacb9d32007-12-18 01:55:51 -0300674
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300675 switch (delsys) {
676 case SYS_ATSC:
677 dprintk(1, "%s() VSB modulation\n", __func__);
678 priv->rf_mode = XC_RF_MODE_AIR;
679 priv->freq_hz = freq - 1750000;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300680 priv->video_standard = DTV6;
681 break;
682 case SYS_DVBC_ANNEX_B:
683 dprintk(1, "%s() QAM modulation\n", __func__);
684 priv->rf_mode = XC_RF_MODE_CABLE;
685 priv->freq_hz = freq - 1750000;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300686 priv->video_standard = DTV6;
687 break;
688 case SYS_DVBT:
689 case SYS_DVBT2:
David T.L. Wong6c990802009-05-04 22:59:58 -0300690 dprintk(1, "%s() OFDM\n", __func__);
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300691 switch (bw) {
692 case 6000000:
David T.L. Wong6c990802009-05-04 22:59:58 -0300693 priv->video_standard = DTV6;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300694 priv->freq_hz = freq - 1750000;
David T.L. Wong6c990802009-05-04 22:59:58 -0300695 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300696 case 7000000:
Mauro Carvalho Chehab0433cd22011-12-09 08:01:01 -0200697 priv->video_standard = DTV7;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300698 priv->freq_hz = freq - 2250000;
Mauro Carvalho Chehab0433cd22011-12-09 08:01:01 -0200699 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300700 case 8000000:
David T.L. Wong6c990802009-05-04 22:59:58 -0300701 priv->video_standard = DTV8;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300702 priv->freq_hz = freq - 2750000;
David T.L. Wong6c990802009-05-04 22:59:58 -0300703 break;
704 default:
705 printk(KERN_ERR "xc5000 bandwidth not set!\n");
706 return -EINVAL;
707 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300708 priv->rf_mode = XC_RF_MODE_AIR;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300709 case SYS_DVBC_ANNEX_A:
710 case SYS_DVBC_ANNEX_C:
711 dprintk(1, "%s() QAM modulation\n", __func__);
712 priv->rf_mode = XC_RF_MODE_CABLE;
713 if (bw <= 6000000) {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300714 priv->video_standard = DTV6;
715 priv->freq_hz = freq - 1750000;
716 b = 6;
717 } else if (bw <= 7000000) {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300718 priv->video_standard = DTV7;
719 priv->freq_hz = freq - 2250000;
720 b = 7;
721 } else {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300722 priv->video_standard = DTV7_8;
723 priv->freq_hz = freq - 2750000;
724 b = 8;
Igor M. Liplianine80edce2011-01-25 17:03:00 -0300725 }
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300726 dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__,
727 b, bw);
728 break;
729 default:
730 printk(KERN_ERR "xc5000: delivery system is not supported!\n");
Steven Tothaacb9d32007-12-18 01:55:51 -0300731 return -EINVAL;
732 }
733
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300734 dprintk(1, "%s() frequency=%d (compensated to %d)\n",
735 __func__, freq, priv->freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300736
Steven Tothe12671c2007-12-20 01:14:43 -0300737 ret = xc_SetSignalSource(priv, priv->rf_mode);
738 if (ret != XC_RESULT_SUCCESS) {
739 printk(KERN_ERR
740 "xc5000: xc_SetSignalSource(%d) failed\n",
741 priv->rf_mode);
742 return -EREMOTEIO;
743 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300744
Steven Tothe12671c2007-12-20 01:14:43 -0300745 ret = xc_SetTVStandard(priv,
Steven Tothaacb9d32007-12-18 01:55:51 -0300746 XC5000_Standard[priv->video_standard].VideoMode,
747 XC5000_Standard[priv->video_standard].AudioMode);
Steven Tothe12671c2007-12-20 01:14:43 -0300748 if (ret != XC_RESULT_SUCCESS) {
749 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
750 return -EREMOTEIO;
751 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300752
Michael Krufky2a6003c2008-09-06 13:54:45 -0300753 ret = xc_set_IF_frequency(priv, priv->if_khz);
Steven Tothe12671c2007-12-20 01:14:43 -0300754 if (ret != XC_RESULT_SUCCESS) {
755 printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
Michael Krufky2a6003c2008-09-06 13:54:45 -0300756 priv->if_khz);
Steven Tothe12671c2007-12-20 01:14:43 -0300757 return -EIO;
758 }
759
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300760 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a);
761
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300762 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
Steven Tothe12671c2007-12-20 01:14:43 -0300763
764 if (debug)
765 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -0300766
Mauro Carvalho Chehabc6f56e72011-12-26 20:02:28 -0300767 priv->bandwidth = bw;
768
Steven Tothaacb9d32007-12-18 01:55:51 -0300769 return 0;
770}
771
Steven Tothe470d812008-06-21 21:06:02 -0300772static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
773{
774 struct xc5000_priv *priv = fe->tuner_priv;
775 int ret;
776 u16 id;
777
778 ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
779 if (ret == XC_RESULT_SUCCESS) {
780 if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
781 ret = XC_RESULT_RESET_FAILURE;
782 else
783 ret = XC_RESULT_SUCCESS;
784 }
785
786 dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
787 ret == XC_RESULT_SUCCESS ? "True" : "False", id);
788 return ret;
789}
790
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300791static int xc5000_set_tv_freq(struct dvb_frontend *fe,
Steven Toth27c685a2008-01-05 16:50:14 -0300792 struct analog_parameters *params)
793{
794 struct xc5000_priv *priv = fe->tuner_priv;
795 int ret;
796
Steven Toth27c685a2008-01-05 16:50:14 -0300797 dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300798 __func__, params->frequency);
Steven Toth27c685a2008-01-05 16:50:14 -0300799
Mauro Carvalho Chehab1fab14e2009-03-03 14:35:41 -0300800 /* Fix me: it could be air. */
801 priv->rf_mode = params->mode;
802 if (params->mode > XC_RF_MODE_CABLE)
803 priv->rf_mode = XC_RF_MODE_CABLE;
Steven Toth27c685a2008-01-05 16:50:14 -0300804
805 /* params->frequency is in units of 62.5khz */
806 priv->freq_hz = params->frequency * 62500;
807
808 /* FIX ME: Some video standards may have several possible audio
809 standards. We simply default to one of them here.
810 */
Steven Toth8f3cd532008-10-16 20:29:38 -0300811 if (params->std & V4L2_STD_MN) {
Steven Toth27c685a2008-01-05 16:50:14 -0300812 /* default to BTSC audio standard */
813 priv->video_standard = MN_NTSC_PAL_BTSC;
814 goto tune_channel;
815 }
816
Steven Toth8f3cd532008-10-16 20:29:38 -0300817 if (params->std & V4L2_STD_PAL_BG) {
Steven Toth27c685a2008-01-05 16:50:14 -0300818 /* default to NICAM audio standard */
819 priv->video_standard = BG_PAL_NICAM;
820 goto tune_channel;
821 }
822
Steven Toth8f3cd532008-10-16 20:29:38 -0300823 if (params->std & V4L2_STD_PAL_I) {
Steven Toth27c685a2008-01-05 16:50:14 -0300824 /* default to NICAM audio standard */
825 priv->video_standard = I_PAL_NICAM;
826 goto tune_channel;
827 }
828
Steven Toth8f3cd532008-10-16 20:29:38 -0300829 if (params->std & V4L2_STD_PAL_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300830 /* default to NICAM audio standard */
831 priv->video_standard = DK_PAL_NICAM;
832 goto tune_channel;
833 }
834
Steven Toth8f3cd532008-10-16 20:29:38 -0300835 if (params->std & V4L2_STD_SECAM_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300836 /* default to A2 DK1 audio standard */
837 priv->video_standard = DK_SECAM_A2DK1;
838 goto tune_channel;
839 }
840
Steven Toth8f3cd532008-10-16 20:29:38 -0300841 if (params->std & V4L2_STD_SECAM_L) {
Steven Toth27c685a2008-01-05 16:50:14 -0300842 priv->video_standard = L_SECAM_NICAM;
843 goto tune_channel;
844 }
845
Steven Toth8f3cd532008-10-16 20:29:38 -0300846 if (params->std & V4L2_STD_SECAM_LC) {
Steven Toth27c685a2008-01-05 16:50:14 -0300847 priv->video_standard = LC_SECAM_NICAM;
848 goto tune_channel;
849 }
850
851tune_channel:
852 ret = xc_SetSignalSource(priv, priv->rf_mode);
853 if (ret != XC_RESULT_SUCCESS) {
Steven Toth8f3cd532008-10-16 20:29:38 -0300854 printk(KERN_ERR
Steven Toth27c685a2008-01-05 16:50:14 -0300855 "xc5000: xc_SetSignalSource(%d) failed\n",
856 priv->rf_mode);
857 return -EREMOTEIO;
858 }
859
860 ret = xc_SetTVStandard(priv,
861 XC5000_Standard[priv->video_standard].VideoMode,
862 XC5000_Standard[priv->video_standard].AudioMode);
863 if (ret != XC_RESULT_SUCCESS) {
864 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
865 return -EREMOTEIO;
866 }
867
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300868 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
869
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300870 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
Steven Toth27c685a2008-01-05 16:50:14 -0300871
872 if (debug)
873 xc_debug_dump(priv);
874
875 return 0;
876}
877
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300878static int xc5000_set_radio_freq(struct dvb_frontend *fe,
879 struct analog_parameters *params)
880{
881 struct xc5000_priv *priv = fe->tuner_priv;
882 int ret = -EINVAL;
Devin Heitmueller496e9052009-09-24 13:27:24 -0300883 u8 radio_input;
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300884
885 dprintk(1, "%s() frequency=%d (in units of khz)\n",
886 __func__, params->frequency);
887
Devin Heitmueller496e9052009-09-24 13:27:24 -0300888 if (priv->radio_input == XC5000_RADIO_NOT_CONFIGURED) {
889 dprintk(1, "%s() radio input not configured\n", __func__);
890 return -EINVAL;
891 }
892
893 if (priv->radio_input == XC5000_RADIO_FM1)
894 radio_input = FM_Radio_INPUT1;
895 else if (priv->radio_input == XC5000_RADIO_FM2)
896 radio_input = FM_Radio_INPUT2;
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300897 else if (priv->radio_input == XC5000_RADIO_FM1_MONO)
898 radio_input = FM_Radio_INPUT1_MONO;
Devin Heitmueller496e9052009-09-24 13:27:24 -0300899 else {
900 dprintk(1, "%s() unknown radio input %d\n", __func__,
901 priv->radio_input);
902 return -EINVAL;
903 }
904
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300905 priv->freq_hz = params->frequency * 125 / 2;
906
907 priv->rf_mode = XC_RF_MODE_AIR;
908
Devin Heitmueller496e9052009-09-24 13:27:24 -0300909 ret = xc_SetTVStandard(priv, XC5000_Standard[radio_input].VideoMode,
910 XC5000_Standard[radio_input].AudioMode);
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300911
912 if (ret != XC_RESULT_SUCCESS) {
913 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
914 return -EREMOTEIO;
915 }
916
917 ret = xc_SetSignalSource(priv, priv->rf_mode);
918 if (ret != XC_RESULT_SUCCESS) {
919 printk(KERN_ERR
920 "xc5000: xc_SetSignalSource(%d) failed\n",
921 priv->rf_mode);
922 return -EREMOTEIO;
923 }
924
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300925 if ((priv->radio_input == XC5000_RADIO_FM1) ||
926 (priv->radio_input == XC5000_RADIO_FM2))
927 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
928 else if (priv->radio_input == XC5000_RADIO_FM1_MONO)
929 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x06);
930
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300931 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
932
933 return 0;
934}
935
936static int xc5000_set_analog_params(struct dvb_frontend *fe,
937 struct analog_parameters *params)
938{
939 struct xc5000_priv *priv = fe->tuner_priv;
940 int ret = -EINVAL;
941
942 if (priv->i2c_props.adap == NULL)
943 return -EINVAL;
944
Devin Heitmueller760c4662009-10-13 23:44:14 -0300945 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
946 if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
947 dprintk(1, "Unable to load firmware and init tuner\n");
948 return -EINVAL;
949 }
950 }
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300951
952 switch (params->mode) {
953 case V4L2_TUNER_RADIO:
954 ret = xc5000_set_radio_freq(fe, params);
955 break;
956 case V4L2_TUNER_ANALOG_TV:
957 case V4L2_TUNER_DIGITAL_TV:
958 ret = xc5000_set_tv_freq(fe, params);
959 break;
960 }
961
962 return ret;
963}
964
965
Steven Tothaacb9d32007-12-18 01:55:51 -0300966static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
967{
968 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300969 dprintk(1, "%s()\n", __func__);
Steven Tothe12671c2007-12-20 01:14:43 -0300970 *freq = priv->freq_hz;
Steven Tothaacb9d32007-12-18 01:55:51 -0300971 return 0;
972}
973
Mauro Carvalho Chehab35621032011-09-23 13:03:42 -0300974static int xc5000_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
975{
976 struct xc5000_priv *priv = fe->tuner_priv;
977 dprintk(1, "%s()\n", __func__);
978 *freq = priv->if_khz * 1000;
979 return 0;
980}
981
Steven Tothaacb9d32007-12-18 01:55:51 -0300982static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
983{
984 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300985 dprintk(1, "%s()\n", __func__);
Steven Toth27c685a2008-01-05 16:50:14 -0300986
Steven Tothaacb9d32007-12-18 01:55:51 -0300987 *bw = priv->bandwidth;
988 return 0;
989}
990
991static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
992{
993 struct xc5000_priv *priv = fe->tuner_priv;
Steven Tothe12671c2007-12-20 01:14:43 -0300994 u16 lock_status = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300995
996 xc_get_lock_status(priv, &lock_status);
997
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300998 dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
Steven Tothaacb9d32007-12-18 01:55:51 -0300999
1000 *status = lock_status;
1001
1002 return 0;
1003}
1004
Steven Tothe12671c2007-12-20 01:14:43 -03001005static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -03001006{
1007 struct xc5000_priv *priv = fe->tuner_priv;
Steven Toth27c685a2008-01-05 16:50:14 -03001008 int ret = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -03001009
Steven Tothe470d812008-06-21 21:06:02 -03001010 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
Steven Tothaacb9d32007-12-18 01:55:51 -03001011 ret = xc5000_fwupload(fe);
Steven Tothe12671c2007-12-20 01:14:43 -03001012 if (ret != XC_RESULT_SUCCESS)
1013 return ret;
Steven Tothaacb9d32007-12-18 01:55:51 -03001014 }
1015
1016 /* Start the tuner self-calibration process */
1017 ret |= xc_initialize(priv);
1018
1019 /* Wait for calibration to complete.
1020 * We could continue but XC5000 will clock stretch subsequent
1021 * I2C transactions until calibration is complete. This way we
1022 * don't have to rely on clock stretching working.
1023 */
Steven Toth8f3cd532008-10-16 20:29:38 -03001024 xc_wait(100);
Steven Tothaacb9d32007-12-18 01:55:51 -03001025
1026 /* Default to "CABLE" mode */
1027 ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
1028
1029 return ret;
1030}
1031
Steven Tothe12671c2007-12-20 01:14:43 -03001032static int xc5000_sleep(struct dvb_frontend *fe)
1033{
Steven Toth27c685a2008-01-05 16:50:14 -03001034 int ret;
1035
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001036 dprintk(1, "%s()\n", __func__);
Steven Tothe12671c2007-12-20 01:14:43 -03001037
Devin Heitmuellerb6bd5eb2009-04-28 13:53:38 -03001038 /* Avoid firmware reload on slow devices */
1039 if (no_poweroff)
1040 return 0;
1041
Devin Heitmueller7f05b532009-04-02 22:02:39 -03001042 /* According to Xceive technical support, the "powerdown" register
1043 was removed in newer versions of the firmware. The "supported"
1044 way to sleep the tuner is to pull the reset pin low for 10ms */
1045 ret = xc5000_TunerReset(fe);
Steven Toth8f3cd532008-10-16 20:29:38 -03001046 if (ret != XC_RESULT_SUCCESS) {
Steven Toth27c685a2008-01-05 16:50:14 -03001047 printk(KERN_ERR
1048 "xc5000: %s() unable to shutdown tuner\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001049 __func__);
Steven Toth27c685a2008-01-05 16:50:14 -03001050 return -EREMOTEIO;
Steven Toth8f3cd532008-10-16 20:29:38 -03001051 } else
Steven Toth27c685a2008-01-05 16:50:14 -03001052 return XC_RESULT_SUCCESS;
Steven Tothe12671c2007-12-20 01:14:43 -03001053}
1054
Steven Tothaacb9d32007-12-18 01:55:51 -03001055static int xc5000_init(struct dvb_frontend *fe)
1056{
1057 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001058 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -03001059
Steven Tothe12671c2007-12-20 01:14:43 -03001060 if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
1061 printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
1062 return -EREMOTEIO;
1063 }
1064
1065 if (debug)
1066 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -03001067
1068 return 0;
1069}
1070
1071static int xc5000_release(struct dvb_frontend *fe)
1072{
Michael Krufky89fd2852008-09-06 11:44:53 -03001073 struct xc5000_priv *priv = fe->tuner_priv;
1074
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001075 dprintk(1, "%s()\n", __func__);
Michael Krufky89fd2852008-09-06 11:44:53 -03001076
1077 mutex_lock(&xc5000_list_mutex);
1078
1079 if (priv)
1080 hybrid_tuner_release_state(priv);
1081
1082 mutex_unlock(&xc5000_list_mutex);
1083
Steven Tothaacb9d32007-12-18 01:55:51 -03001084 fe->tuner_priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -03001085
Steven Tothaacb9d32007-12-18 01:55:51 -03001086 return 0;
1087}
1088
Dmitri Belimov724dcbf2011-02-01 05:25:19 -03001089static int xc5000_set_config(struct dvb_frontend *fe, void *priv_cfg)
1090{
1091 struct xc5000_priv *priv = fe->tuner_priv;
1092 struct xc5000_config *p = priv_cfg;
1093
1094 dprintk(1, "%s()\n", __func__);
1095
1096 if (p->if_khz)
1097 priv->if_khz = p->if_khz;
1098
1099 if (p->radio_input)
1100 priv->radio_input = p->radio_input;
1101
1102 return 0;
1103}
1104
1105
Steven Tothaacb9d32007-12-18 01:55:51 -03001106static const struct dvb_tuner_ops xc5000_tuner_ops = {
1107 .info = {
1108 .name = "Xceive XC5000",
1109 .frequency_min = 1000000,
1110 .frequency_max = 1023000000,
1111 .frequency_step = 50000,
1112 },
1113
Steven Toth27c685a2008-01-05 16:50:14 -03001114 .release = xc5000_release,
1115 .init = xc5000_init,
1116 .sleep = xc5000_sleep,
Steven Tothaacb9d32007-12-18 01:55:51 -03001117
Dmitri Belimov724dcbf2011-02-01 05:25:19 -03001118 .set_config = xc5000_set_config,
Steven Toth27c685a2008-01-05 16:50:14 -03001119 .set_params = xc5000_set_params,
1120 .set_analog_params = xc5000_set_analog_params,
1121 .get_frequency = xc5000_get_frequency,
Mauro Carvalho Chehab35621032011-09-23 13:03:42 -03001122 .get_if_frequency = xc5000_get_if_frequency,
Steven Toth27c685a2008-01-05 16:50:14 -03001123 .get_bandwidth = xc5000_get_bandwidth,
1124 .get_status = xc5000_get_status
Steven Tothaacb9d32007-12-18 01:55:51 -03001125};
1126
Michael Krufky48723542008-05-10 14:34:09 -03001127struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
1128 struct i2c_adapter *i2c,
lawrence rust2e4e98e2010-08-25 09:50:20 -03001129 const struct xc5000_config *cfg)
Steven Tothaacb9d32007-12-18 01:55:51 -03001130{
1131 struct xc5000_priv *priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -03001132 int instance;
Steven Tothaacb9d32007-12-18 01:55:51 -03001133 u16 id = 0;
1134
Michael Krufky89fd2852008-09-06 11:44:53 -03001135 dprintk(1, "%s(%d-%04x)\n", __func__,
1136 i2c ? i2c_adapter_id(i2c) : -1,
1137 cfg ? cfg->i2c_address : -1);
Steven Tothaacb9d32007-12-18 01:55:51 -03001138
Michael Krufky89fd2852008-09-06 11:44:53 -03001139 mutex_lock(&xc5000_list_mutex);
Steven Tothaacb9d32007-12-18 01:55:51 -03001140
Michael Krufky89fd2852008-09-06 11:44:53 -03001141 instance = hybrid_tuner_request_state(struct xc5000_priv, priv,
1142 hybrid_tuner_instance_list,
1143 i2c, cfg->i2c_address, "xc5000");
1144 switch (instance) {
1145 case 0:
1146 goto fail;
1147 break;
1148 case 1:
1149 /* new tuner instance */
Mauro Carvalho Chehabc6f56e72011-12-26 20:02:28 -03001150 priv->bandwidth = 6000000;
Michael Krufky89fd2852008-09-06 11:44:53 -03001151 fe->tuner_priv = priv;
1152 break;
1153 default:
1154 /* existing tuner instance */
1155 fe->tuner_priv = priv;
1156 break;
1157 }
Steven Tothaacb9d32007-12-18 01:55:51 -03001158
Devin Heitmuellerea227862009-03-11 02:58:53 -03001159 if (priv->if_khz == 0) {
1160 /* If the IF hasn't been set yet, use the value provided by
1161 the caller (occurs in hybrid devices where the analog
1162 call to xc5000_attach occurs before the digital side) */
1163 priv->if_khz = cfg->if_khz;
1164 }
1165
Devin Heitmueller496e9052009-09-24 13:27:24 -03001166 if (priv->radio_input == 0)
1167 priv->radio_input = cfg->radio_input;
1168
Michael Krufky6fab81d2012-02-08 14:57:39 -03001169 /* don't override chip id if it's already been set
Michael Krufky76efb0ba2012-02-06 19:40:32 -03001170 unless explicitly specified */
Michael Krufky6fab81d2012-02-08 14:57:39 -03001171 if ((priv->chip_id == 0) || (cfg->chip_id))
1172 /* use default chip id if none specified, set to 0 so
1173 it can be overridden if this is a hybrid driver */
1174 priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0;
Michael Krufky76efb0ba2012-02-06 19:40:32 -03001175
Steven Toth27c685a2008-01-05 16:50:14 -03001176 /* Check if firmware has been loaded. It is possible that another
1177 instance of the driver has loaded the firmware.
1178 */
Devin Heitmueller7988fc22008-11-16 20:23:19 -03001179 if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS)
Michael Krufky89fd2852008-09-06 11:44:53 -03001180 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -03001181
Steven Toth8f3cd532008-10-16 20:29:38 -03001182 switch (id) {
Steven Toth27c685a2008-01-05 16:50:14 -03001183 case XC_PRODUCT_ID_FW_LOADED:
1184 printk(KERN_INFO
1185 "xc5000: Successfully identified at address 0x%02x\n",
1186 cfg->i2c_address);
1187 printk(KERN_INFO
1188 "xc5000: Firmware has been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -03001189 break;
1190 case XC_PRODUCT_ID_FW_NOT_LOADED:
1191 printk(KERN_INFO
1192 "xc5000: Successfully identified at address 0x%02x\n",
1193 cfg->i2c_address);
1194 printk(KERN_INFO
1195 "xc5000: Firmware has not been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -03001196 break;
1197 default:
Steven Tothaacb9d32007-12-18 01:55:51 -03001198 printk(KERN_ERR
1199 "xc5000: Device not found at addr 0x%02x (0x%x)\n",
1200 cfg->i2c_address, id);
Michael Krufky89fd2852008-09-06 11:44:53 -03001201 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -03001202 }
1203
Michael Krufky89fd2852008-09-06 11:44:53 -03001204 mutex_unlock(&xc5000_list_mutex);
1205
Steven Tothaacb9d32007-12-18 01:55:51 -03001206 memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
1207 sizeof(struct dvb_tuner_ops));
1208
Steven Tothaacb9d32007-12-18 01:55:51 -03001209 return fe;
Michael Krufky89fd2852008-09-06 11:44:53 -03001210fail:
1211 mutex_unlock(&xc5000_list_mutex);
1212
1213 xc5000_release(fe);
1214 return NULL;
Steven Tothaacb9d32007-12-18 01:55:51 -03001215}
1216EXPORT_SYMBOL(xc5000_attach);
1217
1218MODULE_AUTHOR("Steven Toth");
Steven Tothe12671c2007-12-20 01:14:43 -03001219MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
Steven Tothaacb9d32007-12-18 01:55:51 -03001220MODULE_LICENSE("GPL");