blob: bf2fdb36e954bbc5ff1284f91c00c213f3d1b30a [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>
Steven Tothaacb9d32007-12-18 01:55:51 -03006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 *
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/moduleparam.h>
Steven Toth49170192008-01-15 21:57:14 -030025#include <linux/videodev2.h>
Steven Tothaacb9d32007-12-18 01:55:51 -030026#include <linux/delay.h>
27#include <linux/dvb/frontend.h>
28#include <linux/i2c.h>
29
30#include "dvb_frontend.h"
31
32#include "xc5000.h"
Michael Krufky89fd2852008-09-06 11:44:53 -030033#include "tuner-i2c.h"
Steven Tothaacb9d32007-12-18 01:55:51 -030034
35static int debug;
36module_param(debug, int, 0644);
37MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
38
Michael Krufky89fd2852008-09-06 11:44:53 -030039static DEFINE_MUTEX(xc5000_list_mutex);
40static LIST_HEAD(hybrid_tuner_instance_list);
41
Steven Toth8f3cd532008-10-16 20:29:38 -030042#define dprintk(level, fmt, arg...) if (debug >= level) \
Steven Tothaacb9d32007-12-18 01:55:51 -030043 printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
44
45#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
Steven Toth71bc9bd2007-12-27 14:33:30 -030046#define XC5000_DEFAULT_FIRMWARE_SIZE 12332
Steven Tothaacb9d32007-12-18 01:55:51 -030047
Michael Krufkyffb41232008-09-06 10:52:30 -030048struct xc5000_priv {
Michael Krufky89fd2852008-09-06 11:44:53 -030049 struct tuner_i2c_props i2c_props;
50 struct list_head hybrid_tuner_instance_list;
Michael Krufkyffb41232008-09-06 10:52:30 -030051
Michael Krufky2a6003c2008-09-06 13:54:45 -030052 u32 if_khz;
Michael Krufkyffb41232008-09-06 10:52:30 -030053 u32 freq_hz;
54 u32 bandwidth;
55 u8 video_standard;
56 u8 rf_mode;
Michael Krufkyffb41232008-09-06 10:52:30 -030057};
58
Steven Tothaacb9d32007-12-18 01:55:51 -030059/* Misc Defines */
60#define MAX_TV_STANDARD 23
61#define XC_MAX_I2C_WRITE_LENGTH 64
62
63/* Signal Types */
64#define XC_RF_MODE_AIR 0
65#define XC_RF_MODE_CABLE 1
66
67/* Result codes */
68#define XC_RESULT_SUCCESS 0
69#define XC_RESULT_RESET_FAILURE 1
70#define XC_RESULT_I2C_WRITE_FAILURE 2
71#define XC_RESULT_I2C_READ_FAILURE 3
72#define XC_RESULT_OUT_OF_RANGE 5
73
Steven Toth27c685a2008-01-05 16:50:14 -030074/* Product id */
75#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
76#define XC_PRODUCT_ID_FW_LOADED 0x1388
77
Steven Tothaacb9d32007-12-18 01:55:51 -030078/* Registers */
79#define XREG_INIT 0x00
80#define XREG_VIDEO_MODE 0x01
81#define XREG_AUDIO_MODE 0x02
82#define XREG_RF_FREQ 0x03
83#define XREG_D_CODE 0x04
84#define XREG_IF_OUT 0x05
85#define XREG_SEEK_MODE 0x07
86#define XREG_POWER_DOWN 0x0A
87#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
88#define XREG_SMOOTHEDCVBS 0x0E
89#define XREG_XTALFREQ 0x0F
90#define XREG_FINERFFREQ 0x10
91#define XREG_DDIMODE 0x11
92
93#define XREG_ADC_ENV 0x00
94#define XREG_QUALITY 0x01
95#define XREG_FRAME_LINES 0x02
96#define XREG_HSYNC_FREQ 0x03
97#define XREG_LOCK 0x04
98#define XREG_FREQ_ERROR 0x05
99#define XREG_SNR 0x06
100#define XREG_VERSION 0x07
101#define XREG_PRODUCT_ID 0x08
102#define XREG_BUSY 0x09
103
104/*
105 Basic firmware description. This will remain with
106 the driver for documentation purposes.
107
108 This represents an I2C firmware file encoded as a
109 string of unsigned char. Format is as follows:
110
111 char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB
112 char[1 ]=len0_LSB -> length of first write transaction
113 char[2 ]=data0 -> first byte to be sent
114 char[3 ]=data1
115 char[4 ]=data2
116 char[ ]=...
117 char[M ]=dataN -> last byte to be sent
118 char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB
119 char[M+2]=len1_LSB -> length of second write transaction
120 char[M+3]=data0
121 char[M+4]=data1
122 ...
123 etc.
124
125 The [len] value should be interpreted as follows:
126
127 len= len_MSB _ len_LSB
128 len=1111_1111_1111_1111 : End of I2C_SEQUENCE
129 len=0000_0000_0000_0000 : Reset command: Do hardware reset
130 len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767)
131 len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms
132
133 For the RESET and WAIT commands, the two following bytes will contain
134 immediately the length of the following transaction.
135
136*/
Steven Toth8f3cd532008-10-16 20:29:38 -0300137struct XC_TV_STANDARD {
Steven Tothaacb9d32007-12-18 01:55:51 -0300138 char *Name;
Steven Tothe12671cf2007-12-20 01:14:43 -0300139 u16 AudioMode;
140 u16 VideoMode;
Steven Toth8f3cd532008-10-16 20:29:38 -0300141};
Steven Tothaacb9d32007-12-18 01:55:51 -0300142
143/* Tuner standards */
Steven Toth27c685a2008-01-05 16:50:14 -0300144#define MN_NTSC_PAL_BTSC 0
145#define MN_NTSC_PAL_A2 1
146#define MN_NTSC_PAL_EIAJ 2
147#define MN_NTSC_PAL_Mono 3
148#define BG_PAL_A2 4
149#define BG_PAL_NICAM 5
150#define BG_PAL_MONO 6
151#define I_PAL_NICAM 7
152#define I_PAL_NICAM_MONO 8
153#define DK_PAL_A2 9
154#define DK_PAL_NICAM 10
155#define DK_PAL_MONO 11
156#define DK_SECAM_A2DK1 12
157#define DK_SECAM_A2LDK3 13
158#define DK_SECAM_A2MONO 14
159#define L_SECAM_NICAM 15
160#define LC_SECAM_NICAM 16
161#define DTV6 17
162#define DTV8 18
163#define DTV7_8 19
164#define DTV7 20
165#define FM_Radio_INPUT2 21
166#define FM_Radio_INPUT1 22
Steven Tothaacb9d32007-12-18 01:55:51 -0300167
Steven Toth8f3cd532008-10-16 20:29:38 -0300168static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
Steven Tothaacb9d32007-12-18 01:55:51 -0300169 {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
170 {"M/N-NTSC/PAL-A2", 0x0600, 0x8020},
171 {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
172 {"M/N-NTSC/PAL-Mono", 0x0478, 0x8020},
173 {"B/G-PAL-A2", 0x0A00, 0x8049},
174 {"B/G-PAL-NICAM", 0x0C04, 0x8049},
175 {"B/G-PAL-MONO", 0x0878, 0x8059},
176 {"I-PAL-NICAM", 0x1080, 0x8009},
177 {"I-PAL-NICAM-MONO", 0x0E78, 0x8009},
178 {"D/K-PAL-A2", 0x1600, 0x8009},
179 {"D/K-PAL-NICAM", 0x0E80, 0x8009},
180 {"D/K-PAL-MONO", 0x1478, 0x8009},
181 {"D/K-SECAM-A2 DK1", 0x1200, 0x8009},
Steven Toth8f3cd532008-10-16 20:29:38 -0300182 {"D/K-SECAM-A2 L/DK3", 0x0E00, 0x8009},
Steven Tothaacb9d32007-12-18 01:55:51 -0300183 {"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
184 {"L-SECAM-NICAM", 0x8E82, 0x0009},
185 {"L'-SECAM-NICAM", 0x8E82, 0x4009},
186 {"DTV6", 0x00C0, 0x8002},
187 {"DTV8", 0x00C0, 0x800B},
188 {"DTV7/8", 0x00C0, 0x801B},
189 {"DTV7", 0x00C0, 0x8007},
190 {"FM Radio-INPUT2", 0x9802, 0x9002},
191 {"FM Radio-INPUT1", 0x0208, 0x9002}
192};
193
Devin Heitmueller8e4c6792008-11-16 20:41:07 -0300194static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300195static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300196static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300197static int xc5000_TunerReset(struct dvb_frontend *fe);
Steven Tothaacb9d32007-12-18 01:55:51 -0300198
Steven Tothe12671cf2007-12-20 01:14:43 -0300199static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
Steven Tothaacb9d32007-12-18 01:55:51 -0300200{
Devin Heitmuellerd7800d42008-11-16 20:20:06 -0300201 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
202 .flags = 0, .buf = buf, .len = len };
203
204 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
205 printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len);
206 return XC_RESULT_I2C_WRITE_FAILURE;
207 }
208 return XC_RESULT_SUCCESS;
Steven Tothaacb9d32007-12-18 01:55:51 -0300209}
210
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300211/* This routine is never used because the only time we read data from the
212 i2c bus is when we read registers, and we want that to be an atomic i2c
213 transaction in case we are on a multi-master bus */
Steven Tothe12671cf2007-12-20 01:14:43 -0300214static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
Steven Tothaacb9d32007-12-18 01:55:51 -0300215{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300216 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
217 .flags = I2C_M_RD, .buf = buf, .len = len };
218
219 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
220 printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", len);
221 return -EREMOTEIO;
222 }
223 return 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300224}
225
Steven Tothe12671cf2007-12-20 01:14:43 -0300226static void xc_wait(int wait_ms)
Steven Tothaacb9d32007-12-18 01:55:51 -0300227{
Steven Tothe12671cf2007-12-20 01:14:43 -0300228 msleep(wait_ms);
Steven Tothaacb9d32007-12-18 01:55:51 -0300229}
230
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300231static int xc5000_TunerReset(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300232{
233 struct xc5000_priv *priv = fe->tuner_priv;
234 int ret;
235
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300236 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300237
Michael Krufkyd7cba042008-09-12 13:31:45 -0300238 if (fe->callback) {
239 ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
Michael Krufky30650962008-09-06 14:56:58 -0300240 fe->dvb->priv :
241 priv->i2c_props.adap->algo_data,
Michael Krufkyd7cba042008-09-12 13:31:45 -0300242 DVB_FRONTEND_COMPONENT_TUNER,
Michael Krufky30650962008-09-06 14:56:58 -0300243 XC5000_TUNER_RESET, 0);
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300244 if (ret) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300245 printk(KERN_ERR "xc5000: reset failed\n");
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300246 return XC_RESULT_RESET_FAILURE;
247 }
248 } else {
Steven Toth27c685a2008-01-05 16:50:14 -0300249 printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300250 return XC_RESULT_RESET_FAILURE;
251 }
252 return XC_RESULT_SUCCESS;
Steven Tothaacb9d32007-12-18 01:55:51 -0300253}
254
Steven Tothe12671cf2007-12-20 01:14:43 -0300255static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
Steven Tothaacb9d32007-12-18 01:55:51 -0300256{
Steven Tothe12671cf2007-12-20 01:14:43 -0300257 u8 buf[4];
Steven Tothaacb9d32007-12-18 01:55:51 -0300258 int WatchDogTimer = 5;
259 int result;
260
261 buf[0] = (regAddr >> 8) & 0xFF;
262 buf[1] = regAddr & 0xFF;
263 buf[2] = (i2cData >> 8) & 0xFF;
264 buf[3] = i2cData & 0xFF;
265 result = xc_send_i2c_data(priv, buf, 4);
Steven Tothe12671cf2007-12-20 01:14:43 -0300266 if (result == XC_RESULT_SUCCESS) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300267 /* wait for busy flag to clear */
268 while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
269 buf[0] = 0;
270 buf[1] = XREG_BUSY;
271
272 result = xc_send_i2c_data(priv, buf, 2);
273 if (result == XC_RESULT_SUCCESS) {
274 result = xc_read_i2c_data(priv, buf, 2);
275 if (result == XC_RESULT_SUCCESS) {
276 if ((buf[0] == 0) && (buf[1] == 0)) {
277 /* busy flag cleared */
278 break;
279 } else {
280 xc_wait(100); /* wait 5 ms */
281 WatchDogTimer--;
282 }
283 }
284 }
285 }
286 }
287 if (WatchDogTimer < 0)
288 result = XC_RESULT_I2C_WRITE_FAILURE;
289
290 return result;
291}
292
David Woodhousec63e87e2008-05-24 00:13:34 +0100293static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
Steven Tothaacb9d32007-12-18 01:55:51 -0300294{
295 struct xc5000_priv *priv = fe->tuner_priv;
296
297 int i, nbytes_to_send, result;
298 unsigned int len, pos, index;
Steven Tothe12671cf2007-12-20 01:14:43 -0300299 u8 buf[XC_MAX_I2C_WRITE_LENGTH];
Steven Tothaacb9d32007-12-18 01:55:51 -0300300
Steven Toth8f3cd532008-10-16 20:29:38 -0300301 index = 0;
302 while ((i2c_sequence[index] != 0xFF) ||
303 (i2c_sequence[index + 1] != 0xFF)) {
304 len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
Steven Tothe12671cf2007-12-20 01:14:43 -0300305 if (len == 0x0000) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300306 /* RESET command */
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300307 result = xc5000_TunerReset(fe);
Steven Tothaacb9d32007-12-18 01:55:51 -0300308 index += 2;
Steven Tothe12671cf2007-12-20 01:14:43 -0300309 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300310 return result;
311 } else if (len & 0x8000) {
312 /* WAIT command */
313 xc_wait(len & 0x7FFF);
314 index += 2;
315 } else {
316 /* Send i2c data whilst ensuring individual transactions
317 * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
318 */
319 index += 2;
320 buf[0] = i2c_sequence[index];
321 buf[1] = i2c_sequence[index + 1];
322 pos = 2;
323 while (pos < len) {
Steven Toth8f3cd532008-10-16 20:29:38 -0300324 if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
325 nbytes_to_send =
326 XC_MAX_I2C_WRITE_LENGTH;
327 else
Steven Tothaacb9d32007-12-18 01:55:51 -0300328 nbytes_to_send = (len - pos + 2);
Steven Toth8f3cd532008-10-16 20:29:38 -0300329 for (i = 2; i < nbytes_to_send; i++) {
330 buf[i] = i2c_sequence[index + pos +
331 i - 2];
Steven Tothaacb9d32007-12-18 01:55:51 -0300332 }
Steven Toth8f3cd532008-10-16 20:29:38 -0300333 result = xc_send_i2c_data(priv, buf,
334 nbytes_to_send);
Steven Tothaacb9d32007-12-18 01:55:51 -0300335
Steven Tothe12671cf2007-12-20 01:14:43 -0300336 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300337 return result;
338
339 pos += nbytes_to_send - 2;
340 }
341 index += len;
342 }
343 }
344 return XC_RESULT_SUCCESS;
345}
346
Steven Tothe12671cf2007-12-20 01:14:43 -0300347static int xc_initialize(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300348{
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300349 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300350 return xc_write_reg(priv, XREG_INIT, 0);
351}
352
Steven Tothe12671cf2007-12-20 01:14:43 -0300353static int xc_SetTVStandard(struct xc5000_priv *priv,
354 u16 VideoMode, u16 AudioMode)
Steven Tothaacb9d32007-12-18 01:55:51 -0300355{
356 int ret;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300357 dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
Steven Tothaacb9d32007-12-18 01:55:51 -0300358 dprintk(1, "%s() Standard = %s\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300359 __func__,
Steven Tothaacb9d32007-12-18 01:55:51 -0300360 XC5000_Standard[priv->video_standard].Name);
361
362 ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
363 if (ret == XC_RESULT_SUCCESS)
364 ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
365
366 return ret;
367}
368
Steven Tothe12671cf2007-12-20 01:14:43 -0300369static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
Steven Tothaacb9d32007-12-18 01:55:51 -0300370{
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300371 dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
Steven Tothaacb9d32007-12-18 01:55:51 -0300372 rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
373
Steven Toth8f3cd532008-10-16 20:29:38 -0300374 if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300375 rf_mode = XC_RF_MODE_CABLE;
376 printk(KERN_ERR
377 "%s(), Invalid mode, defaulting to CABLE",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300378 __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300379 }
380 return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
381}
382
Steven Tothe12671cf2007-12-20 01:14:43 -0300383static const struct dvb_tuner_ops xc5000_tuner_ops;
384
385static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300386{
Steven Tothe12671cf2007-12-20 01:14:43 -0300387 u16 freq_code;
Steven Tothaacb9d32007-12-18 01:55:51 -0300388
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300389 dprintk(1, "%s(%u)\n", __func__, freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300390
Steven Tothe12671cf2007-12-20 01:14:43 -0300391 if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
392 (freq_hz < xc5000_tuner_ops.info.frequency_min))
393 return XC_RESULT_OUT_OF_RANGE;
Steven Tothaacb9d32007-12-18 01:55:51 -0300394
Steven Tothe12671cf2007-12-20 01:14:43 -0300395 freq_code = (u16)(freq_hz / 15625);
396
397 return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
Steven Tothaacb9d32007-12-18 01:55:51 -0300398}
399
Steven Tothe12671cf2007-12-20 01:14:43 -0300400
401static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300402{
Steven Tothe12671cf2007-12-20 01:14:43 -0300403 u32 freq_code = (freq_khz * 1024)/1000;
404 dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300405 __func__, freq_khz, freq_code);
Steven Tothe12671cf2007-12-20 01:14:43 -0300406
407 return xc_write_reg(priv, XREG_IF_OUT, freq_code);
Steven Tothaacb9d32007-12-18 01:55:51 -0300408}
409
Steven Tothe12671cf2007-12-20 01:14:43 -0300410
411static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
Steven Tothaacb9d32007-12-18 01:55:51 -0300412{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300413 return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope);
Steven Tothaacb9d32007-12-18 01:55:51 -0300414}
415
Steven Tothe12671cf2007-12-20 01:14:43 -0300416static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300417{
418 int result;
Steven Tothe12671cf2007-12-20 01:14:43 -0300419 u16 regData;
Steven Tothaacb9d32007-12-18 01:55:51 -0300420 u32 tmp;
421
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300422 result = xc5000_readreg(priv, XREG_FREQ_ERROR, &regData);
Devin Heitmueller7988fc22008-11-16 20:23:19 -0300423 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300424 return result;
425
426 tmp = (u32)regData;
Steven Tothe12671cf2007-12-20 01:14:43 -0300427 (*freq_error_hz) = (tmp * 15625) / 1000;
Steven Tothaacb9d32007-12-18 01:55:51 -0300428 return result;
429}
430
Steven Tothe12671cf2007-12-20 01:14:43 -0300431static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
Steven Tothaacb9d32007-12-18 01:55:51 -0300432{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300433 return xc5000_readreg(priv, XREG_LOCK, lock_status);
Steven Tothaacb9d32007-12-18 01:55:51 -0300434}
435
Steven Tothe12671cf2007-12-20 01:14:43 -0300436static int xc_get_version(struct xc5000_priv *priv,
437 u8 *hw_majorversion, u8 *hw_minorversion,
438 u8 *fw_majorversion, u8 *fw_minorversion)
Steven Tothaacb9d32007-12-18 01:55:51 -0300439{
Steven Tothe12671cf2007-12-20 01:14:43 -0300440 u16 data;
Steven Tothaacb9d32007-12-18 01:55:51 -0300441 int result;
442
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300443 result = xc5000_readreg(priv, XREG_VERSION, &data);
Devin Heitmueller7988fc22008-11-16 20:23:19 -0300444 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300445 return result;
446
Steven Tothe12671cf2007-12-20 01:14:43 -0300447 (*hw_majorversion) = (data >> 12) & 0x0F;
448 (*hw_minorversion) = (data >> 8) & 0x0F;
449 (*fw_majorversion) = (data >> 4) & 0x0F;
450 (*fw_minorversion) = data & 0x0F;
Steven Tothaacb9d32007-12-18 01:55:51 -0300451
452 return 0;
453}
454
Steven Tothe12671cf2007-12-20 01:14:43 -0300455static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300456{
Steven Tothe12671cf2007-12-20 01:14:43 -0300457 u16 regData;
Steven Tothaacb9d32007-12-18 01:55:51 -0300458 int result;
459
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300460 result = xc5000_readreg(priv, XREG_HSYNC_FREQ, &regData);
Devin Heitmueller7988fc22008-11-16 20:23:19 -0300461 if (result != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300462 return result;
463
464 (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
465 return result;
466}
467
Steven Tothe12671cf2007-12-20 01:14:43 -0300468static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
Steven Tothaacb9d32007-12-18 01:55:51 -0300469{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300470 return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines);
Steven Tothaacb9d32007-12-18 01:55:51 -0300471}
472
Steven Tothe12671cf2007-12-20 01:14:43 -0300473static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
Steven Tothaacb9d32007-12-18 01:55:51 -0300474{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300475 return xc5000_readreg(priv, XREG_QUALITY, quality);
Steven Tothaacb9d32007-12-18 01:55:51 -0300476}
477
Steven Tothe12671cf2007-12-20 01:14:43 -0300478static u16 WaitForLock(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300479{
Steven Tothe12671cf2007-12-20 01:14:43 -0300480 u16 lockState = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300481 int watchDogCount = 40;
Steven Tothe12671cf2007-12-20 01:14:43 -0300482
483 while ((lockState == 0) && (watchDogCount > 0)) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300484 xc_get_lock_status(priv, &lockState);
Steven Tothe12671cf2007-12-20 01:14:43 -0300485 if (lockState != 1) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300486 xc_wait(5);
487 watchDogCount--;
488 }
489 }
490 return lockState;
491}
492
Steven Tothe12671cf2007-12-20 01:14:43 -0300493static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300494{
495 int found = 0;
496
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300497 dprintk(1, "%s(%u)\n", __func__, freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300498
Steven Tothe12671cf2007-12-20 01:14:43 -0300499 if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300500 return 0;
501
Steven Tothe12671cf2007-12-20 01:14:43 -0300502 if (WaitForLock(priv) == 1)
Steven Tothaacb9d32007-12-18 01:55:51 -0300503 found = 1;
504
505 return found;
506}
507
508static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
509{
510 u8 buf[2] = { reg >> 8, reg & 0xff };
511 u8 bval[2] = { 0, 0 };
512 struct i2c_msg msg[2] = {
Michael Krufky89fd2852008-09-06 11:44:53 -0300513 { .addr = priv->i2c_props.addr,
Steven Tothaacb9d32007-12-18 01:55:51 -0300514 .flags = 0, .buf = &buf[0], .len = 2 },
Michael Krufky89fd2852008-09-06 11:44:53 -0300515 { .addr = priv->i2c_props.addr,
Steven Tothaacb9d32007-12-18 01:55:51 -0300516 .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
517 };
518
Michael Krufky89fd2852008-09-06 11:44:53 -0300519 if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
Steven Toth27c685a2008-01-05 16:50:14 -0300520 printk(KERN_WARNING "xc5000: I2C read failed\n");
Steven Tothaacb9d32007-12-18 01:55:51 -0300521 return -EREMOTEIO;
522 }
523
524 *val = (bval[0] << 8) | bval[1];
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300525 return XC_RESULT_SUCCESS;
Steven Tothaacb9d32007-12-18 01:55:51 -0300526}
527
Steven Toth8f3cd532008-10-16 20:29:38 -0300528static int xc5000_fwupload(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300529{
530 struct xc5000_priv *priv = fe->tuner_priv;
531 const struct firmware *fw;
532 int ret;
533
Steven Tothe12671cf2007-12-20 01:14:43 -0300534 /* request the firmware, this will block and timeout */
535 printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
536 XC5000_DEFAULT_FIRMWARE);
537
Steven Toth8f3cd532008-10-16 20:29:38 -0300538 ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE,
Jean Delvaree9785252009-04-26 05:43:59 -0300539 priv->i2c_props.adap->dev.parent);
Steven Tothaacb9d32007-12-18 01:55:51 -0300540 if (ret) {
541 printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
542 ret = XC_RESULT_RESET_FAILURE;
Steven Toth5ea60532008-01-24 22:29:46 -0300543 goto out;
Steven Tothaacb9d32007-12-18 01:55:51 -0300544 } else {
Michael Krufky3f514512007-12-21 16:20:23 -0300545 printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n",
546 fw->size);
Steven Tothaacb9d32007-12-18 01:55:51 -0300547 ret = XC_RESULT_SUCCESS;
548 }
549
Steven Tothe12671cf2007-12-20 01:14:43 -0300550 if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300551 printk(KERN_ERR "xc5000: firmware incorrect size\n");
552 ret = XC_RESULT_RESET_FAILURE;
553 } else {
554 printk(KERN_INFO "xc5000: firmware upload\n");
Steven Toth8f3cd532008-10-16 20:29:38 -0300555 ret = xc_load_i2c_sequence(fe, fw->data);
Steven Tothaacb9d32007-12-18 01:55:51 -0300556 }
557
Steven Toth5ea60532008-01-24 22:29:46 -0300558out:
Steven Tothaacb9d32007-12-18 01:55:51 -0300559 release_firmware(fw);
560 return ret;
561}
562
Steven Tothe12671cf2007-12-20 01:14:43 -0300563static void xc_debug_dump(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300564{
Steven Tothe12671cf2007-12-20 01:14:43 -0300565 u16 adc_envelope;
566 u32 freq_error_hz = 0;
567 u16 lock_status;
568 u32 hsync_freq_hz = 0;
569 u16 frame_lines;
570 u16 quality;
571 u8 hw_majorversion = 0, hw_minorversion = 0;
572 u8 fw_majorversion = 0, fw_minorversion = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300573
574 /* Wait for stats to stabilize.
575 * Frame Lines needs two frame times after initial lock
576 * before it is valid.
577 */
Steven Tothe12671cf2007-12-20 01:14:43 -0300578 xc_wait(100);
Steven Tothaacb9d32007-12-18 01:55:51 -0300579
Steven Tothe12671cf2007-12-20 01:14:43 -0300580 xc_get_ADC_Envelope(priv, &adc_envelope);
581 dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
Steven Tothaacb9d32007-12-18 01:55:51 -0300582
Steven Tothe12671cf2007-12-20 01:14:43 -0300583 xc_get_frequency_error(priv, &freq_error_hz);
584 dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300585
Steven Tothe12671cf2007-12-20 01:14:43 -0300586 xc_get_lock_status(priv, &lock_status);
587 dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
Steven Tothaacb9d32007-12-18 01:55:51 -0300588 lock_status);
589
590 xc_get_version(priv, &hw_majorversion, &hw_minorversion,
Steven Tothe12671cf2007-12-20 01:14:43 -0300591 &fw_majorversion, &fw_minorversion);
Steven Tothaacb9d32007-12-18 01:55:51 -0300592 dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
593 hw_majorversion, hw_minorversion,
594 fw_majorversion, fw_minorversion);
595
Steven Tothe12671cf2007-12-20 01:14:43 -0300596 xc_get_hsync_freq(priv, &hsync_freq_hz);
597 dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300598
Steven Tothe12671cf2007-12-20 01:14:43 -0300599 xc_get_frame_lines(priv, &frame_lines);
600 dprintk(1, "*** Frame lines = %d\n", frame_lines);
Steven Tothaacb9d32007-12-18 01:55:51 -0300601
Steven Tothe12671cf2007-12-20 01:14:43 -0300602 xc_get_quality(priv, &quality);
603 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
Steven Tothaacb9d32007-12-18 01:55:51 -0300604}
605
606static int xc5000_set_params(struct dvb_frontend *fe,
607 struct dvb_frontend_parameters *params)
608{
609 struct xc5000_priv *priv = fe->tuner_priv;
Steven Tothe12671cf2007-12-20 01:14:43 -0300610 int ret;
Steven Tothaacb9d32007-12-18 01:55:51 -0300611
Devin Heitmueller8e4c6792008-11-16 20:41:07 -0300612 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
613 xc_load_fw_and_init_tuner(fe);
614
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300615 dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
Steven Tothaacb9d32007-12-18 01:55:51 -0300616
Steven Toth8f3cd532008-10-16 20:29:38 -0300617 switch (params->u.vsb.modulation) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300618 case VSB_8:
619 case VSB_16:
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300620 dprintk(1, "%s() VSB modulation\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300621 priv->rf_mode = XC_RF_MODE_AIR;
Steven Tothe12671cf2007-12-20 01:14:43 -0300622 priv->freq_hz = params->frequency - 1750000;
623 priv->bandwidth = BANDWIDTH_6_MHZ;
624 priv->video_standard = DTV6;
Steven Tothaacb9d32007-12-18 01:55:51 -0300625 break;
626 case QAM_64:
627 case QAM_256:
628 case QAM_AUTO:
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300629 dprintk(1, "%s() QAM modulation\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300630 priv->rf_mode = XC_RF_MODE_CABLE;
Steven Tothe12671cf2007-12-20 01:14:43 -0300631 priv->freq_hz = params->frequency - 1750000;
632 priv->bandwidth = BANDWIDTH_6_MHZ;
633 priv->video_standard = DTV6;
Steven Tothaacb9d32007-12-18 01:55:51 -0300634 break;
635 default:
636 return -EINVAL;
637 }
638
639 dprintk(1, "%s() frequency=%d (compensated)\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300640 __func__, priv->freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300641
Steven Tothe12671cf2007-12-20 01:14:43 -0300642 ret = xc_SetSignalSource(priv, priv->rf_mode);
643 if (ret != XC_RESULT_SUCCESS) {
644 printk(KERN_ERR
645 "xc5000: xc_SetSignalSource(%d) failed\n",
646 priv->rf_mode);
647 return -EREMOTEIO;
648 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300649
Steven Tothe12671cf2007-12-20 01:14:43 -0300650 ret = xc_SetTVStandard(priv,
Steven Tothaacb9d32007-12-18 01:55:51 -0300651 XC5000_Standard[priv->video_standard].VideoMode,
652 XC5000_Standard[priv->video_standard].AudioMode);
Steven Tothe12671cf2007-12-20 01:14:43 -0300653 if (ret != XC_RESULT_SUCCESS) {
654 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
655 return -EREMOTEIO;
656 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300657
Michael Krufky2a6003c2008-09-06 13:54:45 -0300658 ret = xc_set_IF_frequency(priv, priv->if_khz);
Steven Tothe12671cf2007-12-20 01:14:43 -0300659 if (ret != XC_RESULT_SUCCESS) {
660 printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
Michael Krufky2a6003c2008-09-06 13:54:45 -0300661 priv->if_khz);
Steven Tothe12671cf2007-12-20 01:14:43 -0300662 return -EIO;
663 }
664
665 xc_tune_channel(priv, priv->freq_hz);
666
667 if (debug)
668 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -0300669
670 return 0;
671}
672
Steven Tothe470d812008-06-21 21:06:02 -0300673static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
674{
675 struct xc5000_priv *priv = fe->tuner_priv;
676 int ret;
677 u16 id;
678
679 ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
680 if (ret == XC_RESULT_SUCCESS) {
681 if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
682 ret = XC_RESULT_RESET_FAILURE;
683 else
684 ret = XC_RESULT_SUCCESS;
685 }
686
687 dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
688 ret == XC_RESULT_SUCCESS ? "True" : "False", id);
689 return ret;
690}
691
Steven Toth27c685a2008-01-05 16:50:14 -0300692static int xc5000_set_analog_params(struct dvb_frontend *fe,
693 struct analog_parameters *params)
694{
695 struct xc5000_priv *priv = fe->tuner_priv;
696 int ret;
697
Steven Tothe470d812008-06-21 21:06:02 -0300698 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
Steven Toth27c685a2008-01-05 16:50:14 -0300699 xc_load_fw_and_init_tuner(fe);
700
701 dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300702 __func__, params->frequency);
Steven Toth27c685a2008-01-05 16:50:14 -0300703
Mauro Carvalho Chehab1fab14e2009-03-03 14:35:41 -0300704 /* Fix me: it could be air. */
705 priv->rf_mode = params->mode;
706 if (params->mode > XC_RF_MODE_CABLE)
707 priv->rf_mode = XC_RF_MODE_CABLE;
Steven Toth27c685a2008-01-05 16:50:14 -0300708
709 /* params->frequency is in units of 62.5khz */
710 priv->freq_hz = params->frequency * 62500;
711
712 /* FIX ME: Some video standards may have several possible audio
713 standards. We simply default to one of them here.
714 */
Steven Toth8f3cd532008-10-16 20:29:38 -0300715 if (params->std & V4L2_STD_MN) {
Steven Toth27c685a2008-01-05 16:50:14 -0300716 /* default to BTSC audio standard */
717 priv->video_standard = MN_NTSC_PAL_BTSC;
718 goto tune_channel;
719 }
720
Steven Toth8f3cd532008-10-16 20:29:38 -0300721 if (params->std & V4L2_STD_PAL_BG) {
Steven Toth27c685a2008-01-05 16:50:14 -0300722 /* default to NICAM audio standard */
723 priv->video_standard = BG_PAL_NICAM;
724 goto tune_channel;
725 }
726
Steven Toth8f3cd532008-10-16 20:29:38 -0300727 if (params->std & V4L2_STD_PAL_I) {
Steven Toth27c685a2008-01-05 16:50:14 -0300728 /* default to NICAM audio standard */
729 priv->video_standard = I_PAL_NICAM;
730 goto tune_channel;
731 }
732
Steven Toth8f3cd532008-10-16 20:29:38 -0300733 if (params->std & V4L2_STD_PAL_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300734 /* default to NICAM audio standard */
735 priv->video_standard = DK_PAL_NICAM;
736 goto tune_channel;
737 }
738
Steven Toth8f3cd532008-10-16 20:29:38 -0300739 if (params->std & V4L2_STD_SECAM_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300740 /* default to A2 DK1 audio standard */
741 priv->video_standard = DK_SECAM_A2DK1;
742 goto tune_channel;
743 }
744
Steven Toth8f3cd532008-10-16 20:29:38 -0300745 if (params->std & V4L2_STD_SECAM_L) {
Steven Toth27c685a2008-01-05 16:50:14 -0300746 priv->video_standard = L_SECAM_NICAM;
747 goto tune_channel;
748 }
749
Steven Toth8f3cd532008-10-16 20:29:38 -0300750 if (params->std & V4L2_STD_SECAM_LC) {
Steven Toth27c685a2008-01-05 16:50:14 -0300751 priv->video_standard = LC_SECAM_NICAM;
752 goto tune_channel;
753 }
754
755tune_channel:
756 ret = xc_SetSignalSource(priv, priv->rf_mode);
757 if (ret != XC_RESULT_SUCCESS) {
Steven Toth8f3cd532008-10-16 20:29:38 -0300758 printk(KERN_ERR
Steven Toth27c685a2008-01-05 16:50:14 -0300759 "xc5000: xc_SetSignalSource(%d) failed\n",
760 priv->rf_mode);
761 return -EREMOTEIO;
762 }
763
764 ret = xc_SetTVStandard(priv,
765 XC5000_Standard[priv->video_standard].VideoMode,
766 XC5000_Standard[priv->video_standard].AudioMode);
767 if (ret != XC_RESULT_SUCCESS) {
768 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
769 return -EREMOTEIO;
770 }
771
772 xc_tune_channel(priv, priv->freq_hz);
773
774 if (debug)
775 xc_debug_dump(priv);
776
777 return 0;
778}
779
Steven Tothaacb9d32007-12-18 01:55:51 -0300780static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
781{
782 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300783 dprintk(1, "%s()\n", __func__);
Steven Tothe12671cf2007-12-20 01:14:43 -0300784 *freq = priv->freq_hz;
Steven Tothaacb9d32007-12-18 01:55:51 -0300785 return 0;
786}
787
788static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
789{
790 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300791 dprintk(1, "%s()\n", __func__);
Steven Toth27c685a2008-01-05 16:50:14 -0300792
Steven Tothaacb9d32007-12-18 01:55:51 -0300793 *bw = priv->bandwidth;
794 return 0;
795}
796
797static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
798{
799 struct xc5000_priv *priv = fe->tuner_priv;
Steven Tothe12671cf2007-12-20 01:14:43 -0300800 u16 lock_status = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300801
802 xc_get_lock_status(priv, &lock_status);
803
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300804 dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
Steven Tothaacb9d32007-12-18 01:55:51 -0300805
806 *status = lock_status;
807
808 return 0;
809}
810
Steven Tothe12671cf2007-12-20 01:14:43 -0300811static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300812{
813 struct xc5000_priv *priv = fe->tuner_priv;
Steven Toth27c685a2008-01-05 16:50:14 -0300814 int ret = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300815
Steven Tothe470d812008-06-21 21:06:02 -0300816 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300817 ret = xc5000_fwupload(fe);
Steven Tothe12671cf2007-12-20 01:14:43 -0300818 if (ret != XC_RESULT_SUCCESS)
819 return ret;
Steven Tothaacb9d32007-12-18 01:55:51 -0300820 }
821
822 /* Start the tuner self-calibration process */
823 ret |= xc_initialize(priv);
824
825 /* Wait for calibration to complete.
826 * We could continue but XC5000 will clock stretch subsequent
827 * I2C transactions until calibration is complete. This way we
828 * don't have to rely on clock stretching working.
829 */
Steven Toth8f3cd532008-10-16 20:29:38 -0300830 xc_wait(100);
Steven Tothaacb9d32007-12-18 01:55:51 -0300831
832 /* Default to "CABLE" mode */
833 ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
834
835 return ret;
836}
837
Steven Tothe12671cf2007-12-20 01:14:43 -0300838static int xc5000_sleep(struct dvb_frontend *fe)
839{
840 struct xc5000_priv *priv = fe->tuner_priv;
Steven Toth27c685a2008-01-05 16:50:14 -0300841 int ret;
842
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300843 dprintk(1, "%s()\n", __func__);
Steven Tothe12671cf2007-12-20 01:14:43 -0300844
Devin Heitmueller8e4c6792008-11-16 20:41:07 -0300845 ret = xc_write_reg(priv, XREG_POWER_DOWN, 0);
Steven Toth8f3cd532008-10-16 20:29:38 -0300846 if (ret != XC_RESULT_SUCCESS) {
Steven Toth27c685a2008-01-05 16:50:14 -0300847 printk(KERN_ERR
848 "xc5000: %s() unable to shutdown tuner\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300849 __func__);
Steven Toth27c685a2008-01-05 16:50:14 -0300850 return -EREMOTEIO;
Steven Toth8f3cd532008-10-16 20:29:38 -0300851 } else
Steven Toth27c685a2008-01-05 16:50:14 -0300852 return XC_RESULT_SUCCESS;
Steven Tothe12671cf2007-12-20 01:14:43 -0300853}
854
Steven Tothaacb9d32007-12-18 01:55:51 -0300855static int xc5000_init(struct dvb_frontend *fe)
856{
857 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300858 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300859
Steven Tothe12671cf2007-12-20 01:14:43 -0300860 if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
861 printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
862 return -EREMOTEIO;
863 }
864
865 if (debug)
866 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -0300867
868 return 0;
869}
870
871static int xc5000_release(struct dvb_frontend *fe)
872{
Michael Krufky89fd2852008-09-06 11:44:53 -0300873 struct xc5000_priv *priv = fe->tuner_priv;
874
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300875 dprintk(1, "%s()\n", __func__);
Michael Krufky89fd2852008-09-06 11:44:53 -0300876
877 mutex_lock(&xc5000_list_mutex);
878
879 if (priv)
880 hybrid_tuner_release_state(priv);
881
882 mutex_unlock(&xc5000_list_mutex);
883
Steven Tothaacb9d32007-12-18 01:55:51 -0300884 fe->tuner_priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -0300885
Steven Tothaacb9d32007-12-18 01:55:51 -0300886 return 0;
887}
888
889static const struct dvb_tuner_ops xc5000_tuner_ops = {
890 .info = {
891 .name = "Xceive XC5000",
892 .frequency_min = 1000000,
893 .frequency_max = 1023000000,
894 .frequency_step = 50000,
895 },
896
Steven Toth27c685a2008-01-05 16:50:14 -0300897 .release = xc5000_release,
898 .init = xc5000_init,
899 .sleep = xc5000_sleep,
Steven Tothaacb9d32007-12-18 01:55:51 -0300900
Steven Toth27c685a2008-01-05 16:50:14 -0300901 .set_params = xc5000_set_params,
902 .set_analog_params = xc5000_set_analog_params,
903 .get_frequency = xc5000_get_frequency,
904 .get_bandwidth = xc5000_get_bandwidth,
905 .get_status = xc5000_get_status
Steven Tothaacb9d32007-12-18 01:55:51 -0300906};
907
Michael Krufky48723542008-05-10 14:34:09 -0300908struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
909 struct i2c_adapter *i2c,
Michael Krufky30650962008-09-06 14:56:58 -0300910 struct xc5000_config *cfg)
Steven Tothaacb9d32007-12-18 01:55:51 -0300911{
912 struct xc5000_priv *priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -0300913 int instance;
Steven Tothaacb9d32007-12-18 01:55:51 -0300914 u16 id = 0;
915
Michael Krufky89fd2852008-09-06 11:44:53 -0300916 dprintk(1, "%s(%d-%04x)\n", __func__,
917 i2c ? i2c_adapter_id(i2c) : -1,
918 cfg ? cfg->i2c_address : -1);
Steven Tothaacb9d32007-12-18 01:55:51 -0300919
Michael Krufky89fd2852008-09-06 11:44:53 -0300920 mutex_lock(&xc5000_list_mutex);
Steven Tothaacb9d32007-12-18 01:55:51 -0300921
Michael Krufky89fd2852008-09-06 11:44:53 -0300922 instance = hybrid_tuner_request_state(struct xc5000_priv, priv,
923 hybrid_tuner_instance_list,
924 i2c, cfg->i2c_address, "xc5000");
925 switch (instance) {
926 case 0:
927 goto fail;
928 break;
929 case 1:
930 /* new tuner instance */
Michael Krufky89fd2852008-09-06 11:44:53 -0300931 priv->bandwidth = BANDWIDTH_6_MHZ;
Michael Krufky89fd2852008-09-06 11:44:53 -0300932 fe->tuner_priv = priv;
933 break;
934 default:
935 /* existing tuner instance */
936 fe->tuner_priv = priv;
937 break;
938 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300939
Devin Heitmuellerea227862009-03-11 02:58:53 -0300940 if (priv->if_khz == 0) {
941 /* If the IF hasn't been set yet, use the value provided by
942 the caller (occurs in hybrid devices where the analog
943 call to xc5000_attach occurs before the digital side) */
944 priv->if_khz = cfg->if_khz;
945 }
946
Steven Toth27c685a2008-01-05 16:50:14 -0300947 /* Check if firmware has been loaded. It is possible that another
948 instance of the driver has loaded the firmware.
949 */
Devin Heitmueller7988fc22008-11-16 20:23:19 -0300950 if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS)
Michael Krufky89fd2852008-09-06 11:44:53 -0300951 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -0300952
Steven Toth8f3cd532008-10-16 20:29:38 -0300953 switch (id) {
Steven Toth27c685a2008-01-05 16:50:14 -0300954 case XC_PRODUCT_ID_FW_LOADED:
955 printk(KERN_INFO
956 "xc5000: Successfully identified at address 0x%02x\n",
957 cfg->i2c_address);
958 printk(KERN_INFO
959 "xc5000: Firmware has been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -0300960 break;
961 case XC_PRODUCT_ID_FW_NOT_LOADED:
962 printk(KERN_INFO
963 "xc5000: Successfully identified at address 0x%02x\n",
964 cfg->i2c_address);
965 printk(KERN_INFO
966 "xc5000: Firmware has not been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -0300967 break;
968 default:
Steven Tothaacb9d32007-12-18 01:55:51 -0300969 printk(KERN_ERR
970 "xc5000: Device not found at addr 0x%02x (0x%x)\n",
971 cfg->i2c_address, id);
Michael Krufky89fd2852008-09-06 11:44:53 -0300972 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -0300973 }
974
Michael Krufky89fd2852008-09-06 11:44:53 -0300975 mutex_unlock(&xc5000_list_mutex);
976
Steven Tothaacb9d32007-12-18 01:55:51 -0300977 memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
978 sizeof(struct dvb_tuner_ops));
979
Steven Tothaacb9d32007-12-18 01:55:51 -0300980 return fe;
Michael Krufky89fd2852008-09-06 11:44:53 -0300981fail:
982 mutex_unlock(&xc5000_list_mutex);
983
984 xc5000_release(fe);
985 return NULL;
Steven Tothaacb9d32007-12-18 01:55:51 -0300986}
987EXPORT_SYMBOL(xc5000_attach);
988
989MODULE_AUTHOR("Steven Toth");
Steven Tothe12671cf2007-12-20 01:14:43 -0300990MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
Steven Tothaacb9d32007-12-18 01:55:51 -0300991MODULE_LICENSE("GPL");