blob: 2c71ee7dcb1e6ea643d32a799d7eec3c2dbd3f24 [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
63 struct xc5000_fw_cfg *fw;
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 Krufkyddea4272012-02-07 02:39:36 -0300222static inline struct xc5000_fw_cfg *xc5000_assign_firmware(int fw)
223{
224 switch (fw) {
225 default:
226 case XC5000_FW_A_1_6_114:
227 return &xc5000a_1_6_114;
228 case XC5000_FW_C_41_024_5_31875:
229 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;
581
Steven Tothe12671c2007-12-20 01:14:43 -0300582 /* request the firmware, this will block and timeout */
583 printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
Michael Krufky76efb0ba2012-02-06 19:40:32 -0300584 priv->fw->name);
Steven Tothe12671c2007-12-20 01:14:43 -0300585
Michael Krufky76efb0ba2012-02-06 19:40:32 -0300586 ret = request_firmware(&fw, priv->fw->name,
Jean Delvaree9785252009-04-26 05:43:59 -0300587 priv->i2c_props.adap->dev.parent);
Steven Tothaacb9d32007-12-18 01:55:51 -0300588 if (ret) {
589 printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
590 ret = XC_RESULT_RESET_FAILURE;
Steven Toth5ea60532008-01-24 22:29:46 -0300591 goto out;
Steven Tothaacb9d32007-12-18 01:55:51 -0300592 } else {
Devin Heitmueller34a0db92009-04-02 22:45:17 -0300593 printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n",
Michael Krufky3f514512007-12-21 16:20:23 -0300594 fw->size);
Steven Tothaacb9d32007-12-18 01:55:51 -0300595 ret = XC_RESULT_SUCCESS;
596 }
597
Michael Krufky76efb0ba2012-02-06 19:40:32 -0300598 if (fw->size != priv->fw->size) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300599 printk(KERN_ERR "xc5000: firmware incorrect size\n");
600 ret = XC_RESULT_RESET_FAILURE;
601 } else {
Devin Heitmueller34a0db92009-04-02 22:45:17 -0300602 printk(KERN_INFO "xc5000: firmware uploading...\n");
Steven Toth8f3cd532008-10-16 20:29:38 -0300603 ret = xc_load_i2c_sequence(fe, fw->data);
Devin Heitmueller34a0db92009-04-02 22:45:17 -0300604 printk(KERN_INFO "xc5000: firmware upload complete...\n");
Steven Tothaacb9d32007-12-18 01:55:51 -0300605 }
606
Steven Toth5ea60532008-01-24 22:29:46 -0300607out:
Steven Tothaacb9d32007-12-18 01:55:51 -0300608 release_firmware(fw);
609 return ret;
610}
611
Steven Tothe12671c2007-12-20 01:14:43 -0300612static void xc_debug_dump(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300613{
Steven Tothe12671c2007-12-20 01:14:43 -0300614 u16 adc_envelope;
615 u32 freq_error_hz = 0;
616 u16 lock_status;
617 u32 hsync_freq_hz = 0;
618 u16 frame_lines;
619 u16 quality;
620 u8 hw_majorversion = 0, hw_minorversion = 0;
621 u8 fw_majorversion = 0, fw_minorversion = 0;
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300622 u16 fw_buildversion = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300623
624 /* Wait for stats to stabilize.
625 * Frame Lines needs two frame times after initial lock
626 * before it is valid.
627 */
Steven Tothe12671c2007-12-20 01:14:43 -0300628 xc_wait(100);
Steven Tothaacb9d32007-12-18 01:55:51 -0300629
Steven Tothe12671c2007-12-20 01:14:43 -0300630 xc_get_ADC_Envelope(priv, &adc_envelope);
631 dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
Steven Tothaacb9d32007-12-18 01:55:51 -0300632
Steven Tothe12671c2007-12-20 01:14:43 -0300633 xc_get_frequency_error(priv, &freq_error_hz);
634 dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300635
Steven Tothe12671c2007-12-20 01:14:43 -0300636 xc_get_lock_status(priv, &lock_status);
637 dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
Steven Tothaacb9d32007-12-18 01:55:51 -0300638 lock_status);
639
640 xc_get_version(priv, &hw_majorversion, &hw_minorversion,
Steven Tothe12671c2007-12-20 01:14:43 -0300641 &fw_majorversion, &fw_minorversion);
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300642 xc_get_buildversion(priv, &fw_buildversion);
643 dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x.%04x\n",
Steven Tothaacb9d32007-12-18 01:55:51 -0300644 hw_majorversion, hw_minorversion,
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300645 fw_majorversion, fw_minorversion, fw_buildversion);
Steven Tothaacb9d32007-12-18 01:55:51 -0300646
Steven Tothe12671c2007-12-20 01:14:43 -0300647 xc_get_hsync_freq(priv, &hsync_freq_hz);
648 dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300649
Steven Tothe12671c2007-12-20 01:14:43 -0300650 xc_get_frame_lines(priv, &frame_lines);
651 dprintk(1, "*** Frame lines = %d\n", frame_lines);
Steven Tothaacb9d32007-12-18 01:55:51 -0300652
Steven Tothe12671c2007-12-20 01:14:43 -0300653 xc_get_quality(priv, &quality);
654 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
Steven Tothaacb9d32007-12-18 01:55:51 -0300655}
656
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -0300657static int xc5000_set_params(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300658{
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300659 int ret, b;
Steven Tothaacb9d32007-12-18 01:55:51 -0300660 struct xc5000_priv *priv = fe->tuner_priv;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300661 u32 bw = fe->dtv_property_cache.bandwidth_hz;
662 u32 freq = fe->dtv_property_cache.frequency;
663 u32 delsys = fe->dtv_property_cache.delivery_system;
Steven Tothaacb9d32007-12-18 01:55:51 -0300664
Devin Heitmueller760c4662009-10-13 23:44:14 -0300665 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
666 if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
667 dprintk(1, "Unable to load firmware and init tuner\n");
668 return -EINVAL;
669 }
670 }
Devin Heitmueller8e4c6792008-11-16 20:41:07 -0300671
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300672 dprintk(1, "%s() frequency=%d (Hz)\n", __func__, freq);
Steven Tothaacb9d32007-12-18 01:55:51 -0300673
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300674 switch (delsys) {
675 case SYS_ATSC:
676 dprintk(1, "%s() VSB modulation\n", __func__);
677 priv->rf_mode = XC_RF_MODE_AIR;
678 priv->freq_hz = freq - 1750000;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300679 priv->video_standard = DTV6;
680 break;
681 case SYS_DVBC_ANNEX_B:
682 dprintk(1, "%s() QAM modulation\n", __func__);
683 priv->rf_mode = XC_RF_MODE_CABLE;
684 priv->freq_hz = freq - 1750000;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300685 priv->video_standard = DTV6;
686 break;
687 case SYS_DVBT:
688 case SYS_DVBT2:
David T.L. Wong6c990802009-05-04 22:59:58 -0300689 dprintk(1, "%s() OFDM\n", __func__);
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300690 switch (bw) {
691 case 6000000:
David T.L. Wong6c990802009-05-04 22:59:58 -0300692 priv->video_standard = DTV6;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300693 priv->freq_hz = freq - 1750000;
David T.L. Wong6c990802009-05-04 22:59:58 -0300694 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300695 case 7000000:
Mauro Carvalho Chehab0433cd22011-12-09 08:01:01 -0200696 priv->video_standard = DTV7;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300697 priv->freq_hz = freq - 2250000;
Mauro Carvalho Chehab0433cd22011-12-09 08:01:01 -0200698 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300699 case 8000000:
David T.L. Wong6c990802009-05-04 22:59:58 -0300700 priv->video_standard = DTV8;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300701 priv->freq_hz = freq - 2750000;
David T.L. Wong6c990802009-05-04 22:59:58 -0300702 break;
703 default:
704 printk(KERN_ERR "xc5000 bandwidth not set!\n");
705 return -EINVAL;
706 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300707 priv->rf_mode = XC_RF_MODE_AIR;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300708 case SYS_DVBC_ANNEX_A:
709 case SYS_DVBC_ANNEX_C:
710 dprintk(1, "%s() QAM modulation\n", __func__);
711 priv->rf_mode = XC_RF_MODE_CABLE;
712 if (bw <= 6000000) {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300713 priv->video_standard = DTV6;
714 priv->freq_hz = freq - 1750000;
715 b = 6;
716 } else if (bw <= 7000000) {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300717 priv->video_standard = DTV7;
718 priv->freq_hz = freq - 2250000;
719 b = 7;
720 } else {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300721 priv->video_standard = DTV7_8;
722 priv->freq_hz = freq - 2750000;
723 b = 8;
Igor M. Liplianine80edce2011-01-25 17:03:00 -0300724 }
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300725 dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__,
726 b, bw);
727 break;
728 default:
729 printk(KERN_ERR "xc5000: delivery system is not supported!\n");
Steven Tothaacb9d32007-12-18 01:55:51 -0300730 return -EINVAL;
731 }
732
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300733 dprintk(1, "%s() frequency=%d (compensated to %d)\n",
734 __func__, freq, priv->freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300735
Steven Tothe12671c2007-12-20 01:14:43 -0300736 ret = xc_SetSignalSource(priv, priv->rf_mode);
737 if (ret != XC_RESULT_SUCCESS) {
738 printk(KERN_ERR
739 "xc5000: xc_SetSignalSource(%d) failed\n",
740 priv->rf_mode);
741 return -EREMOTEIO;
742 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300743
Steven Tothe12671c2007-12-20 01:14:43 -0300744 ret = xc_SetTVStandard(priv,
Steven Tothaacb9d32007-12-18 01:55:51 -0300745 XC5000_Standard[priv->video_standard].VideoMode,
746 XC5000_Standard[priv->video_standard].AudioMode);
Steven Tothe12671c2007-12-20 01:14:43 -0300747 if (ret != XC_RESULT_SUCCESS) {
748 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
749 return -EREMOTEIO;
750 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300751
Michael Krufky2a6003c2008-09-06 13:54:45 -0300752 ret = xc_set_IF_frequency(priv, priv->if_khz);
Steven Tothe12671c2007-12-20 01:14:43 -0300753 if (ret != XC_RESULT_SUCCESS) {
754 printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
Michael Krufky2a6003c2008-09-06 13:54:45 -0300755 priv->if_khz);
Steven Tothe12671c2007-12-20 01:14:43 -0300756 return -EIO;
757 }
758
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300759 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a);
760
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300761 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
Steven Tothe12671c2007-12-20 01:14:43 -0300762
763 if (debug)
764 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -0300765
Mauro Carvalho Chehabc6f56e72011-12-26 20:02:28 -0300766 priv->bandwidth = bw;
767
Steven Tothaacb9d32007-12-18 01:55:51 -0300768 return 0;
769}
770
Steven Tothe470d812008-06-21 21:06:02 -0300771static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
772{
773 struct xc5000_priv *priv = fe->tuner_priv;
774 int ret;
775 u16 id;
776
777 ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
778 if (ret == XC_RESULT_SUCCESS) {
779 if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
780 ret = XC_RESULT_RESET_FAILURE;
781 else
782 ret = XC_RESULT_SUCCESS;
783 }
784
785 dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
786 ret == XC_RESULT_SUCCESS ? "True" : "False", id);
787 return ret;
788}
789
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300790static int xc5000_set_tv_freq(struct dvb_frontend *fe,
Steven Toth27c685a2008-01-05 16:50:14 -0300791 struct analog_parameters *params)
792{
793 struct xc5000_priv *priv = fe->tuner_priv;
794 int ret;
795
Steven Toth27c685a2008-01-05 16:50:14 -0300796 dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300797 __func__, params->frequency);
Steven Toth27c685a2008-01-05 16:50:14 -0300798
Mauro Carvalho Chehab1fab14e2009-03-03 14:35:41 -0300799 /* Fix me: it could be air. */
800 priv->rf_mode = params->mode;
801 if (params->mode > XC_RF_MODE_CABLE)
802 priv->rf_mode = XC_RF_MODE_CABLE;
Steven Toth27c685a2008-01-05 16:50:14 -0300803
804 /* params->frequency is in units of 62.5khz */
805 priv->freq_hz = params->frequency * 62500;
806
807 /* FIX ME: Some video standards may have several possible audio
808 standards. We simply default to one of them here.
809 */
Steven Toth8f3cd532008-10-16 20:29:38 -0300810 if (params->std & V4L2_STD_MN) {
Steven Toth27c685a2008-01-05 16:50:14 -0300811 /* default to BTSC audio standard */
812 priv->video_standard = MN_NTSC_PAL_BTSC;
813 goto tune_channel;
814 }
815
Steven Toth8f3cd532008-10-16 20:29:38 -0300816 if (params->std & V4L2_STD_PAL_BG) {
Steven Toth27c685a2008-01-05 16:50:14 -0300817 /* default to NICAM audio standard */
818 priv->video_standard = BG_PAL_NICAM;
819 goto tune_channel;
820 }
821
Steven Toth8f3cd532008-10-16 20:29:38 -0300822 if (params->std & V4L2_STD_PAL_I) {
Steven Toth27c685a2008-01-05 16:50:14 -0300823 /* default to NICAM audio standard */
824 priv->video_standard = I_PAL_NICAM;
825 goto tune_channel;
826 }
827
Steven Toth8f3cd532008-10-16 20:29:38 -0300828 if (params->std & V4L2_STD_PAL_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300829 /* default to NICAM audio standard */
830 priv->video_standard = DK_PAL_NICAM;
831 goto tune_channel;
832 }
833
Steven Toth8f3cd532008-10-16 20:29:38 -0300834 if (params->std & V4L2_STD_SECAM_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300835 /* default to A2 DK1 audio standard */
836 priv->video_standard = DK_SECAM_A2DK1;
837 goto tune_channel;
838 }
839
Steven Toth8f3cd532008-10-16 20:29:38 -0300840 if (params->std & V4L2_STD_SECAM_L) {
Steven Toth27c685a2008-01-05 16:50:14 -0300841 priv->video_standard = L_SECAM_NICAM;
842 goto tune_channel;
843 }
844
Steven Toth8f3cd532008-10-16 20:29:38 -0300845 if (params->std & V4L2_STD_SECAM_LC) {
Steven Toth27c685a2008-01-05 16:50:14 -0300846 priv->video_standard = LC_SECAM_NICAM;
847 goto tune_channel;
848 }
849
850tune_channel:
851 ret = xc_SetSignalSource(priv, priv->rf_mode);
852 if (ret != XC_RESULT_SUCCESS) {
Steven Toth8f3cd532008-10-16 20:29:38 -0300853 printk(KERN_ERR
Steven Toth27c685a2008-01-05 16:50:14 -0300854 "xc5000: xc_SetSignalSource(%d) failed\n",
855 priv->rf_mode);
856 return -EREMOTEIO;
857 }
858
859 ret = xc_SetTVStandard(priv,
860 XC5000_Standard[priv->video_standard].VideoMode,
861 XC5000_Standard[priv->video_standard].AudioMode);
862 if (ret != XC_RESULT_SUCCESS) {
863 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
864 return -EREMOTEIO;
865 }
866
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300867 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
868
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300869 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
Steven Toth27c685a2008-01-05 16:50:14 -0300870
871 if (debug)
872 xc_debug_dump(priv);
873
874 return 0;
875}
876
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300877static int xc5000_set_radio_freq(struct dvb_frontend *fe,
878 struct analog_parameters *params)
879{
880 struct xc5000_priv *priv = fe->tuner_priv;
881 int ret = -EINVAL;
Devin Heitmueller496e9052009-09-24 13:27:24 -0300882 u8 radio_input;
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300883
884 dprintk(1, "%s() frequency=%d (in units of khz)\n",
885 __func__, params->frequency);
886
Devin Heitmueller496e9052009-09-24 13:27:24 -0300887 if (priv->radio_input == XC5000_RADIO_NOT_CONFIGURED) {
888 dprintk(1, "%s() radio input not configured\n", __func__);
889 return -EINVAL;
890 }
891
892 if (priv->radio_input == XC5000_RADIO_FM1)
893 radio_input = FM_Radio_INPUT1;
894 else if (priv->radio_input == XC5000_RADIO_FM2)
895 radio_input = FM_Radio_INPUT2;
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300896 else if (priv->radio_input == XC5000_RADIO_FM1_MONO)
897 radio_input = FM_Radio_INPUT1_MONO;
Devin Heitmueller496e9052009-09-24 13:27:24 -0300898 else {
899 dprintk(1, "%s() unknown radio input %d\n", __func__,
900 priv->radio_input);
901 return -EINVAL;
902 }
903
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300904 priv->freq_hz = params->frequency * 125 / 2;
905
906 priv->rf_mode = XC_RF_MODE_AIR;
907
Devin Heitmueller496e9052009-09-24 13:27:24 -0300908 ret = xc_SetTVStandard(priv, XC5000_Standard[radio_input].VideoMode,
909 XC5000_Standard[radio_input].AudioMode);
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300910
911 if (ret != XC_RESULT_SUCCESS) {
912 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
913 return -EREMOTEIO;
914 }
915
916 ret = xc_SetSignalSource(priv, priv->rf_mode);
917 if (ret != XC_RESULT_SUCCESS) {
918 printk(KERN_ERR
919 "xc5000: xc_SetSignalSource(%d) failed\n",
920 priv->rf_mode);
921 return -EREMOTEIO;
922 }
923
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300924 if ((priv->radio_input == XC5000_RADIO_FM1) ||
925 (priv->radio_input == XC5000_RADIO_FM2))
926 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
927 else if (priv->radio_input == XC5000_RADIO_FM1_MONO)
928 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x06);
929
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300930 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
931
932 return 0;
933}
934
935static int xc5000_set_analog_params(struct dvb_frontend *fe,
936 struct analog_parameters *params)
937{
938 struct xc5000_priv *priv = fe->tuner_priv;
939 int ret = -EINVAL;
940
941 if (priv->i2c_props.adap == NULL)
942 return -EINVAL;
943
Devin Heitmueller760c4662009-10-13 23:44:14 -0300944 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
945 if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
946 dprintk(1, "Unable to load firmware and init tuner\n");
947 return -EINVAL;
948 }
949 }
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300950
951 switch (params->mode) {
952 case V4L2_TUNER_RADIO:
953 ret = xc5000_set_radio_freq(fe, params);
954 break;
955 case V4L2_TUNER_ANALOG_TV:
956 case V4L2_TUNER_DIGITAL_TV:
957 ret = xc5000_set_tv_freq(fe, params);
958 break;
959 }
960
961 return ret;
962}
963
964
Steven Tothaacb9d32007-12-18 01:55:51 -0300965static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
966{
967 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300968 dprintk(1, "%s()\n", __func__);
Steven Tothe12671c2007-12-20 01:14:43 -0300969 *freq = priv->freq_hz;
Steven Tothaacb9d32007-12-18 01:55:51 -0300970 return 0;
971}
972
Mauro Carvalho Chehab35621032011-09-23 13:03:42 -0300973static int xc5000_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
974{
975 struct xc5000_priv *priv = fe->tuner_priv;
976 dprintk(1, "%s()\n", __func__);
977 *freq = priv->if_khz * 1000;
978 return 0;
979}
980
Steven Tothaacb9d32007-12-18 01:55:51 -0300981static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
982{
983 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300984 dprintk(1, "%s()\n", __func__);
Steven Toth27c685a2008-01-05 16:50:14 -0300985
Steven Tothaacb9d32007-12-18 01:55:51 -0300986 *bw = priv->bandwidth;
987 return 0;
988}
989
990static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
991{
992 struct xc5000_priv *priv = fe->tuner_priv;
Steven Tothe12671c2007-12-20 01:14:43 -0300993 u16 lock_status = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300994
995 xc_get_lock_status(priv, &lock_status);
996
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300997 dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
Steven Tothaacb9d32007-12-18 01:55:51 -0300998
999 *status = lock_status;
1000
1001 return 0;
1002}
1003
Steven Tothe12671c2007-12-20 01:14:43 -03001004static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -03001005{
1006 struct xc5000_priv *priv = fe->tuner_priv;
Steven Toth27c685a2008-01-05 16:50:14 -03001007 int ret = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -03001008
Steven Tothe470d812008-06-21 21:06:02 -03001009 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
Steven Tothaacb9d32007-12-18 01:55:51 -03001010 ret = xc5000_fwupload(fe);
Steven Tothe12671c2007-12-20 01:14:43 -03001011 if (ret != XC_RESULT_SUCCESS)
1012 return ret;
Steven Tothaacb9d32007-12-18 01:55:51 -03001013 }
1014
1015 /* Start the tuner self-calibration process */
1016 ret |= xc_initialize(priv);
1017
1018 /* Wait for calibration to complete.
1019 * We could continue but XC5000 will clock stretch subsequent
1020 * I2C transactions until calibration is complete. This way we
1021 * don't have to rely on clock stretching working.
1022 */
Steven Toth8f3cd532008-10-16 20:29:38 -03001023 xc_wait(100);
Steven Tothaacb9d32007-12-18 01:55:51 -03001024
1025 /* Default to "CABLE" mode */
1026 ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
1027
1028 return ret;
1029}
1030
Steven Tothe12671c2007-12-20 01:14:43 -03001031static int xc5000_sleep(struct dvb_frontend *fe)
1032{
Steven Toth27c685a2008-01-05 16:50:14 -03001033 int ret;
1034
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001035 dprintk(1, "%s()\n", __func__);
Steven Tothe12671c2007-12-20 01:14:43 -03001036
Devin Heitmuellerb6bd5eb2009-04-28 13:53:38 -03001037 /* Avoid firmware reload on slow devices */
1038 if (no_poweroff)
1039 return 0;
1040
Devin Heitmueller7f05b532009-04-02 22:02:39 -03001041 /* According to Xceive technical support, the "powerdown" register
1042 was removed in newer versions of the firmware. The "supported"
1043 way to sleep the tuner is to pull the reset pin low for 10ms */
1044 ret = xc5000_TunerReset(fe);
Steven Toth8f3cd532008-10-16 20:29:38 -03001045 if (ret != XC_RESULT_SUCCESS) {
Steven Toth27c685a2008-01-05 16:50:14 -03001046 printk(KERN_ERR
1047 "xc5000: %s() unable to shutdown tuner\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001048 __func__);
Steven Toth27c685a2008-01-05 16:50:14 -03001049 return -EREMOTEIO;
Steven Toth8f3cd532008-10-16 20:29:38 -03001050 } else
Steven Toth27c685a2008-01-05 16:50:14 -03001051 return XC_RESULT_SUCCESS;
Steven Tothe12671c2007-12-20 01:14:43 -03001052}
1053
Steven Tothaacb9d32007-12-18 01:55:51 -03001054static int xc5000_init(struct dvb_frontend *fe)
1055{
1056 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001057 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -03001058
Steven Tothe12671c2007-12-20 01:14:43 -03001059 if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
1060 printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
1061 return -EREMOTEIO;
1062 }
1063
1064 if (debug)
1065 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -03001066
1067 return 0;
1068}
1069
1070static int xc5000_release(struct dvb_frontend *fe)
1071{
Michael Krufky89fd2852008-09-06 11:44:53 -03001072 struct xc5000_priv *priv = fe->tuner_priv;
1073
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001074 dprintk(1, "%s()\n", __func__);
Michael Krufky89fd2852008-09-06 11:44:53 -03001075
1076 mutex_lock(&xc5000_list_mutex);
1077
1078 if (priv)
1079 hybrid_tuner_release_state(priv);
1080
1081 mutex_unlock(&xc5000_list_mutex);
1082
Steven Tothaacb9d32007-12-18 01:55:51 -03001083 fe->tuner_priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -03001084
Steven Tothaacb9d32007-12-18 01:55:51 -03001085 return 0;
1086}
1087
Dmitri Belimov724dcbf2011-02-01 05:25:19 -03001088static int xc5000_set_config(struct dvb_frontend *fe, void *priv_cfg)
1089{
1090 struct xc5000_priv *priv = fe->tuner_priv;
1091 struct xc5000_config *p = priv_cfg;
1092
1093 dprintk(1, "%s()\n", __func__);
1094
1095 if (p->if_khz)
1096 priv->if_khz = p->if_khz;
1097
1098 if (p->radio_input)
1099 priv->radio_input = p->radio_input;
1100
1101 return 0;
1102}
1103
1104
Steven Tothaacb9d32007-12-18 01:55:51 -03001105static const struct dvb_tuner_ops xc5000_tuner_ops = {
1106 .info = {
1107 .name = "Xceive XC5000",
1108 .frequency_min = 1000000,
1109 .frequency_max = 1023000000,
1110 .frequency_step = 50000,
1111 },
1112
Steven Toth27c685a2008-01-05 16:50:14 -03001113 .release = xc5000_release,
1114 .init = xc5000_init,
1115 .sleep = xc5000_sleep,
Steven Tothaacb9d32007-12-18 01:55:51 -03001116
Dmitri Belimov724dcbf2011-02-01 05:25:19 -03001117 .set_config = xc5000_set_config,
Steven Toth27c685a2008-01-05 16:50:14 -03001118 .set_params = xc5000_set_params,
1119 .set_analog_params = xc5000_set_analog_params,
1120 .get_frequency = xc5000_get_frequency,
Mauro Carvalho Chehab35621032011-09-23 13:03:42 -03001121 .get_if_frequency = xc5000_get_if_frequency,
Steven Toth27c685a2008-01-05 16:50:14 -03001122 .get_bandwidth = xc5000_get_bandwidth,
1123 .get_status = xc5000_get_status
Steven Tothaacb9d32007-12-18 01:55:51 -03001124};
1125
Michael Krufky48723542008-05-10 14:34:09 -03001126struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
1127 struct i2c_adapter *i2c,
lawrence rust2e4e98e2010-08-25 09:50:20 -03001128 const struct xc5000_config *cfg)
Steven Tothaacb9d32007-12-18 01:55:51 -03001129{
1130 struct xc5000_priv *priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -03001131 int instance;
Steven Tothaacb9d32007-12-18 01:55:51 -03001132 u16 id = 0;
1133
Michael Krufky89fd2852008-09-06 11:44:53 -03001134 dprintk(1, "%s(%d-%04x)\n", __func__,
1135 i2c ? i2c_adapter_id(i2c) : -1,
1136 cfg ? cfg->i2c_address : -1);
Steven Tothaacb9d32007-12-18 01:55:51 -03001137
Michael Krufky89fd2852008-09-06 11:44:53 -03001138 mutex_lock(&xc5000_list_mutex);
Steven Tothaacb9d32007-12-18 01:55:51 -03001139
Michael Krufky89fd2852008-09-06 11:44:53 -03001140 instance = hybrid_tuner_request_state(struct xc5000_priv, priv,
1141 hybrid_tuner_instance_list,
1142 i2c, cfg->i2c_address, "xc5000");
1143 switch (instance) {
1144 case 0:
1145 goto fail;
1146 break;
1147 case 1:
1148 /* new tuner instance */
Mauro Carvalho Chehabc6f56e72011-12-26 20:02:28 -03001149 priv->bandwidth = 6000000;
Michael Krufky89fd2852008-09-06 11:44:53 -03001150 fe->tuner_priv = priv;
1151 break;
1152 default:
1153 /* existing tuner instance */
1154 fe->tuner_priv = priv;
1155 break;
1156 }
Steven Tothaacb9d32007-12-18 01:55:51 -03001157
Devin Heitmuellerea227862009-03-11 02:58:53 -03001158 if (priv->if_khz == 0) {
1159 /* If the IF hasn't been set yet, use the value provided by
1160 the caller (occurs in hybrid devices where the analog
1161 call to xc5000_attach occurs before the digital side) */
1162 priv->if_khz = cfg->if_khz;
1163 }
1164
Devin Heitmueller496e9052009-09-24 13:27:24 -03001165 if (priv->radio_input == 0)
1166 priv->radio_input = cfg->radio_input;
1167
Michael Krufky76efb0ba2012-02-06 19:40:32 -03001168 /* don't override firmware filename if it's already been set
1169 unless explicitly specified */
1170 if ((priv->fw == NULL) || (cfg->fw))
1171 /* use default firmware if none specified */
Michael Krufkyddea4272012-02-07 02:39:36 -03001172 priv->fw = xc5000_assign_firmware((cfg->fw) ?
1173 cfg->fw : XC5000_DEFAULT_FIRMWARE);
Michael Krufky76efb0ba2012-02-06 19:40:32 -03001174
Steven Toth27c685a2008-01-05 16:50:14 -03001175 /* Check if firmware has been loaded. It is possible that another
1176 instance of the driver has loaded the firmware.
1177 */
Devin Heitmueller7988fc22008-11-16 20:23:19 -03001178 if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS)
Michael Krufky89fd2852008-09-06 11:44:53 -03001179 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -03001180
Steven Toth8f3cd532008-10-16 20:29:38 -03001181 switch (id) {
Steven Toth27c685a2008-01-05 16:50:14 -03001182 case XC_PRODUCT_ID_FW_LOADED:
1183 printk(KERN_INFO
1184 "xc5000: Successfully identified at address 0x%02x\n",
1185 cfg->i2c_address);
1186 printk(KERN_INFO
1187 "xc5000: Firmware has been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -03001188 break;
1189 case XC_PRODUCT_ID_FW_NOT_LOADED:
1190 printk(KERN_INFO
1191 "xc5000: Successfully identified at address 0x%02x\n",
1192 cfg->i2c_address);
1193 printk(KERN_INFO
1194 "xc5000: Firmware has not been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -03001195 break;
1196 default:
Steven Tothaacb9d32007-12-18 01:55:51 -03001197 printk(KERN_ERR
1198 "xc5000: Device not found at addr 0x%02x (0x%x)\n",
1199 cfg->i2c_address, id);
Michael Krufky89fd2852008-09-06 11:44:53 -03001200 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -03001201 }
1202
Michael Krufky89fd2852008-09-06 11:44:53 -03001203 mutex_unlock(&xc5000_list_mutex);
1204
Steven Tothaacb9d32007-12-18 01:55:51 -03001205 memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
1206 sizeof(struct dvb_tuner_ops));
1207
Steven Tothaacb9d32007-12-18 01:55:51 -03001208 return fe;
Michael Krufky89fd2852008-09-06 11:44:53 -03001209fail:
1210 mutex_unlock(&xc5000_list_mutex);
1211
1212 xc5000_release(fe);
1213 return NULL;
Steven Tothaacb9d32007-12-18 01:55:51 -03001214}
1215EXPORT_SYMBOL(xc5000_attach);
1216
1217MODULE_AUTHOR("Steven Toth");
Steven Tothe12671c2007-12-20 01:14:43 -03001218MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
Steven Tothaacb9d32007-12-18 01:55:51 -03001219MODULE_LICENSE("GPL");