blob: c9e72ae94fbb012bdb20ea78a82fadcc0acb9fb2 [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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-12-20 01:14:43 -0300226static void xc_wait(int wait_ms)
Steven Tothaacb9d32007-12-18 01:55:51 -0300227{
Steven Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-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 Tothe12671c2007-12-20 01:14:43 -0300478static u16 WaitForLock(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300479{
Steven Tothe12671c2007-12-20 01:14:43 -0300480 u16 lockState = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300481 int watchDogCount = 40;
Steven Tothe12671c2007-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 Tothe12671c2007-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
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300493#define XC_TUNE_ANALOG 0
494#define XC_TUNE_DIGITAL 1
495static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
Steven Tothaacb9d32007-12-18 01:55:51 -0300496{
497 int found = 0;
498
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300499 dprintk(1, "%s(%u)\n", __func__, freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300500
Steven Tothe12671c2007-12-20 01:14:43 -0300501 if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
Steven Tothaacb9d32007-12-18 01:55:51 -0300502 return 0;
503
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300504 if (mode == XC_TUNE_ANALOG) {
505 if (WaitForLock(priv) == 1)
506 found = 1;
507 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300508
509 return found;
510}
511
512static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
513{
514 u8 buf[2] = { reg >> 8, reg & 0xff };
515 u8 bval[2] = { 0, 0 };
516 struct i2c_msg msg[2] = {
Michael Krufky89fd2852008-09-06 11:44:53 -0300517 { .addr = priv->i2c_props.addr,
Steven Tothaacb9d32007-12-18 01:55:51 -0300518 .flags = 0, .buf = &buf[0], .len = 2 },
Michael Krufky89fd2852008-09-06 11:44:53 -0300519 { .addr = priv->i2c_props.addr,
Steven Tothaacb9d32007-12-18 01:55:51 -0300520 .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
521 };
522
Michael Krufky89fd2852008-09-06 11:44:53 -0300523 if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
Steven Toth27c685a2008-01-05 16:50:14 -0300524 printk(KERN_WARNING "xc5000: I2C read failed\n");
Steven Tothaacb9d32007-12-18 01:55:51 -0300525 return -EREMOTEIO;
526 }
527
528 *val = (bval[0] << 8) | bval[1];
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300529 return XC_RESULT_SUCCESS;
Steven Tothaacb9d32007-12-18 01:55:51 -0300530}
531
Steven Toth8f3cd532008-10-16 20:29:38 -0300532static int xc5000_fwupload(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300533{
534 struct xc5000_priv *priv = fe->tuner_priv;
535 const struct firmware *fw;
536 int ret;
537
Steven Tothe12671c2007-12-20 01:14:43 -0300538 /* request the firmware, this will block and timeout */
539 printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
540 XC5000_DEFAULT_FIRMWARE);
541
Steven Toth8f3cd532008-10-16 20:29:38 -0300542 ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE,
Jean Delvaree9785252009-04-26 05:43:59 -0300543 priv->i2c_props.adap->dev.parent);
Steven Tothaacb9d32007-12-18 01:55:51 -0300544 if (ret) {
545 printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
546 ret = XC_RESULT_RESET_FAILURE;
Steven Toth5ea60532008-01-24 22:29:46 -0300547 goto out;
Steven Tothaacb9d32007-12-18 01:55:51 -0300548 } else {
Michael Krufky3f514512007-12-21 16:20:23 -0300549 printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n",
550 fw->size);
Steven Tothaacb9d32007-12-18 01:55:51 -0300551 ret = XC_RESULT_SUCCESS;
552 }
553
Steven Tothe12671c2007-12-20 01:14:43 -0300554 if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300555 printk(KERN_ERR "xc5000: firmware incorrect size\n");
556 ret = XC_RESULT_RESET_FAILURE;
557 } else {
558 printk(KERN_INFO "xc5000: firmware upload\n");
Steven Toth8f3cd532008-10-16 20:29:38 -0300559 ret = xc_load_i2c_sequence(fe, fw->data);
Steven Tothaacb9d32007-12-18 01:55:51 -0300560 }
561
Steven Toth5ea60532008-01-24 22:29:46 -0300562out:
Steven Tothaacb9d32007-12-18 01:55:51 -0300563 release_firmware(fw);
564 return ret;
565}
566
Steven Tothe12671c2007-12-20 01:14:43 -0300567static void xc_debug_dump(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300568{
Steven Tothe12671c2007-12-20 01:14:43 -0300569 u16 adc_envelope;
570 u32 freq_error_hz = 0;
571 u16 lock_status;
572 u32 hsync_freq_hz = 0;
573 u16 frame_lines;
574 u16 quality;
575 u8 hw_majorversion = 0, hw_minorversion = 0;
576 u8 fw_majorversion = 0, fw_minorversion = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300577
578 /* Wait for stats to stabilize.
579 * Frame Lines needs two frame times after initial lock
580 * before it is valid.
581 */
Steven Tothe12671c2007-12-20 01:14:43 -0300582 xc_wait(100);
Steven Tothaacb9d32007-12-18 01:55:51 -0300583
Steven Tothe12671c2007-12-20 01:14:43 -0300584 xc_get_ADC_Envelope(priv, &adc_envelope);
585 dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
Steven Tothaacb9d32007-12-18 01:55:51 -0300586
Steven Tothe12671c2007-12-20 01:14:43 -0300587 xc_get_frequency_error(priv, &freq_error_hz);
588 dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300589
Steven Tothe12671c2007-12-20 01:14:43 -0300590 xc_get_lock_status(priv, &lock_status);
591 dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
Steven Tothaacb9d32007-12-18 01:55:51 -0300592 lock_status);
593
594 xc_get_version(priv, &hw_majorversion, &hw_minorversion,
Steven Tothe12671c2007-12-20 01:14:43 -0300595 &fw_majorversion, &fw_minorversion);
Steven Tothaacb9d32007-12-18 01:55:51 -0300596 dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
597 hw_majorversion, hw_minorversion,
598 fw_majorversion, fw_minorversion);
599
Steven Tothe12671c2007-12-20 01:14:43 -0300600 xc_get_hsync_freq(priv, &hsync_freq_hz);
601 dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300602
Steven Tothe12671c2007-12-20 01:14:43 -0300603 xc_get_frame_lines(priv, &frame_lines);
604 dprintk(1, "*** Frame lines = %d\n", frame_lines);
Steven Tothaacb9d32007-12-18 01:55:51 -0300605
Steven Tothe12671c2007-12-20 01:14:43 -0300606 xc_get_quality(priv, &quality);
607 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
Steven Tothaacb9d32007-12-18 01:55:51 -0300608}
609
610static int xc5000_set_params(struct dvb_frontend *fe,
611 struct dvb_frontend_parameters *params)
612{
613 struct xc5000_priv *priv = fe->tuner_priv;
Steven Tothe12671c2007-12-20 01:14:43 -0300614 int ret;
Steven Tothaacb9d32007-12-18 01:55:51 -0300615
Devin Heitmueller8e4c6792008-11-16 20:41:07 -0300616 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
617 xc_load_fw_and_init_tuner(fe);
618
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300619 dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
Steven Tothaacb9d32007-12-18 01:55:51 -0300620
Steven Toth8f3cd532008-10-16 20:29:38 -0300621 switch (params->u.vsb.modulation) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300622 case VSB_8:
623 case VSB_16:
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300624 dprintk(1, "%s() VSB modulation\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300625 priv->rf_mode = XC_RF_MODE_AIR;
Steven Tothe12671c2007-12-20 01:14:43 -0300626 priv->freq_hz = params->frequency - 1750000;
627 priv->bandwidth = BANDWIDTH_6_MHZ;
628 priv->video_standard = DTV6;
Steven Tothaacb9d32007-12-18 01:55:51 -0300629 break;
630 case QAM_64:
631 case QAM_256:
632 case QAM_AUTO:
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300633 dprintk(1, "%s() QAM modulation\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300634 priv->rf_mode = XC_RF_MODE_CABLE;
Steven Tothe12671c2007-12-20 01:14:43 -0300635 priv->freq_hz = params->frequency - 1750000;
636 priv->bandwidth = BANDWIDTH_6_MHZ;
637 priv->video_standard = DTV6;
Steven Tothaacb9d32007-12-18 01:55:51 -0300638 break;
639 default:
640 return -EINVAL;
641 }
642
643 dprintk(1, "%s() frequency=%d (compensated)\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300644 __func__, priv->freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300645
Steven Tothe12671c2007-12-20 01:14:43 -0300646 ret = xc_SetSignalSource(priv, priv->rf_mode);
647 if (ret != XC_RESULT_SUCCESS) {
648 printk(KERN_ERR
649 "xc5000: xc_SetSignalSource(%d) failed\n",
650 priv->rf_mode);
651 return -EREMOTEIO;
652 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300653
Steven Tothe12671c2007-12-20 01:14:43 -0300654 ret = xc_SetTVStandard(priv,
Steven Tothaacb9d32007-12-18 01:55:51 -0300655 XC5000_Standard[priv->video_standard].VideoMode,
656 XC5000_Standard[priv->video_standard].AudioMode);
Steven Tothe12671c2007-12-20 01:14:43 -0300657 if (ret != XC_RESULT_SUCCESS) {
658 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
659 return -EREMOTEIO;
660 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300661
Michael Krufky2a6003c2008-09-06 13:54:45 -0300662 ret = xc_set_IF_frequency(priv, priv->if_khz);
Steven Tothe12671c2007-12-20 01:14:43 -0300663 if (ret != XC_RESULT_SUCCESS) {
664 printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
Michael Krufky2a6003c2008-09-06 13:54:45 -0300665 priv->if_khz);
Steven Tothe12671c2007-12-20 01:14:43 -0300666 return -EIO;
667 }
668
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300669 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
Steven Tothe12671c2007-12-20 01:14:43 -0300670
671 if (debug)
672 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -0300673
674 return 0;
675}
676
Steven Tothe470d812008-06-21 21:06:02 -0300677static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
678{
679 struct xc5000_priv *priv = fe->tuner_priv;
680 int ret;
681 u16 id;
682
683 ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
684 if (ret == XC_RESULT_SUCCESS) {
685 if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
686 ret = XC_RESULT_RESET_FAILURE;
687 else
688 ret = XC_RESULT_SUCCESS;
689 }
690
691 dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
692 ret == XC_RESULT_SUCCESS ? "True" : "False", id);
693 return ret;
694}
695
Steven Toth27c685a2008-01-05 16:50:14 -0300696static int xc5000_set_analog_params(struct dvb_frontend *fe,
697 struct analog_parameters *params)
698{
699 struct xc5000_priv *priv = fe->tuner_priv;
700 int ret;
701
Steven Tothe470d812008-06-21 21:06:02 -0300702 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
Steven Toth27c685a2008-01-05 16:50:14 -0300703 xc_load_fw_and_init_tuner(fe);
704
705 dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300706 __func__, params->frequency);
Steven Toth27c685a2008-01-05 16:50:14 -0300707
Mauro Carvalho Chehab1fab14e2009-03-03 14:35:41 -0300708 /* Fix me: it could be air. */
709 priv->rf_mode = params->mode;
710 if (params->mode > XC_RF_MODE_CABLE)
711 priv->rf_mode = XC_RF_MODE_CABLE;
Steven Toth27c685a2008-01-05 16:50:14 -0300712
713 /* params->frequency is in units of 62.5khz */
714 priv->freq_hz = params->frequency * 62500;
715
716 /* FIX ME: Some video standards may have several possible audio
717 standards. We simply default to one of them here.
718 */
Steven Toth8f3cd532008-10-16 20:29:38 -0300719 if (params->std & V4L2_STD_MN) {
Steven Toth27c685a2008-01-05 16:50:14 -0300720 /* default to BTSC audio standard */
721 priv->video_standard = MN_NTSC_PAL_BTSC;
722 goto tune_channel;
723 }
724
Steven Toth8f3cd532008-10-16 20:29:38 -0300725 if (params->std & V4L2_STD_PAL_BG) {
Steven Toth27c685a2008-01-05 16:50:14 -0300726 /* default to NICAM audio standard */
727 priv->video_standard = BG_PAL_NICAM;
728 goto tune_channel;
729 }
730
Steven Toth8f3cd532008-10-16 20:29:38 -0300731 if (params->std & V4L2_STD_PAL_I) {
Steven Toth27c685a2008-01-05 16:50:14 -0300732 /* default to NICAM audio standard */
733 priv->video_standard = I_PAL_NICAM;
734 goto tune_channel;
735 }
736
Steven Toth8f3cd532008-10-16 20:29:38 -0300737 if (params->std & V4L2_STD_PAL_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300738 /* default to NICAM audio standard */
739 priv->video_standard = DK_PAL_NICAM;
740 goto tune_channel;
741 }
742
Steven Toth8f3cd532008-10-16 20:29:38 -0300743 if (params->std & V4L2_STD_SECAM_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300744 /* default to A2 DK1 audio standard */
745 priv->video_standard = DK_SECAM_A2DK1;
746 goto tune_channel;
747 }
748
Steven Toth8f3cd532008-10-16 20:29:38 -0300749 if (params->std & V4L2_STD_SECAM_L) {
Steven Toth27c685a2008-01-05 16:50:14 -0300750 priv->video_standard = L_SECAM_NICAM;
751 goto tune_channel;
752 }
753
Steven Toth8f3cd532008-10-16 20:29:38 -0300754 if (params->std & V4L2_STD_SECAM_LC) {
Steven Toth27c685a2008-01-05 16:50:14 -0300755 priv->video_standard = LC_SECAM_NICAM;
756 goto tune_channel;
757 }
758
759tune_channel:
760 ret = xc_SetSignalSource(priv, priv->rf_mode);
761 if (ret != XC_RESULT_SUCCESS) {
Steven Toth8f3cd532008-10-16 20:29:38 -0300762 printk(KERN_ERR
Steven Toth27c685a2008-01-05 16:50:14 -0300763 "xc5000: xc_SetSignalSource(%d) failed\n",
764 priv->rf_mode);
765 return -EREMOTEIO;
766 }
767
768 ret = xc_SetTVStandard(priv,
769 XC5000_Standard[priv->video_standard].VideoMode,
770 XC5000_Standard[priv->video_standard].AudioMode);
771 if (ret != XC_RESULT_SUCCESS) {
772 printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
773 return -EREMOTEIO;
774 }
775
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300776 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
Steven Toth27c685a2008-01-05 16:50:14 -0300777
778 if (debug)
779 xc_debug_dump(priv);
780
781 return 0;
782}
783
Steven Tothaacb9d32007-12-18 01:55:51 -0300784static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
785{
786 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300787 dprintk(1, "%s()\n", __func__);
Steven Tothe12671c2007-12-20 01:14:43 -0300788 *freq = priv->freq_hz;
Steven Tothaacb9d32007-12-18 01:55:51 -0300789 return 0;
790}
791
792static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
793{
794 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300795 dprintk(1, "%s()\n", __func__);
Steven Toth27c685a2008-01-05 16:50:14 -0300796
Steven Tothaacb9d32007-12-18 01:55:51 -0300797 *bw = priv->bandwidth;
798 return 0;
799}
800
801static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
802{
803 struct xc5000_priv *priv = fe->tuner_priv;
Steven Tothe12671c2007-12-20 01:14:43 -0300804 u16 lock_status = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300805
806 xc_get_lock_status(priv, &lock_status);
807
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300808 dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
Steven Tothaacb9d32007-12-18 01:55:51 -0300809
810 *status = lock_status;
811
812 return 0;
813}
814
Steven Tothe12671c2007-12-20 01:14:43 -0300815static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300816{
817 struct xc5000_priv *priv = fe->tuner_priv;
Steven Toth27c685a2008-01-05 16:50:14 -0300818 int ret = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300819
Steven Tothe470d812008-06-21 21:06:02 -0300820 if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300821 ret = xc5000_fwupload(fe);
Steven Tothe12671c2007-12-20 01:14:43 -0300822 if (ret != XC_RESULT_SUCCESS)
823 return ret;
Steven Tothaacb9d32007-12-18 01:55:51 -0300824 }
825
826 /* Start the tuner self-calibration process */
827 ret |= xc_initialize(priv);
828
829 /* Wait for calibration to complete.
830 * We could continue but XC5000 will clock stretch subsequent
831 * I2C transactions until calibration is complete. This way we
832 * don't have to rely on clock stretching working.
833 */
Steven Toth8f3cd532008-10-16 20:29:38 -0300834 xc_wait(100);
Steven Tothaacb9d32007-12-18 01:55:51 -0300835
836 /* Default to "CABLE" mode */
837 ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
838
839 return ret;
840}
841
Steven Tothe12671c2007-12-20 01:14:43 -0300842static int xc5000_sleep(struct dvb_frontend *fe)
843{
844 struct xc5000_priv *priv = fe->tuner_priv;
Steven Toth27c685a2008-01-05 16:50:14 -0300845 int ret;
846
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300847 dprintk(1, "%s()\n", __func__);
Steven Tothe12671c2007-12-20 01:14:43 -0300848
Devin Heitmueller8e4c6792008-11-16 20:41:07 -0300849 ret = xc_write_reg(priv, XREG_POWER_DOWN, 0);
Steven Toth8f3cd532008-10-16 20:29:38 -0300850 if (ret != XC_RESULT_SUCCESS) {
Steven Toth27c685a2008-01-05 16:50:14 -0300851 printk(KERN_ERR
852 "xc5000: %s() unable to shutdown tuner\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300853 __func__);
Steven Toth27c685a2008-01-05 16:50:14 -0300854 return -EREMOTEIO;
Steven Toth8f3cd532008-10-16 20:29:38 -0300855 } else
Steven Toth27c685a2008-01-05 16:50:14 -0300856 return XC_RESULT_SUCCESS;
Steven Tothe12671c2007-12-20 01:14:43 -0300857}
858
Steven Tothaacb9d32007-12-18 01:55:51 -0300859static int xc5000_init(struct dvb_frontend *fe)
860{
861 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300862 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300863
Steven Tothe12671c2007-12-20 01:14:43 -0300864 if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
865 printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
866 return -EREMOTEIO;
867 }
868
869 if (debug)
870 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -0300871
872 return 0;
873}
874
875static int xc5000_release(struct dvb_frontend *fe)
876{
Michael Krufky89fd2852008-09-06 11:44:53 -0300877 struct xc5000_priv *priv = fe->tuner_priv;
878
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300879 dprintk(1, "%s()\n", __func__);
Michael Krufky89fd2852008-09-06 11:44:53 -0300880
881 mutex_lock(&xc5000_list_mutex);
882
883 if (priv)
884 hybrid_tuner_release_state(priv);
885
886 mutex_unlock(&xc5000_list_mutex);
887
Steven Tothaacb9d32007-12-18 01:55:51 -0300888 fe->tuner_priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -0300889
Steven Tothaacb9d32007-12-18 01:55:51 -0300890 return 0;
891}
892
893static const struct dvb_tuner_ops xc5000_tuner_ops = {
894 .info = {
895 .name = "Xceive XC5000",
896 .frequency_min = 1000000,
897 .frequency_max = 1023000000,
898 .frequency_step = 50000,
899 },
900
Steven Toth27c685a2008-01-05 16:50:14 -0300901 .release = xc5000_release,
902 .init = xc5000_init,
903 .sleep = xc5000_sleep,
Steven Tothaacb9d32007-12-18 01:55:51 -0300904
Steven Toth27c685a2008-01-05 16:50:14 -0300905 .set_params = xc5000_set_params,
906 .set_analog_params = xc5000_set_analog_params,
907 .get_frequency = xc5000_get_frequency,
908 .get_bandwidth = xc5000_get_bandwidth,
909 .get_status = xc5000_get_status
Steven Tothaacb9d32007-12-18 01:55:51 -0300910};
911
Michael Krufky48723542008-05-10 14:34:09 -0300912struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
913 struct i2c_adapter *i2c,
Michael Krufky30650962008-09-06 14:56:58 -0300914 struct xc5000_config *cfg)
Steven Tothaacb9d32007-12-18 01:55:51 -0300915{
916 struct xc5000_priv *priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -0300917 int instance;
Steven Tothaacb9d32007-12-18 01:55:51 -0300918 u16 id = 0;
919
Michael Krufky89fd2852008-09-06 11:44:53 -0300920 dprintk(1, "%s(%d-%04x)\n", __func__,
921 i2c ? i2c_adapter_id(i2c) : -1,
922 cfg ? cfg->i2c_address : -1);
Steven Tothaacb9d32007-12-18 01:55:51 -0300923
Michael Krufky89fd2852008-09-06 11:44:53 -0300924 mutex_lock(&xc5000_list_mutex);
Steven Tothaacb9d32007-12-18 01:55:51 -0300925
Michael Krufky89fd2852008-09-06 11:44:53 -0300926 instance = hybrid_tuner_request_state(struct xc5000_priv, priv,
927 hybrid_tuner_instance_list,
928 i2c, cfg->i2c_address, "xc5000");
929 switch (instance) {
930 case 0:
931 goto fail;
932 break;
933 case 1:
934 /* new tuner instance */
Michael Krufky89fd2852008-09-06 11:44:53 -0300935 priv->bandwidth = BANDWIDTH_6_MHZ;
Michael Krufky89fd2852008-09-06 11:44:53 -0300936 fe->tuner_priv = priv;
937 break;
938 default:
939 /* existing tuner instance */
940 fe->tuner_priv = priv;
941 break;
942 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300943
Devin Heitmuellerea227862009-03-11 02:58:53 -0300944 if (priv->if_khz == 0) {
945 /* If the IF hasn't been set yet, use the value provided by
946 the caller (occurs in hybrid devices where the analog
947 call to xc5000_attach occurs before the digital side) */
948 priv->if_khz = cfg->if_khz;
949 }
950
Steven Toth27c685a2008-01-05 16:50:14 -0300951 /* Check if firmware has been loaded. It is possible that another
952 instance of the driver has loaded the firmware.
953 */
Devin Heitmueller7988fc22008-11-16 20:23:19 -0300954 if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS)
Michael Krufky89fd2852008-09-06 11:44:53 -0300955 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -0300956
Steven Toth8f3cd532008-10-16 20:29:38 -0300957 switch (id) {
Steven Toth27c685a2008-01-05 16:50:14 -0300958 case XC_PRODUCT_ID_FW_LOADED:
959 printk(KERN_INFO
960 "xc5000: Successfully identified at address 0x%02x\n",
961 cfg->i2c_address);
962 printk(KERN_INFO
963 "xc5000: Firmware has been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -0300964 break;
965 case XC_PRODUCT_ID_FW_NOT_LOADED:
966 printk(KERN_INFO
967 "xc5000: Successfully identified at address 0x%02x\n",
968 cfg->i2c_address);
969 printk(KERN_INFO
970 "xc5000: Firmware has not been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -0300971 break;
972 default:
Steven Tothaacb9d32007-12-18 01:55:51 -0300973 printk(KERN_ERR
974 "xc5000: Device not found at addr 0x%02x (0x%x)\n",
975 cfg->i2c_address, id);
Michael Krufky89fd2852008-09-06 11:44:53 -0300976 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -0300977 }
978
Michael Krufky89fd2852008-09-06 11:44:53 -0300979 mutex_unlock(&xc5000_list_mutex);
980
Steven Tothaacb9d32007-12-18 01:55:51 -0300981 memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
982 sizeof(struct dvb_tuner_ops));
983
Steven Tothaacb9d32007-12-18 01:55:51 -0300984 return fe;
Michael Krufky89fd2852008-09-06 11:44:53 -0300985fail:
986 mutex_unlock(&xc5000_list_mutex);
987
988 xc5000_release(fe);
989 return NULL;
Steven Tothaacb9d32007-12-18 01:55:51 -0300990}
991EXPORT_SYMBOL(xc5000_attach);
992
993MODULE_AUTHOR("Steven Toth");
Steven Tothe12671c2007-12-20 01:14:43 -0300994MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
Steven Tothaacb9d32007-12-18 01:55:51 -0300995MODULE_LICENSE("GPL");