blob: ab7d444bcdcc85e6bb6b4c6a4d4743a49999d948 [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>
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -030028#include <linux/workqueue.h>
Steven Tothaacb9d32007-12-18 01:55:51 -030029#include <linux/dvb/frontend.h>
30#include <linux/i2c.h>
31
32#include "dvb_frontend.h"
33
34#include "xc5000.h"
Michael Krufky89fd2852008-09-06 11:44:53 -030035#include "tuner-i2c.h"
Steven Tothaacb9d32007-12-18 01:55:51 -030036
37static int debug;
38module_param(debug, int, 0644);
39MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
40
Devin Heitmuellerb6bd5eb2009-04-28 13:53:38 -030041static int no_poweroff;
42module_param(no_poweroff, int, 0644);
43MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n"
44 "\t\t1 keep device energized and with tuner ready all the times.\n"
45 "\t\tFaster, but consumes more power and keeps the device hotter");
46
Michael Krufky89fd2852008-09-06 11:44:53 -030047static DEFINE_MUTEX(xc5000_list_mutex);
48static LIST_HEAD(hybrid_tuner_instance_list);
49
Steven Toth8f3cd532008-10-16 20:29:38 -030050#define dprintk(level, fmt, arg...) if (debug >= level) \
Steven Tothaacb9d32007-12-18 01:55:51 -030051 printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
52
Michael Krufkyffb41232008-09-06 10:52:30 -030053struct xc5000_priv {
Michael Krufky89fd2852008-09-06 11:44:53 -030054 struct tuner_i2c_props i2c_props;
55 struct list_head hybrid_tuner_instance_list;
Michael Krufkyffb41232008-09-06 10:52:30 -030056
Michael Krufky2a6003c2008-09-06 13:54:45 -030057 u32 if_khz;
Michael Krufky409328a2012-04-16 15:21:51 -030058 u16 xtal_khz;
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -030059 u32 freq_hz, freq_offset;
Michael Krufkyffb41232008-09-06 10:52:30 -030060 u32 bandwidth;
61 u8 video_standard;
62 u8 rf_mode;
Devin Heitmueller496e9052009-09-24 13:27:24 -030063 u8 radio_input;
Michael Krufky76efb0ba2012-02-06 19:40:32 -030064
Michael Krufky6fab81d2012-02-08 14:57:39 -030065 int chip_id;
Devin Heitmuellerde49bc62012-08-06 22:47:08 -030066 u16 pll_register_no;
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -030067 u8 init_status_supported;
68 u8 fw_checksum_supported;
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -030069
70 struct dvb_frontend *fe;
71 struct delayed_work timer_sleep;
Michael Krufkyffb41232008-09-06 10:52:30 -030072};
73
Steven Tothaacb9d32007-12-18 01:55:51 -030074/* Misc Defines */
Dmitri Belimov724dcbf2011-02-01 05:25:19 -030075#define MAX_TV_STANDARD 24
Steven Tothaacb9d32007-12-18 01:55:51 -030076#define XC_MAX_I2C_WRITE_LENGTH 64
77
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -030078/* Time to suspend after the .sleep callback is called */
79#define XC5000_SLEEP_TIME 5000 /* ms */
80
Steven Tothaacb9d32007-12-18 01:55:51 -030081/* Signal Types */
82#define XC_RF_MODE_AIR 0
83#define XC_RF_MODE_CABLE 1
84
Steven Toth27c685a2008-01-05 16:50:14 -030085/* Product id */
86#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
Mauro Carvalho Chehab5015c272014-05-21 13:41:01 -030087#define XC_PRODUCT_ID_FW_LOADED 0x1388
Steven Toth27c685a2008-01-05 16:50:14 -030088
Steven Tothaacb9d32007-12-18 01:55:51 -030089/* Registers */
90#define XREG_INIT 0x00
91#define XREG_VIDEO_MODE 0x01
92#define XREG_AUDIO_MODE 0x02
93#define XREG_RF_FREQ 0x03
94#define XREG_D_CODE 0x04
95#define XREG_IF_OUT 0x05
96#define XREG_SEEK_MODE 0x07
Devin Heitmueller7f05b532009-04-02 22:02:39 -030097#define XREG_POWER_DOWN 0x0A /* Obsolete */
Dmitri Belimov724dcbf2011-02-01 05:25:19 -030098/* Set the output amplitude - SIF for analog, DTVP/DTVN for digital */
99#define XREG_OUTPUT_AMP 0x0B
Steven Tothaacb9d32007-12-18 01:55:51 -0300100#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
101#define XREG_SMOOTHEDCVBS 0x0E
102#define XREG_XTALFREQ 0x0F
Devin Heitmueller81c4dfe2009-04-02 22:40:29 -0300103#define XREG_FINERFREQ 0x10
Steven Tothaacb9d32007-12-18 01:55:51 -0300104#define XREG_DDIMODE 0x11
105
106#define XREG_ADC_ENV 0x00
107#define XREG_QUALITY 0x01
108#define XREG_FRAME_LINES 0x02
109#define XREG_HSYNC_FREQ 0x03
110#define XREG_LOCK 0x04
111#define XREG_FREQ_ERROR 0x05
112#define XREG_SNR 0x06
113#define XREG_VERSION 0x07
114#define XREG_PRODUCT_ID 0x08
115#define XREG_BUSY 0x09
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300116#define XREG_BUILD 0x0D
Devin Heitmueller7c287f12012-08-06 22:46:56 -0300117#define XREG_TOTALGAIN 0x0F
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -0300118#define XREG_FW_CHECKSUM 0x12
119#define XREG_INIT_STATUS 0x13
Steven Tothaacb9d32007-12-18 01:55:51 -0300120
121/*
122 Basic firmware description. This will remain with
123 the driver for documentation purposes.
124
125 This represents an I2C firmware file encoded as a
126 string of unsigned char. Format is as follows:
127
128 char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB
129 char[1 ]=len0_LSB -> length of first write transaction
130 char[2 ]=data0 -> first byte to be sent
131 char[3 ]=data1
132 char[4 ]=data2
133 char[ ]=...
134 char[M ]=dataN -> last byte to be sent
135 char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB
136 char[M+2]=len1_LSB -> length of second write transaction
137 char[M+3]=data0
138 char[M+4]=data1
139 ...
140 etc.
141
142 The [len] value should be interpreted as follows:
143
144 len= len_MSB _ len_LSB
145 len=1111_1111_1111_1111 : End of I2C_SEQUENCE
146 len=0000_0000_0000_0000 : Reset command: Do hardware reset
147 len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767)
148 len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms
149
150 For the RESET and WAIT commands, the two following bytes will contain
151 immediately the length of the following transaction.
152
153*/
Steven Toth8f3cd532008-10-16 20:29:38 -0300154struct XC_TV_STANDARD {
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300155 char *name;
156 u16 audio_mode;
157 u16 video_mode;
Steven Toth8f3cd532008-10-16 20:29:38 -0300158};
Steven Tothaacb9d32007-12-18 01:55:51 -0300159
160/* Tuner standards */
Steven Toth27c685a2008-01-05 16:50:14 -0300161#define MN_NTSC_PAL_BTSC 0
162#define MN_NTSC_PAL_A2 1
163#define MN_NTSC_PAL_EIAJ 2
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300164#define MN_NTSC_PAL_MONO 3
Steven Toth27c685a2008-01-05 16:50:14 -0300165#define BG_PAL_A2 4
166#define BG_PAL_NICAM 5
167#define BG_PAL_MONO 6
168#define I_PAL_NICAM 7
169#define I_PAL_NICAM_MONO 8
170#define DK_PAL_A2 9
171#define DK_PAL_NICAM 10
172#define DK_PAL_MONO 11
173#define DK_SECAM_A2DK1 12
Mauro Carvalho Chehab5015c272014-05-21 13:41:01 -0300174#define DK_SECAM_A2LDK3 13
175#define DK_SECAM_A2MONO 14
Steven Toth27c685a2008-01-05 16:50:14 -0300176#define L_SECAM_NICAM 15
177#define LC_SECAM_NICAM 16
178#define DTV6 17
179#define DTV8 18
180#define DTV7_8 19
181#define DTV7 20
Mauro Carvalho Chehab5015c272014-05-21 13:41:01 -0300182#define FM_RADIO_INPUT2 21
183#define FM_RADIO_INPUT1 22
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300184#define FM_RADIO_INPUT1_MONO 23
Steven Tothaacb9d32007-12-18 01:55:51 -0300185
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300186static struct XC_TV_STANDARD xc5000_standard[MAX_TV_STANDARD] = {
Steven Tothaacb9d32007-12-18 01:55:51 -0300187 {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
188 {"M/N-NTSC/PAL-A2", 0x0600, 0x8020},
189 {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
190 {"M/N-NTSC/PAL-Mono", 0x0478, 0x8020},
191 {"B/G-PAL-A2", 0x0A00, 0x8049},
192 {"B/G-PAL-NICAM", 0x0C04, 0x8049},
193 {"B/G-PAL-MONO", 0x0878, 0x8059},
194 {"I-PAL-NICAM", 0x1080, 0x8009},
195 {"I-PAL-NICAM-MONO", 0x0E78, 0x8009},
196 {"D/K-PAL-A2", 0x1600, 0x8009},
197 {"D/K-PAL-NICAM", 0x0E80, 0x8009},
198 {"D/K-PAL-MONO", 0x1478, 0x8009},
199 {"D/K-SECAM-A2 DK1", 0x1200, 0x8009},
Steven Toth8f3cd532008-10-16 20:29:38 -0300200 {"D/K-SECAM-A2 L/DK3", 0x0E00, 0x8009},
Steven Tothaacb9d32007-12-18 01:55:51 -0300201 {"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
202 {"L-SECAM-NICAM", 0x8E82, 0x0009},
203 {"L'-SECAM-NICAM", 0x8E82, 0x4009},
204 {"DTV6", 0x00C0, 0x8002},
205 {"DTV8", 0x00C0, 0x800B},
206 {"DTV7/8", 0x00C0, 0x801B},
207 {"DTV7", 0x00C0, 0x8007},
208 {"FM Radio-INPUT2", 0x9802, 0x9002},
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300209 {"FM Radio-INPUT1", 0x0208, 0x9002},
210 {"FM Radio-INPUT1_MONO", 0x0278, 0x9002}
Steven Tothaacb9d32007-12-18 01:55:51 -0300211};
212
Michael Krufkyddea4272012-02-07 02:39:36 -0300213
214struct xc5000_fw_cfg {
215 char *name;
216 u16 size;
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300217 u16 pll_reg;
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -0300218 u8 init_status_supported;
219 u8 fw_checksum_supported;
Michael Krufkyddea4272012-02-07 02:39:36 -0300220};
221
Tim Gardner3422f2a62012-07-25 09:15:19 -0300222#define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw"
Michael Krufkya3db60b2012-02-08 15:03:07 -0300223static const struct xc5000_fw_cfg xc5000a_1_6_114 = {
Tim Gardner3422f2a62012-07-25 09:15:19 -0300224 .name = XC5000A_FIRMWARE,
Michael Krufky76efb0ba2012-02-06 19:40:32 -0300225 .size = 12401,
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300226 .pll_reg = 0x806c,
Michael Krufky76efb0ba2012-02-06 19:40:32 -0300227};
228
Devin Heitmueller3de5bff2012-08-06 22:47:14 -0300229#define XC5000C_FIRMWARE "dvb-fe-xc5000c-4.1.30.7.fw"
Michael Krufky7d3d0d82012-04-16 14:59:32 -0300230static const struct xc5000_fw_cfg xc5000c_41_024_5 = {
Tim Gardner3422f2a62012-07-25 09:15:19 -0300231 .name = XC5000C_FIRMWARE,
Michael Krufky7d3d0d82012-04-16 14:59:32 -0300232 .size = 16497,
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300233 .pll_reg = 0x13,
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -0300234 .init_status_supported = 1,
235 .fw_checksum_supported = 1,
Michael Krufkyd8398802012-02-07 01:16:27 -0300236};
237
Michael Krufkya3db60b2012-02-08 15:03:07 -0300238static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
Michael Krufkyddea4272012-02-07 02:39:36 -0300239{
Michael Krufky6fab81d2012-02-08 14:57:39 -0300240 switch (chip_id) {
Michael Krufkyddea4272012-02-07 02:39:36 -0300241 default:
Michael Krufky6fab81d2012-02-08 14:57:39 -0300242 case XC5000A:
Michael Krufkyddea4272012-02-07 02:39:36 -0300243 return &xc5000a_1_6_114;
Michael Krufky6fab81d2012-02-08 14:57:39 -0300244 case XC5000C:
Michael Krufky7d3d0d82012-04-16 14:59:32 -0300245 return &xc5000c_41_024_5;
Michael Krufkyddea4272012-02-07 02:39:36 -0300246 }
247}
248
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300249static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force);
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300250static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300251static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300252static int xc5000_tuner_reset(struct dvb_frontend *fe);
Steven Tothaacb9d32007-12-18 01:55:51 -0300253
Steven Tothe12671c2007-12-20 01:14:43 -0300254static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
Steven Tothaacb9d32007-12-18 01:55:51 -0300255{
Devin Heitmuellerd7800d42008-11-16 20:20:06 -0300256 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
257 .flags = 0, .buf = buf, .len = len };
258
259 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
260 printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300261 return -EREMOTEIO;
Devin Heitmuellerd7800d42008-11-16 20:20:06 -0300262 }
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300263 return 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300264}
265
Mauro Carvalho Chehab1cdffda2010-07-05 18:38:46 -0300266#if 0
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300267/* This routine is never used because the only time we read data from the
268 i2c bus is when we read registers, and we want that to be an atomic i2c
269 transaction in case we are on a multi-master bus */
Steven Tothe12671c2007-12-20 01:14:43 -0300270static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
Steven Tothaacb9d32007-12-18 01:55:51 -0300271{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300272 struct i2c_msg msg = { .addr = priv->i2c_props.addr,
273 .flags = I2C_M_RD, .buf = buf, .len = len };
274
275 if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
276 printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", len);
277 return -EREMOTEIO;
278 }
279 return 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300280}
Mauro Carvalho Chehab1cdffda2010-07-05 18:38:46 -0300281#endif
Steven Tothaacb9d32007-12-18 01:55:51 -0300282
Dmitri Belimov47433192010-05-18 04:30:11 -0300283static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
284{
285 u8 buf[2] = { reg >> 8, reg & 0xff };
286 u8 bval[2] = { 0, 0 };
287 struct i2c_msg msg[2] = {
288 { .addr = priv->i2c_props.addr,
289 .flags = 0, .buf = &buf[0], .len = 2 },
290 { .addr = priv->i2c_props.addr,
291 .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
292 };
293
294 if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
295 printk(KERN_WARNING "xc5000: I2C read failed\n");
296 return -EREMOTEIO;
297 }
298
299 *val = (bval[0] << 8) | bval[1];
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300300 return 0;
Dmitri Belimov47433192010-05-18 04:30:11 -0300301}
302
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300303static int xc5000_tuner_reset(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300304{
305 struct xc5000_priv *priv = fe->tuner_priv;
306 int ret;
307
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300308 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300309
Michael Krufkyd7cba042008-09-12 13:31:45 -0300310 if (fe->callback) {
311 ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
Michael Krufky30650962008-09-06 14:56:58 -0300312 fe->dvb->priv :
313 priv->i2c_props.adap->algo_data,
Michael Krufkyd7cba042008-09-12 13:31:45 -0300314 DVB_FRONTEND_COMPONENT_TUNER,
Michael Krufky30650962008-09-06 14:56:58 -0300315 XC5000_TUNER_RESET, 0);
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300316 if (ret) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300317 printk(KERN_ERR "xc5000: reset failed\n");
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300318 return ret;
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300319 }
320 } else {
Steven Toth27c685a2008-01-05 16:50:14 -0300321 printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300322 return -EINVAL;
Devin Heitmueller91bd6252008-11-15 23:29:11 -0300323 }
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300324 return 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300325}
326
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300327static int xc_write_reg(struct xc5000_priv *priv, u16 reg_addr, u16 i2c_data)
Steven Tothaacb9d32007-12-18 01:55:51 -0300328{
Steven Tothe12671c2007-12-20 01:14:43 -0300329 u8 buf[4];
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300330 int watch_dog_timer = 100;
Steven Tothaacb9d32007-12-18 01:55:51 -0300331 int result;
332
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300333 buf[0] = (reg_addr >> 8) & 0xFF;
334 buf[1] = reg_addr & 0xFF;
335 buf[2] = (i2c_data >> 8) & 0xFF;
336 buf[3] = i2c_data & 0xFF;
Steven Tothaacb9d32007-12-18 01:55:51 -0300337 result = xc_send_i2c_data(priv, buf, 4);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300338 if (result == 0) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300339 /* wait for busy flag to clear */
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300340 while ((watch_dog_timer > 0) && (result == 0)) {
Mauro Carvalho Chehab1cdffda2010-07-05 18:38:46 -0300341 result = xc5000_readreg(priv, XREG_BUSY, (u16 *)buf);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300342 if (result == 0) {
Dmitri Belimov47433192010-05-18 04:30:11 -0300343 if ((buf[0] == 0) && (buf[1] == 0)) {
344 /* busy flag cleared */
Steven Tothaacb9d32007-12-18 01:55:51 -0300345 break;
Dmitri Belimov47433192010-05-18 04:30:11 -0300346 } else {
Mauro Carvalho Chehabe5bf4a12014-05-21 13:15:17 -0300347 msleep(5); /* wait 5 ms */
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300348 watch_dog_timer--;
Steven Tothaacb9d32007-12-18 01:55:51 -0300349 }
350 }
351 }
352 }
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300353 if (watch_dog_timer <= 0)
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300354 result = -EREMOTEIO;
Steven Tothaacb9d32007-12-18 01:55:51 -0300355
356 return result;
357}
358
David Woodhousec63e87e2008-05-24 00:13:34 +0100359static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
Steven Tothaacb9d32007-12-18 01:55:51 -0300360{
361 struct xc5000_priv *priv = fe->tuner_priv;
362
363 int i, nbytes_to_send, result;
364 unsigned int len, pos, index;
Steven Tothe12671c2007-12-20 01:14:43 -0300365 u8 buf[XC_MAX_I2C_WRITE_LENGTH];
Steven Tothaacb9d32007-12-18 01:55:51 -0300366
Steven Toth8f3cd532008-10-16 20:29:38 -0300367 index = 0;
368 while ((i2c_sequence[index] != 0xFF) ||
369 (i2c_sequence[index + 1] != 0xFF)) {
370 len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
Steven Tothe12671c2007-12-20 01:14:43 -0300371 if (len == 0x0000) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300372 /* RESET command */
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300373 result = xc5000_tuner_reset(fe);
Steven Tothaacb9d32007-12-18 01:55:51 -0300374 index += 2;
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300375 if (result != 0)
Steven Tothaacb9d32007-12-18 01:55:51 -0300376 return result;
377 } else if (len & 0x8000) {
378 /* WAIT command */
Mauro Carvalho Chehabe5bf4a12014-05-21 13:15:17 -0300379 msleep(len & 0x7FFF);
Steven Tothaacb9d32007-12-18 01:55:51 -0300380 index += 2;
381 } else {
382 /* Send i2c data whilst ensuring individual transactions
383 * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
384 */
385 index += 2;
386 buf[0] = i2c_sequence[index];
387 buf[1] = i2c_sequence[index + 1];
388 pos = 2;
389 while (pos < len) {
Steven Toth8f3cd532008-10-16 20:29:38 -0300390 if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
391 nbytes_to_send =
392 XC_MAX_I2C_WRITE_LENGTH;
393 else
Steven Tothaacb9d32007-12-18 01:55:51 -0300394 nbytes_to_send = (len - pos + 2);
Steven Toth8f3cd532008-10-16 20:29:38 -0300395 for (i = 2; i < nbytes_to_send; i++) {
396 buf[i] = i2c_sequence[index + pos +
397 i - 2];
Steven Tothaacb9d32007-12-18 01:55:51 -0300398 }
Steven Toth8f3cd532008-10-16 20:29:38 -0300399 result = xc_send_i2c_data(priv, buf,
400 nbytes_to_send);
Steven Tothaacb9d32007-12-18 01:55:51 -0300401
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300402 if (result != 0)
Steven Tothaacb9d32007-12-18 01:55:51 -0300403 return result;
404
405 pos += nbytes_to_send - 2;
406 }
407 index += len;
408 }
409 }
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300410 return 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300411}
412
Steven Tothe12671c2007-12-20 01:14:43 -0300413static int xc_initialize(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300414{
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300415 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300416 return xc_write_reg(priv, XREG_INIT, 0);
417}
418
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300419static int xc_set_tv_standard(struct xc5000_priv *priv,
420 u16 video_mode, u16 audio_mode, u8 radio_mode)
Steven Tothaacb9d32007-12-18 01:55:51 -0300421{
422 int ret;
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300423 dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, video_mode, audio_mode);
424 if (radio_mode) {
Dmitri Belimov01ae7282013-03-13 00:23:36 -0300425 dprintk(1, "%s() Standard = %s\n",
426 __func__,
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300427 xc5000_standard[radio_mode].name);
Dmitri Belimov01ae7282013-03-13 00:23:36 -0300428 } else {
429 dprintk(1, "%s() Standard = %s\n",
430 __func__,
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300431 xc5000_standard[priv->video_standard].name);
Dmitri Belimov01ae7282013-03-13 00:23:36 -0300432 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300433
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300434 ret = xc_write_reg(priv, XREG_VIDEO_MODE, video_mode);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300435 if (ret == 0)
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300436 ret = xc_write_reg(priv, XREG_AUDIO_MODE, audio_mode);
Steven Tothaacb9d32007-12-18 01:55:51 -0300437
438 return ret;
439}
440
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300441static int xc_set_signal_source(struct xc5000_priv *priv, u16 rf_mode)
Steven Tothaacb9d32007-12-18 01:55:51 -0300442{
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300443 dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
Steven Tothaacb9d32007-12-18 01:55:51 -0300444 rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
445
Steven Toth8f3cd532008-10-16 20:29:38 -0300446 if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300447 rf_mode = XC_RF_MODE_CABLE;
448 printk(KERN_ERR
449 "%s(), Invalid mode, defaulting to CABLE",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300450 __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -0300451 }
452 return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
453}
454
Steven Tothe12671c2007-12-20 01:14:43 -0300455static const struct dvb_tuner_ops xc5000_tuner_ops;
456
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300457static int xc_set_rf_frequency(struct xc5000_priv *priv, u32 freq_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300458{
Steven Tothe12671c2007-12-20 01:14:43 -0300459 u16 freq_code;
Steven Tothaacb9d32007-12-18 01:55:51 -0300460
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300461 dprintk(1, "%s(%u)\n", __func__, freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300462
Steven Tothe12671c2007-12-20 01:14:43 -0300463 if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
464 (freq_hz < xc5000_tuner_ops.info.frequency_min))
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300465 return -EINVAL;
Steven Tothaacb9d32007-12-18 01:55:51 -0300466
Steven Tothe12671c2007-12-20 01:14:43 -0300467 freq_code = (u16)(freq_hz / 15625);
468
Devin Heitmueller81c4dfe2009-04-02 22:40:29 -0300469 /* Starting in firmware version 1.1.44, Xceive recommends using the
470 FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
471 only be used for fast scanning for channel lock) */
472 return xc_write_reg(priv, XREG_FINERFREQ, freq_code);
Steven Tothaacb9d32007-12-18 01:55:51 -0300473}
474
Steven Tothe12671c2007-12-20 01:14:43 -0300475
476static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300477{
Steven Tothe12671c2007-12-20 01:14:43 -0300478 u32 freq_code = (freq_khz * 1024)/1000;
479 dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300480 __func__, freq_khz, freq_code);
Steven Tothe12671c2007-12-20 01:14:43 -0300481
482 return xc_write_reg(priv, XREG_IF_OUT, freq_code);
Steven Tothaacb9d32007-12-18 01:55:51 -0300483}
484
Steven Tothe12671c2007-12-20 01:14:43 -0300485
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300486static int xc_get_adc_envelope(struct xc5000_priv *priv, u16 *adc_envelope)
Steven Tothaacb9d32007-12-18 01:55:51 -0300487{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300488 return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope);
Steven Tothaacb9d32007-12-18 01:55:51 -0300489}
490
Steven Tothe12671c2007-12-20 01:14:43 -0300491static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300492{
493 int result;
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300494 u16 reg_data;
Steven Tothaacb9d32007-12-18 01:55:51 -0300495 u32 tmp;
496
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300497 result = xc5000_readreg(priv, XREG_FREQ_ERROR, &reg_data);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300498 if (result != 0)
Steven Tothaacb9d32007-12-18 01:55:51 -0300499 return result;
500
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300501 tmp = (u32)reg_data;
Steven Tothe12671c2007-12-20 01:14:43 -0300502 (*freq_error_hz) = (tmp * 15625) / 1000;
Steven Tothaacb9d32007-12-18 01:55:51 -0300503 return result;
504}
505
Steven Tothe12671c2007-12-20 01:14:43 -0300506static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
Steven Tothaacb9d32007-12-18 01:55:51 -0300507{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300508 return xc5000_readreg(priv, XREG_LOCK, lock_status);
Steven Tothaacb9d32007-12-18 01:55:51 -0300509}
510
Steven Tothe12671c2007-12-20 01:14:43 -0300511static int xc_get_version(struct xc5000_priv *priv,
512 u8 *hw_majorversion, u8 *hw_minorversion,
513 u8 *fw_majorversion, u8 *fw_minorversion)
Steven Tothaacb9d32007-12-18 01:55:51 -0300514{
Steven Tothe12671c2007-12-20 01:14:43 -0300515 u16 data;
Steven Tothaacb9d32007-12-18 01:55:51 -0300516 int result;
517
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300518 result = xc5000_readreg(priv, XREG_VERSION, &data);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300519 if (result != 0)
Steven Tothaacb9d32007-12-18 01:55:51 -0300520 return result;
521
Steven Tothe12671c2007-12-20 01:14:43 -0300522 (*hw_majorversion) = (data >> 12) & 0x0F;
523 (*hw_minorversion) = (data >> 8) & 0x0F;
524 (*fw_majorversion) = (data >> 4) & 0x0F;
525 (*fw_minorversion) = data & 0x0F;
Steven Tothaacb9d32007-12-18 01:55:51 -0300526
527 return 0;
528}
529
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300530static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev)
531{
532 return xc5000_readreg(priv, XREG_BUILD, buildrev);
533}
534
Steven Tothe12671c2007-12-20 01:14:43 -0300535static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
Steven Tothaacb9d32007-12-18 01:55:51 -0300536{
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300537 u16 reg_data;
Steven Tothaacb9d32007-12-18 01:55:51 -0300538 int result;
539
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300540 result = xc5000_readreg(priv, XREG_HSYNC_FREQ, &reg_data);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300541 if (result != 0)
Steven Tothaacb9d32007-12-18 01:55:51 -0300542 return result;
543
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300544 (*hsync_freq_hz) = ((reg_data & 0x0fff) * 763)/100;
Steven Tothaacb9d32007-12-18 01:55:51 -0300545 return result;
546}
547
Steven Tothe12671c2007-12-20 01:14:43 -0300548static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
Steven Tothaacb9d32007-12-18 01:55:51 -0300549{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300550 return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines);
Steven Tothaacb9d32007-12-18 01:55:51 -0300551}
552
Steven Tothe12671c2007-12-20 01:14:43 -0300553static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
Steven Tothaacb9d32007-12-18 01:55:51 -0300554{
Devin Heitmuellerbdd33562008-11-16 20:17:14 -0300555 return xc5000_readreg(priv, XREG_QUALITY, quality);
Steven Tothaacb9d32007-12-18 01:55:51 -0300556}
557
Devin Heitmueller7c287f12012-08-06 22:46:56 -0300558static int xc_get_analogsnr(struct xc5000_priv *priv, u16 *snr)
559{
560 return xc5000_readreg(priv, XREG_SNR, snr);
561}
562
563static int xc_get_totalgain(struct xc5000_priv *priv, u16 *totalgain)
564{
565 return xc5000_readreg(priv, XREG_TOTALGAIN, totalgain);
566}
567
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300568static u16 wait_for_lock(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300569{
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300570 u16 lock_state = 0;
571 int watch_dog_count = 40;
Steven Tothe12671c2007-12-20 01:14:43 -0300572
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300573 while ((lock_state == 0) && (watch_dog_count > 0)) {
574 xc_get_lock_status(priv, &lock_state);
575 if (lock_state != 1) {
Mauro Carvalho Chehabe5bf4a12014-05-21 13:15:17 -0300576 msleep(5);
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300577 watch_dog_count--;
Steven Tothaacb9d32007-12-18 01:55:51 -0300578 }
579 }
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300580 return lock_state;
Steven Tothaacb9d32007-12-18 01:55:51 -0300581}
582
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300583#define XC_TUNE_ANALOG 0
584#define XC_TUNE_DIGITAL 1
585static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
Steven Tothaacb9d32007-12-18 01:55:51 -0300586{
587 int found = 0;
588
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300589 dprintk(1, "%s(%u)\n", __func__, freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300590
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300591 if (xc_set_rf_frequency(priv, freq_hz) != 0)
Steven Tothaacb9d32007-12-18 01:55:51 -0300592 return 0;
593
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300594 if (mode == XC_TUNE_ANALOG) {
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300595 if (wait_for_lock(priv) == 1)
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300596 found = 1;
597 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300598
599 return found;
600}
601
Michael Krufky7d3d0d82012-04-16 14:59:32 -0300602static int xc_set_xtal(struct dvb_frontend *fe)
603{
604 struct xc5000_priv *priv = fe->tuner_priv;
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300605 int ret = 0;
Michael Krufky7d3d0d82012-04-16 14:59:32 -0300606
607 switch (priv->chip_id) {
608 default:
609 case XC5000A:
610 /* 32.000 MHz xtal is default */
611 break;
612 case XC5000C:
613 switch (priv->xtal_khz) {
614 default:
615 case 32000:
616 /* 32.000 MHz xtal is default */
617 break;
618 case 31875:
619 /* 31.875 MHz xtal configuration */
620 ret = xc_write_reg(priv, 0x000f, 0x8081);
621 break;
622 }
623 break;
624 }
625 return ret;
626}
Steven Tothaacb9d32007-12-18 01:55:51 -0300627
Steven Toth8f3cd532008-10-16 20:29:38 -0300628static int xc5000_fwupload(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300629{
630 struct xc5000_priv *priv = fe->tuner_priv;
631 const struct firmware *fw;
632 int ret;
Michael Krufkya3db60b2012-02-08 15:03:07 -0300633 const struct xc5000_fw_cfg *desired_fw =
634 xc5000_assign_firmware(priv->chip_id);
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300635 priv->pll_register_no = desired_fw->pll_reg;
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -0300636 priv->init_status_supported = desired_fw->init_status_supported;
637 priv->fw_checksum_supported = desired_fw->fw_checksum_supported;
Steven Tothaacb9d32007-12-18 01:55:51 -0300638
Steven Tothe12671c2007-12-20 01:14:43 -0300639 /* request the firmware, this will block and timeout */
640 printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
Michael Krufky6fab81d2012-02-08 14:57:39 -0300641 desired_fw->name);
Steven Tothe12671c2007-12-20 01:14:43 -0300642
Michael Krufky6fab81d2012-02-08 14:57:39 -0300643 ret = request_firmware(&fw, desired_fw->name,
Jean Delvaree9785252009-04-26 05:43:59 -0300644 priv->i2c_props.adap->dev.parent);
Steven Tothaacb9d32007-12-18 01:55:51 -0300645 if (ret) {
646 printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
Steven Toth5ea60532008-01-24 22:29:46 -0300647 goto out;
Steven Tothaacb9d32007-12-18 01:55:51 -0300648 } else {
Devin Heitmueller34a0db92009-04-02 22:45:17 -0300649 printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n",
Michael Krufky3f514512007-12-21 16:20:23 -0300650 fw->size);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300651 ret = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -0300652 }
653
Michael Krufky6fab81d2012-02-08 14:57:39 -0300654 if (fw->size != desired_fw->size) {
Steven Tothaacb9d32007-12-18 01:55:51 -0300655 printk(KERN_ERR "xc5000: firmware incorrect size\n");
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300656 ret = -EINVAL;
Steven Tothaacb9d32007-12-18 01:55:51 -0300657 } else {
Devin Heitmueller34a0db92009-04-02 22:45:17 -0300658 printk(KERN_INFO "xc5000: firmware uploading...\n");
Steven Toth8f3cd532008-10-16 20:29:38 -0300659 ret = xc_load_i2c_sequence(fe, fw->data);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300660 if (0 == ret)
Michael Krufky7d3d0d82012-04-16 14:59:32 -0300661 ret = xc_set_xtal(fe);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300662 if (0 == ret)
Michael Krufky35320672012-04-16 15:06:45 -0300663 printk(KERN_INFO "xc5000: firmware upload complete...\n");
664 else
665 printk(KERN_ERR "xc5000: firmware upload failed...\n");
Steven Tothaacb9d32007-12-18 01:55:51 -0300666 }
667
Steven Toth5ea60532008-01-24 22:29:46 -0300668out:
Steven Tothaacb9d32007-12-18 01:55:51 -0300669 release_firmware(fw);
670 return ret;
671}
672
Steven Tothe12671c2007-12-20 01:14:43 -0300673static void xc_debug_dump(struct xc5000_priv *priv)
Steven Tothaacb9d32007-12-18 01:55:51 -0300674{
Steven Tothe12671c2007-12-20 01:14:43 -0300675 u16 adc_envelope;
676 u32 freq_error_hz = 0;
677 u16 lock_status;
678 u32 hsync_freq_hz = 0;
679 u16 frame_lines;
680 u16 quality;
Devin Heitmueller7c287f12012-08-06 22:46:56 -0300681 u16 snr;
682 u16 totalgain;
Steven Tothe12671c2007-12-20 01:14:43 -0300683 u8 hw_majorversion = 0, hw_minorversion = 0;
684 u8 fw_majorversion = 0, fw_minorversion = 0;
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300685 u16 fw_buildversion = 0;
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300686 u16 regval;
Steven Tothaacb9d32007-12-18 01:55:51 -0300687
688 /* Wait for stats to stabilize.
689 * Frame Lines needs two frame times after initial lock
690 * before it is valid.
691 */
Mauro Carvalho Chehabe5bf4a12014-05-21 13:15:17 -0300692 msleep(100);
Steven Tothaacb9d32007-12-18 01:55:51 -0300693
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300694 xc_get_adc_envelope(priv, &adc_envelope);
Steven Tothe12671c2007-12-20 01:14:43 -0300695 dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
Steven Tothaacb9d32007-12-18 01:55:51 -0300696
Steven Tothe12671c2007-12-20 01:14:43 -0300697 xc_get_frequency_error(priv, &freq_error_hz);
698 dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300699
Steven Tothe12671c2007-12-20 01:14:43 -0300700 xc_get_lock_status(priv, &lock_status);
701 dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
Steven Tothaacb9d32007-12-18 01:55:51 -0300702 lock_status);
703
704 xc_get_version(priv, &hw_majorversion, &hw_minorversion,
Steven Tothe12671c2007-12-20 01:14:43 -0300705 &fw_majorversion, &fw_minorversion);
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300706 xc_get_buildversion(priv, &fw_buildversion);
Devin Heitmuellerca60a45d2012-08-06 22:47:11 -0300707 dprintk(1, "*** HW: V%d.%d, FW: V %d.%d.%d\n",
Steven Tothaacb9d32007-12-18 01:55:51 -0300708 hw_majorversion, hw_minorversion,
Devin Heitmuellerbae7b7d2009-04-02 22:24:38 -0300709 fw_majorversion, fw_minorversion, fw_buildversion);
Steven Tothaacb9d32007-12-18 01:55:51 -0300710
Steven Tothe12671c2007-12-20 01:14:43 -0300711 xc_get_hsync_freq(priv, &hsync_freq_hz);
712 dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300713
Steven Tothe12671c2007-12-20 01:14:43 -0300714 xc_get_frame_lines(priv, &frame_lines);
715 dprintk(1, "*** Frame lines = %d\n", frame_lines);
Steven Tothaacb9d32007-12-18 01:55:51 -0300716
Steven Tothe12671c2007-12-20 01:14:43 -0300717 xc_get_quality(priv, &quality);
Devin Heitmueller1aa9c4872012-08-06 22:46:55 -0300718 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality & 0x07);
Devin Heitmueller7c287f12012-08-06 22:46:56 -0300719
720 xc_get_analogsnr(priv, &snr);
721 dprintk(1, "*** Unweighted analog SNR = %d dB\n", snr & 0x3f);
722
723 xc_get_totalgain(priv, &totalgain);
724 dprintk(1, "*** Total gain = %d.%d dB\n", totalgain / 256,
725 (totalgain % 256) * 100 / 256);
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300726
727 if (priv->pll_register_no) {
728 xc5000_readreg(priv, priv->pll_register_no, &regval);
729 dprintk(1, "*** PLL lock status = 0x%04x\n", regval);
730 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300731}
732
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -0300733static int xc5000_set_params(struct dvb_frontend *fe)
Steven Tothaacb9d32007-12-18 01:55:51 -0300734{
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300735 int ret, b;
Steven Tothaacb9d32007-12-18 01:55:51 -0300736 struct xc5000_priv *priv = fe->tuner_priv;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300737 u32 bw = fe->dtv_property_cache.bandwidth_hz;
738 u32 freq = fe->dtv_property_cache.frequency;
739 u32 delsys = fe->dtv_property_cache.delivery_system;
Steven Tothaacb9d32007-12-18 01:55:51 -0300740
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300741 if (xc_load_fw_and_init_tuner(fe, 0) != 0) {
Devin Heitmuellerfc7a74b2012-08-06 22:47:01 -0300742 dprintk(1, "Unable to load firmware and init tuner\n");
743 return -EINVAL;
Devin Heitmueller760c4662009-10-13 23:44:14 -0300744 }
Devin Heitmueller8e4c6792008-11-16 20:41:07 -0300745
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300746 dprintk(1, "%s() frequency=%d (Hz)\n", __func__, freq);
Steven Tothaacb9d32007-12-18 01:55:51 -0300747
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300748 switch (delsys) {
749 case SYS_ATSC:
750 dprintk(1, "%s() VSB modulation\n", __func__);
751 priv->rf_mode = XC_RF_MODE_AIR;
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -0300752 priv->freq_offset = 1750000;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300753 priv->video_standard = DTV6;
754 break;
755 case SYS_DVBC_ANNEX_B:
756 dprintk(1, "%s() QAM modulation\n", __func__);
757 priv->rf_mode = XC_RF_MODE_CABLE;
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -0300758 priv->freq_offset = 1750000;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300759 priv->video_standard = DTV6;
760 break;
Mauro Carvalho Chehab5cf73ce2012-07-05 14:07:59 -0300761 case SYS_ISDBT:
762 /* All ISDB-T are currently for 6 MHz bw */
763 if (!bw)
764 bw = 6000000;
765 /* fall to OFDM handling */
766 case SYS_DMBTH:
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300767 case SYS_DVBT:
768 case SYS_DVBT2:
David T.L. Wong6c990802009-05-04 22:59:58 -0300769 dprintk(1, "%s() OFDM\n", __func__);
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300770 switch (bw) {
771 case 6000000:
David T.L. Wong6c990802009-05-04 22:59:58 -0300772 priv->video_standard = DTV6;
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -0300773 priv->freq_offset = 1750000;
David T.L. Wong6c990802009-05-04 22:59:58 -0300774 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300775 case 7000000:
Mauro Carvalho Chehab0433cd22011-12-09 08:01:01 -0200776 priv->video_standard = DTV7;
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -0300777 priv->freq_offset = 2250000;
Mauro Carvalho Chehab0433cd22011-12-09 08:01:01 -0200778 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300779 case 8000000:
David T.L. Wong6c990802009-05-04 22:59:58 -0300780 priv->video_standard = DTV8;
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -0300781 priv->freq_offset = 2750000;
David T.L. Wong6c990802009-05-04 22:59:58 -0300782 break;
783 default:
784 printk(KERN_ERR "xc5000 bandwidth not set!\n");
785 return -EINVAL;
786 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300787 priv->rf_mode = XC_RF_MODE_AIR;
Dan Carpentercf1364b2013-01-13 15:31:33 -0300788 break;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300789 case SYS_DVBC_ANNEX_A:
790 case SYS_DVBC_ANNEX_C:
791 dprintk(1, "%s() QAM modulation\n", __func__);
792 priv->rf_mode = XC_RF_MODE_CABLE;
793 if (bw <= 6000000) {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300794 priv->video_standard = DTV6;
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -0300795 priv->freq_offset = 1750000;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300796 b = 6;
797 } else if (bw <= 7000000) {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300798 priv->video_standard = DTV7;
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -0300799 priv->freq_offset = 2250000;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300800 b = 7;
801 } else {
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300802 priv->video_standard = DTV7_8;
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -0300803 priv->freq_offset = 2750000;
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300804 b = 8;
Igor M. Liplianine80edce2011-01-25 17:03:00 -0300805 }
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300806 dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__,
807 b, bw);
808 break;
809 default:
810 printk(KERN_ERR "xc5000: delivery system is not supported!\n");
Steven Tothaacb9d32007-12-18 01:55:51 -0300811 return -EINVAL;
812 }
813
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -0300814 priv->freq_hz = freq - priv->freq_offset;
815
Mauro Carvalho Chehabfd66c452011-12-17 20:36:57 -0300816 dprintk(1, "%s() frequency=%d (compensated to %d)\n",
817 __func__, freq, priv->freq_hz);
Steven Tothaacb9d32007-12-18 01:55:51 -0300818
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300819 ret = xc_set_signal_source(priv, priv->rf_mode);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300820 if (ret != 0) {
Steven Tothe12671c2007-12-20 01:14:43 -0300821 printk(KERN_ERR
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300822 "xc5000: xc_set_signal_source(%d) failed\n",
Steven Tothe12671c2007-12-20 01:14:43 -0300823 priv->rf_mode);
824 return -EREMOTEIO;
825 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300826
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300827 ret = xc_set_tv_standard(priv,
828 xc5000_standard[priv->video_standard].video_mode,
829 xc5000_standard[priv->video_standard].audio_mode, 0);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300830 if (ret != 0) {
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300831 printk(KERN_ERR "xc5000: xc_set_tv_standard failed\n");
Steven Tothe12671c2007-12-20 01:14:43 -0300832 return -EREMOTEIO;
833 }
Steven Tothaacb9d32007-12-18 01:55:51 -0300834
Michael Krufky2a6003c2008-09-06 13:54:45 -0300835 ret = xc_set_IF_frequency(priv, priv->if_khz);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300836 if (ret != 0) {
Steven Tothe12671c2007-12-20 01:14:43 -0300837 printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
Michael Krufky2a6003c2008-09-06 13:54:45 -0300838 priv->if_khz);
Steven Tothe12671c2007-12-20 01:14:43 -0300839 return -EIO;
840 }
841
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300842 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a);
843
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300844 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
Steven Tothe12671c2007-12-20 01:14:43 -0300845
846 if (debug)
847 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -0300848
Mauro Carvalho Chehabc6f56e72011-12-26 20:02:28 -0300849 priv->bandwidth = bw;
850
Steven Tothaacb9d32007-12-18 01:55:51 -0300851 return 0;
852}
853
Steven Tothe470d812008-06-21 21:06:02 -0300854static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
855{
856 struct xc5000_priv *priv = fe->tuner_priv;
857 int ret;
858 u16 id;
859
860 ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300861 if (ret == 0) {
Steven Tothe470d812008-06-21 21:06:02 -0300862 if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300863 ret = -ENOENT;
Steven Tothe470d812008-06-21 21:06:02 -0300864 else
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300865 ret = 0;
Steven Tothe470d812008-06-21 21:06:02 -0300866 }
867
868 dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300869 ret == 0 ? "True" : "False", id);
Steven Tothe470d812008-06-21 21:06:02 -0300870 return ret;
871}
872
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300873static int xc5000_set_tv_freq(struct dvb_frontend *fe,
Steven Toth27c685a2008-01-05 16:50:14 -0300874 struct analog_parameters *params)
875{
876 struct xc5000_priv *priv = fe->tuner_priv;
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300877 u16 pll_lock_status;
Steven Toth27c685a2008-01-05 16:50:14 -0300878 int ret;
879
Steven Toth27c685a2008-01-05 16:50:14 -0300880 dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
Harvey Harrison271ddbf2008-04-08 23:20:00 -0300881 __func__, params->frequency);
Steven Toth27c685a2008-01-05 16:50:14 -0300882
Mauro Carvalho Chehab1fab14e2009-03-03 14:35:41 -0300883 /* Fix me: it could be air. */
884 priv->rf_mode = params->mode;
885 if (params->mode > XC_RF_MODE_CABLE)
886 priv->rf_mode = XC_RF_MODE_CABLE;
Steven Toth27c685a2008-01-05 16:50:14 -0300887
888 /* params->frequency is in units of 62.5khz */
889 priv->freq_hz = params->frequency * 62500;
890
891 /* FIX ME: Some video standards may have several possible audio
892 standards. We simply default to one of them here.
893 */
Steven Toth8f3cd532008-10-16 20:29:38 -0300894 if (params->std & V4L2_STD_MN) {
Steven Toth27c685a2008-01-05 16:50:14 -0300895 /* default to BTSC audio standard */
896 priv->video_standard = MN_NTSC_PAL_BTSC;
897 goto tune_channel;
898 }
899
Steven Toth8f3cd532008-10-16 20:29:38 -0300900 if (params->std & V4L2_STD_PAL_BG) {
Steven Toth27c685a2008-01-05 16:50:14 -0300901 /* default to NICAM audio standard */
902 priv->video_standard = BG_PAL_NICAM;
903 goto tune_channel;
904 }
905
Steven Toth8f3cd532008-10-16 20:29:38 -0300906 if (params->std & V4L2_STD_PAL_I) {
Steven Toth27c685a2008-01-05 16:50:14 -0300907 /* default to NICAM audio standard */
908 priv->video_standard = I_PAL_NICAM;
909 goto tune_channel;
910 }
911
Steven Toth8f3cd532008-10-16 20:29:38 -0300912 if (params->std & V4L2_STD_PAL_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300913 /* default to NICAM audio standard */
914 priv->video_standard = DK_PAL_NICAM;
915 goto tune_channel;
916 }
917
Steven Toth8f3cd532008-10-16 20:29:38 -0300918 if (params->std & V4L2_STD_SECAM_DK) {
Steven Toth27c685a2008-01-05 16:50:14 -0300919 /* default to A2 DK1 audio standard */
920 priv->video_standard = DK_SECAM_A2DK1;
921 goto tune_channel;
922 }
923
Steven Toth8f3cd532008-10-16 20:29:38 -0300924 if (params->std & V4L2_STD_SECAM_L) {
Steven Toth27c685a2008-01-05 16:50:14 -0300925 priv->video_standard = L_SECAM_NICAM;
926 goto tune_channel;
927 }
928
Steven Toth8f3cd532008-10-16 20:29:38 -0300929 if (params->std & V4L2_STD_SECAM_LC) {
Steven Toth27c685a2008-01-05 16:50:14 -0300930 priv->video_standard = LC_SECAM_NICAM;
931 goto tune_channel;
932 }
933
934tune_channel:
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300935 ret = xc_set_signal_source(priv, priv->rf_mode);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300936 if (ret != 0) {
Steven Toth8f3cd532008-10-16 20:29:38 -0300937 printk(KERN_ERR
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300938 "xc5000: xc_set_signal_source(%d) failed\n",
Steven Toth27c685a2008-01-05 16:50:14 -0300939 priv->rf_mode);
940 return -EREMOTEIO;
941 }
942
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300943 ret = xc_set_tv_standard(priv,
944 xc5000_standard[priv->video_standard].video_mode,
945 xc5000_standard[priv->video_standard].audio_mode, 0);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300946 if (ret != 0) {
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300947 printk(KERN_ERR "xc5000: xc_set_tv_standard failed\n");
Steven Toth27c685a2008-01-05 16:50:14 -0300948 return -EREMOTEIO;
949 }
950
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300951 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
952
Devin Heitmuellera78baac2008-11-16 20:48:31 -0300953 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
Steven Toth27c685a2008-01-05 16:50:14 -0300954
955 if (debug)
956 xc_debug_dump(priv);
957
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300958 if (priv->pll_register_no != 0) {
959 msleep(20);
960 xc5000_readreg(priv, priv->pll_register_no, &pll_lock_status);
961 if (pll_lock_status > 63) {
962 /* PLL is unlocked, force reload of the firmware */
963 dprintk(1, "xc5000: PLL not locked (0x%x). Reloading...\n",
964 pll_lock_status);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -0300965 if (xc_load_fw_and_init_tuner(fe, 1) != 0) {
Devin Heitmuellerde49bc62012-08-06 22:47:08 -0300966 printk(KERN_ERR "xc5000: Unable to reload fw\n");
967 return -EREMOTEIO;
968 }
969 goto tune_channel;
970 }
971 }
972
Steven Toth27c685a2008-01-05 16:50:14 -0300973 return 0;
974}
975
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300976static int xc5000_set_radio_freq(struct dvb_frontend *fe,
977 struct analog_parameters *params)
978{
979 struct xc5000_priv *priv = fe->tuner_priv;
980 int ret = -EINVAL;
Devin Heitmueller496e9052009-09-24 13:27:24 -0300981 u8 radio_input;
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -0300982
983 dprintk(1, "%s() frequency=%d (in units of khz)\n",
984 __func__, params->frequency);
985
Devin Heitmueller496e9052009-09-24 13:27:24 -0300986 if (priv->radio_input == XC5000_RADIO_NOT_CONFIGURED) {
987 dprintk(1, "%s() radio input not configured\n", __func__);
988 return -EINVAL;
989 }
990
991 if (priv->radio_input == XC5000_RADIO_FM1)
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300992 radio_input = FM_RADIO_INPUT1;
Devin Heitmueller496e9052009-09-24 13:27:24 -0300993 else if (priv->radio_input == XC5000_RADIO_FM2)
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300994 radio_input = FM_RADIO_INPUT2;
Dmitri Belimov724dcbf2011-02-01 05:25:19 -0300995 else if (priv->radio_input == XC5000_RADIO_FM1_MONO)
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -0300996 radio_input = FM_RADIO_INPUT1_MONO;
Devin Heitmueller496e9052009-09-24 13:27:24 -0300997 else {
998 dprintk(1, "%s() unknown radio input %d\n", __func__,
999 priv->radio_input);
1000 return -EINVAL;
1001 }
1002
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -03001003 priv->freq_hz = params->frequency * 125 / 2;
1004
1005 priv->rf_mode = XC_RF_MODE_AIR;
1006
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -03001007 ret = xc_set_tv_standard(priv, xc5000_standard[radio_input].video_mode,
1008 xc5000_standard[radio_input].audio_mode, radio_input);
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -03001009
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001010 if (ret != 0) {
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -03001011 printk(KERN_ERR "xc5000: xc_set_tv_standard failed\n");
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -03001012 return -EREMOTEIO;
1013 }
1014
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -03001015 ret = xc_set_signal_source(priv, priv->rf_mode);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001016 if (ret != 0) {
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -03001017 printk(KERN_ERR
Mauro Carvalho Chehab303ddd92014-05-21 13:23:27 -03001018 "xc5000: xc_set_signal_source(%d) failed\n",
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -03001019 priv->rf_mode);
1020 return -EREMOTEIO;
1021 }
1022
Dmitri Belimov724dcbf2011-02-01 05:25:19 -03001023 if ((priv->radio_input == XC5000_RADIO_FM1) ||
1024 (priv->radio_input == XC5000_RADIO_FM2))
1025 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
1026 else if (priv->radio_input == XC5000_RADIO_FM1_MONO)
1027 xc_write_reg(priv, XREG_OUTPUT_AMP, 0x06);
1028
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -03001029 xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
1030
1031 return 0;
1032}
1033
1034static int xc5000_set_analog_params(struct dvb_frontend *fe,
1035 struct analog_parameters *params)
1036{
1037 struct xc5000_priv *priv = fe->tuner_priv;
1038 int ret = -EINVAL;
1039
1040 if (priv->i2c_props.adap == NULL)
1041 return -EINVAL;
1042
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001043 if (xc_load_fw_and_init_tuner(fe, 0) != 0) {
Devin Heitmuellerfc7a74b2012-08-06 22:47:01 -03001044 dprintk(1, "Unable to load firmware and init tuner\n");
1045 return -EINVAL;
Devin Heitmueller760c4662009-10-13 23:44:14 -03001046 }
Beholder Intl. Ltd. Dmitry Belimovd7009cd2009-09-24 13:13:28 -03001047
1048 switch (params->mode) {
1049 case V4L2_TUNER_RADIO:
1050 ret = xc5000_set_radio_freq(fe, params);
1051 break;
1052 case V4L2_TUNER_ANALOG_TV:
1053 case V4L2_TUNER_DIGITAL_TV:
1054 ret = xc5000_set_tv_freq(fe, params);
1055 break;
1056 }
1057
1058 return ret;
1059}
1060
1061
Steven Tothaacb9d32007-12-18 01:55:51 -03001062static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
1063{
1064 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001065 dprintk(1, "%s()\n", __func__);
Mauro Carvalho Chehaba3eec912014-07-21 14:21:18 -03001066 *freq = priv->freq_hz + priv->freq_offset;
Steven Tothaacb9d32007-12-18 01:55:51 -03001067 return 0;
1068}
1069
Mauro Carvalho Chehab35621032011-09-23 13:03:42 -03001070static int xc5000_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
1071{
1072 struct xc5000_priv *priv = fe->tuner_priv;
1073 dprintk(1, "%s()\n", __func__);
1074 *freq = priv->if_khz * 1000;
1075 return 0;
1076}
1077
Steven Tothaacb9d32007-12-18 01:55:51 -03001078static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
1079{
1080 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001081 dprintk(1, "%s()\n", __func__);
Steven Toth27c685a2008-01-05 16:50:14 -03001082
Steven Tothaacb9d32007-12-18 01:55:51 -03001083 *bw = priv->bandwidth;
1084 return 0;
1085}
1086
1087static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
1088{
1089 struct xc5000_priv *priv = fe->tuner_priv;
Steven Tothe12671c2007-12-20 01:14:43 -03001090 u16 lock_status = 0;
Steven Tothaacb9d32007-12-18 01:55:51 -03001091
1092 xc_get_lock_status(priv, &lock_status);
1093
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001094 dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
Steven Tothaacb9d32007-12-18 01:55:51 -03001095
1096 *status = lock_status;
1097
1098 return 0;
1099}
1100
Devin Heitmuellerde49bc62012-08-06 22:47:08 -03001101static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force)
Steven Tothaacb9d32007-12-18 01:55:51 -03001102{
1103 struct xc5000_priv *priv = fe->tuner_priv;
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001104 int ret = 0;
Devin Heitmuellerde49bc62012-08-06 22:47:08 -03001105 u16 pll_lock_status;
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -03001106 u16 fw_ck;
Steven Tothaacb9d32007-12-18 01:55:51 -03001107
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -03001108 cancel_delayed_work(&priv->timer_sleep);
1109
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001110 if (force || xc5000_is_firmware_loaded(fe) != 0) {
Devin Heitmuellerde49bc62012-08-06 22:47:08 -03001111
1112fw_retry:
1113
Steven Tothaacb9d32007-12-18 01:55:51 -03001114 ret = xc5000_fwupload(fe);
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001115 if (ret != 0)
Steven Tothe12671c2007-12-20 01:14:43 -03001116 return ret;
Devin Heitmuellerfc7a74b2012-08-06 22:47:01 -03001117
Devin Heitmuellerde49bc62012-08-06 22:47:08 -03001118 msleep(20);
1119
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -03001120 if (priv->fw_checksum_supported) {
1121 if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001122 != 0) {
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -03001123 dprintk(1, "%s() FW checksum reading failed.\n",
1124 __func__);
1125 goto fw_retry;
1126 }
1127
1128 if (fw_ck == 0) {
1129 dprintk(1, "%s() FW checksum failed = 0x%04x\n",
1130 __func__, fw_ck);
1131 goto fw_retry;
1132 }
1133 }
1134
Devin Heitmuellerfc7a74b2012-08-06 22:47:01 -03001135 /* Start the tuner self-calibration process */
1136 ret |= xc_initialize(priv);
1137
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001138 if (ret != 0)
Devin Heitmuellerde49bc62012-08-06 22:47:08 -03001139 goto fw_retry;
1140
Devin Heitmuellerfc7a74b2012-08-06 22:47:01 -03001141 /* Wait for calibration to complete.
1142 * We could continue but XC5000 will clock stretch subsequent
1143 * I2C transactions until calibration is complete. This way we
1144 * don't have to rely on clock stretching working.
1145 */
Mauro Carvalho Chehabe5bf4a12014-05-21 13:15:17 -03001146 msleep(100);
Devin Heitmuellerfc7a74b2012-08-06 22:47:01 -03001147
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -03001148 if (priv->init_status_supported) {
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001149 if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != 0) {
Devin Heitmueller22d5c6f2012-08-06 22:47:09 -03001150 dprintk(1, "%s() FW failed reading init status.\n",
1151 __func__);
1152 goto fw_retry;
1153 }
1154
1155 if (fw_ck == 0) {
1156 dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck);
1157 goto fw_retry;
1158 }
1159 }
1160
Devin Heitmuellerde49bc62012-08-06 22:47:08 -03001161 if (priv->pll_register_no) {
1162 xc5000_readreg(priv, priv->pll_register_no,
1163 &pll_lock_status);
1164 if (pll_lock_status > 63) {
1165 /* PLL is unlocked, force reload of the firmware */
1166 printk(KERN_ERR "xc5000: PLL not running after fwload.\n");
1167 goto fw_retry;
1168 }
1169 }
1170
Devin Heitmuellerfc7a74b2012-08-06 22:47:01 -03001171 /* Default to "CABLE" mode */
1172 ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
Steven Tothaacb9d32007-12-18 01:55:51 -03001173 }
1174
Steven Tothaacb9d32007-12-18 01:55:51 -03001175 return ret;
1176}
1177
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -03001178static void xc5000_do_timer_sleep(struct work_struct *timer_sleep)
1179{
1180 struct xc5000_priv *priv =container_of(timer_sleep, struct xc5000_priv,
1181 timer_sleep.work);
1182 struct dvb_frontend *fe = priv->fe;
1183 int ret;
1184
1185 dprintk(1, "%s()\n", __func__);
1186
1187 /* According to Xceive technical support, the "powerdown" register
1188 was removed in newer versions of the firmware. The "supported"
1189 way to sleep the tuner is to pull the reset pin low for 10ms */
1190 ret = xc5000_tuner_reset(fe);
1191 if (ret != 0)
1192 printk(KERN_ERR
1193 "xc5000: %s() unable to shutdown tuner\n",
1194 __func__);
1195}
1196
Steven Tothe12671c2007-12-20 01:14:43 -03001197static int xc5000_sleep(struct dvb_frontend *fe)
1198{
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -03001199 struct xc5000_priv *priv = fe->tuner_priv;
Steven Toth27c685a2008-01-05 16:50:14 -03001200
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001201 dprintk(1, "%s()\n", __func__);
Steven Tothe12671c2007-12-20 01:14:43 -03001202
Devin Heitmuellerb6bd5eb2009-04-28 13:53:38 -03001203 /* Avoid firmware reload on slow devices */
1204 if (no_poweroff)
1205 return 0;
1206
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -03001207 schedule_delayed_work(&priv->timer_sleep,
1208 msecs_to_jiffies(XC5000_SLEEP_TIME));
1209
1210 return 0;
Steven Tothe12671c2007-12-20 01:14:43 -03001211}
1212
Steven Tothaacb9d32007-12-18 01:55:51 -03001213static int xc5000_init(struct dvb_frontend *fe)
1214{
1215 struct xc5000_priv *priv = fe->tuner_priv;
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001216 dprintk(1, "%s()\n", __func__);
Steven Tothaacb9d32007-12-18 01:55:51 -03001217
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001218 if (xc_load_fw_and_init_tuner(fe, 0) != 0) {
Steven Tothe12671c2007-12-20 01:14:43 -03001219 printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
1220 return -EREMOTEIO;
1221 }
1222
1223 if (debug)
1224 xc_debug_dump(priv);
Steven Tothaacb9d32007-12-18 01:55:51 -03001225
1226 return 0;
1227}
1228
1229static int xc5000_release(struct dvb_frontend *fe)
1230{
Michael Krufky89fd2852008-09-06 11:44:53 -03001231 struct xc5000_priv *priv = fe->tuner_priv;
1232
Harvey Harrison271ddbf2008-04-08 23:20:00 -03001233 dprintk(1, "%s()\n", __func__);
Michael Krufky89fd2852008-09-06 11:44:53 -03001234
1235 mutex_lock(&xc5000_list_mutex);
1236
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -03001237 if (priv) {
1238 cancel_delayed_work(&priv->timer_sleep);
Michael Krufky89fd2852008-09-06 11:44:53 -03001239 hybrid_tuner_release_state(priv);
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -03001240 }
Michael Krufky89fd2852008-09-06 11:44:53 -03001241
1242 mutex_unlock(&xc5000_list_mutex);
1243
Steven Tothaacb9d32007-12-18 01:55:51 -03001244 fe->tuner_priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -03001245
Steven Tothaacb9d32007-12-18 01:55:51 -03001246 return 0;
1247}
1248
Dmitri Belimov724dcbf2011-02-01 05:25:19 -03001249static int xc5000_set_config(struct dvb_frontend *fe, void *priv_cfg)
1250{
1251 struct xc5000_priv *priv = fe->tuner_priv;
1252 struct xc5000_config *p = priv_cfg;
1253
1254 dprintk(1, "%s()\n", __func__);
1255
1256 if (p->if_khz)
1257 priv->if_khz = p->if_khz;
1258
1259 if (p->radio_input)
1260 priv->radio_input = p->radio_input;
1261
1262 return 0;
1263}
1264
1265
Steven Tothaacb9d32007-12-18 01:55:51 -03001266static const struct dvb_tuner_ops xc5000_tuner_ops = {
1267 .info = {
1268 .name = "Xceive XC5000",
1269 .frequency_min = 1000000,
1270 .frequency_max = 1023000000,
1271 .frequency_step = 50000,
1272 },
1273
Steven Toth27c685a2008-01-05 16:50:14 -03001274 .release = xc5000_release,
1275 .init = xc5000_init,
1276 .sleep = xc5000_sleep,
Steven Tothaacb9d32007-12-18 01:55:51 -03001277
Dmitri Belimov724dcbf2011-02-01 05:25:19 -03001278 .set_config = xc5000_set_config,
Steven Toth27c685a2008-01-05 16:50:14 -03001279 .set_params = xc5000_set_params,
1280 .set_analog_params = xc5000_set_analog_params,
1281 .get_frequency = xc5000_get_frequency,
Mauro Carvalho Chehab35621032011-09-23 13:03:42 -03001282 .get_if_frequency = xc5000_get_if_frequency,
Steven Toth27c685a2008-01-05 16:50:14 -03001283 .get_bandwidth = xc5000_get_bandwidth,
1284 .get_status = xc5000_get_status
Steven Tothaacb9d32007-12-18 01:55:51 -03001285};
1286
Michael Krufky48723542008-05-10 14:34:09 -03001287struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
1288 struct i2c_adapter *i2c,
lawrence rust2e4e98e2010-08-25 09:50:20 -03001289 const struct xc5000_config *cfg)
Steven Tothaacb9d32007-12-18 01:55:51 -03001290{
1291 struct xc5000_priv *priv = NULL;
Michael Krufky89fd2852008-09-06 11:44:53 -03001292 int instance;
Steven Tothaacb9d32007-12-18 01:55:51 -03001293 u16 id = 0;
1294
Michael Krufky89fd2852008-09-06 11:44:53 -03001295 dprintk(1, "%s(%d-%04x)\n", __func__,
1296 i2c ? i2c_adapter_id(i2c) : -1,
1297 cfg ? cfg->i2c_address : -1);
Steven Tothaacb9d32007-12-18 01:55:51 -03001298
Michael Krufky89fd2852008-09-06 11:44:53 -03001299 mutex_lock(&xc5000_list_mutex);
Steven Tothaacb9d32007-12-18 01:55:51 -03001300
Michael Krufky89fd2852008-09-06 11:44:53 -03001301 instance = hybrid_tuner_request_state(struct xc5000_priv, priv,
1302 hybrid_tuner_instance_list,
1303 i2c, cfg->i2c_address, "xc5000");
1304 switch (instance) {
1305 case 0:
1306 goto fail;
Michael Krufky89fd2852008-09-06 11:44:53 -03001307 case 1:
1308 /* new tuner instance */
Mauro Carvalho Chehabc6f56e72011-12-26 20:02:28 -03001309 priv->bandwidth = 6000000;
Michael Krufky89fd2852008-09-06 11:44:53 -03001310 fe->tuner_priv = priv;
Mauro Carvalho Chehabf7a27ff2014-05-21 13:57:30 -03001311 priv->fe = fe;
1312 INIT_DELAYED_WORK(&priv->timer_sleep, xc5000_do_timer_sleep);
Michael Krufky89fd2852008-09-06 11:44:53 -03001313 break;
1314 default:
1315 /* existing tuner instance */
1316 fe->tuner_priv = priv;
1317 break;
1318 }
Steven Tothaacb9d32007-12-18 01:55:51 -03001319
Devin Heitmuellerea227862009-03-11 02:58:53 -03001320 if (priv->if_khz == 0) {
1321 /* If the IF hasn't been set yet, use the value provided by
1322 the caller (occurs in hybrid devices where the analog
1323 call to xc5000_attach occurs before the digital side) */
1324 priv->if_khz = cfg->if_khz;
1325 }
1326
Michael Krufky7d3d0d82012-04-16 14:59:32 -03001327 if (priv->xtal_khz == 0)
1328 priv->xtal_khz = cfg->xtal_khz;
1329
Devin Heitmueller496e9052009-09-24 13:27:24 -03001330 if (priv->radio_input == 0)
1331 priv->radio_input = cfg->radio_input;
1332
Michael Krufky6fab81d2012-02-08 14:57:39 -03001333 /* don't override chip id if it's already been set
Michael Krufky76efb0ba2012-02-06 19:40:32 -03001334 unless explicitly specified */
Michael Krufky6fab81d2012-02-08 14:57:39 -03001335 if ((priv->chip_id == 0) || (cfg->chip_id))
1336 /* use default chip id if none specified, set to 0 so
1337 it can be overridden if this is a hybrid driver */
1338 priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0;
Michael Krufky76efb0ba2012-02-06 19:40:32 -03001339
Steven Toth27c685a2008-01-05 16:50:14 -03001340 /* Check if firmware has been loaded. It is possible that another
1341 instance of the driver has loaded the firmware.
1342 */
Mauro Carvalho Chehab859ae7f2014-05-21 13:08:18 -03001343 if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
Michael Krufky89fd2852008-09-06 11:44:53 -03001344 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -03001345
Steven Toth8f3cd532008-10-16 20:29:38 -03001346 switch (id) {
Steven Toth27c685a2008-01-05 16:50:14 -03001347 case XC_PRODUCT_ID_FW_LOADED:
1348 printk(KERN_INFO
1349 "xc5000: Successfully identified at address 0x%02x\n",
1350 cfg->i2c_address);
1351 printk(KERN_INFO
1352 "xc5000: Firmware has been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -03001353 break;
1354 case XC_PRODUCT_ID_FW_NOT_LOADED:
1355 printk(KERN_INFO
1356 "xc5000: Successfully identified at address 0x%02x\n",
1357 cfg->i2c_address);
1358 printk(KERN_INFO
1359 "xc5000: Firmware has not been loaded previously\n");
Steven Toth27c685a2008-01-05 16:50:14 -03001360 break;
1361 default:
Steven Tothaacb9d32007-12-18 01:55:51 -03001362 printk(KERN_ERR
1363 "xc5000: Device not found at addr 0x%02x (0x%x)\n",
1364 cfg->i2c_address, id);
Michael Krufky89fd2852008-09-06 11:44:53 -03001365 goto fail;
Steven Tothaacb9d32007-12-18 01:55:51 -03001366 }
1367
Michael Krufky89fd2852008-09-06 11:44:53 -03001368 mutex_unlock(&xc5000_list_mutex);
1369
Steven Tothaacb9d32007-12-18 01:55:51 -03001370 memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
1371 sizeof(struct dvb_tuner_ops));
1372
Steven Tothaacb9d32007-12-18 01:55:51 -03001373 return fe;
Michael Krufky89fd2852008-09-06 11:44:53 -03001374fail:
1375 mutex_unlock(&xc5000_list_mutex);
1376
1377 xc5000_release(fe);
1378 return NULL;
Steven Tothaacb9d32007-12-18 01:55:51 -03001379}
1380EXPORT_SYMBOL(xc5000_attach);
1381
1382MODULE_AUTHOR("Steven Toth");
Steven Tothe12671c2007-12-20 01:14:43 -03001383MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
Steven Tothaacb9d32007-12-18 01:55:51 -03001384MODULE_LICENSE("GPL");
Tim Gardner3422f2a62012-07-25 09:15:19 -03001385MODULE_FIRMWARE(XC5000A_FIRMWARE);
1386MODULE_FIRMWARE(XC5000C_FIRMWARE);