blob: 5c3da21d188e68cb410830924c1ed1b2c439a59d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
3 * i2c tv tuner chip device driver
4 * core core, i.e. kernel interfaces, registering and so on
5 */
6
7#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/string.h>
10#include <linux/timer.h>
11#include <linux/delay.h>
12#include <linux/errno.h>
13#include <linux/slab.h>
14#include <linux/poll.h>
15#include <linux/i2c.h>
16#include <linux/types.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/init.h>
Hans Verkuil75b4c262009-04-01 03:32:22 -030018#include <linux/videodev2.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <media/tuner.h>
Michael Krufky4adad282007-08-27 21:59:08 -030020#include <media/tuner-types.h>
Hans Verkuile8a4a9e2008-11-24 18:21:40 -030021#include <media/v4l2-device.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030022#include <media/v4l2-ioctl.h>
Michael Krufky96c0b7c2007-08-27 21:23:08 -030023#include "mt20xx.h"
Michael Krufky910bb3e2007-08-27 21:22:20 -030024#include "tda8290.h"
Michael Krufky7ab10bf2007-08-27 21:23:40 -030025#include "tea5761.h"
Michael Krufky8d0936e2007-08-27 21:24:27 -030026#include "tea5767.h"
Mauro Carvalho Chehab215b95b2007-10-23 15:24:06 -030027#include "tuner-xc2028.h"
Michael Krufky4adad282007-08-27 21:59:08 -030028#include "tuner-simple.h"
Michael Krufky31c95842007-10-21 20:48:48 -030029#include "tda9887.h"
Steven Toth27c685a2008-01-05 16:50:14 -030030#include "xc5000.h"
Michael Krufky93463892009-09-15 23:04:18 -030031#include "tda18271.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
33#define UNSET (-1U)
34
Hans Verkuil9dd659d2007-11-04 11:03:36 -030035#define PREFIX t->i2c->driver->driver.name
Michael Krufky241020d2007-10-30 09:46:10 -030036
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -030037/*
38 * Driver modprobe parameters
39 */
40
41/* insmod options used at init time => read/only */
42static unsigned int addr;
43static unsigned int no_autodetect;
44static unsigned int show_i2c;
45
46module_param(addr, int, 0444);
47module_param(no_autodetect, int, 0444);
48module_param(show_i2c, int, 0444);
49
50/* insmod options used at runtime => read/write */
51static int tuner_debug;
52static unsigned int tv_range[2] = { 44, 958 };
53static unsigned int radio_range[2] = { 65, 108 };
54static char pal[] = "--";
55static char secam[] = "--";
56static char ntsc[] = "-";
57
58module_param_named(debug,tuner_debug, int, 0644);
59module_param_array(tv_range, int, NULL, 0644);
60module_param_array(radio_range, int, NULL, 0644);
61module_param_string(pal, pal, sizeof(pal), 0644);
62module_param_string(secam, secam, sizeof(secam), 0644);
63module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
64
65/*
66 * Static vars
67 */
68
69static struct xc5000_config xc5000_cfg;
70static LIST_HEAD(tuner_list);
71
72/*
73 * Debug macros
74 */
75
76#define tuner_warn(fmt, arg...) do { \
77 printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \
78 i2c_adapter_id(t->i2c->adapter), \
79 t->i2c->addr, ##arg); \
80 } while (0)
81
82#define tuner_info(fmt, arg...) do { \
83 printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \
84 i2c_adapter_id(t->i2c->adapter), \
85 t->i2c->addr, ##arg); \
86 } while (0)
87
88#define tuner_err(fmt, arg...) do { \
89 printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \
90 i2c_adapter_id(t->i2c->adapter), \
91 t->i2c->addr, ##arg); \
92 } while (0)
93
94#define tuner_dbg(fmt, arg...) do { \
95 if (tuner_debug) \
96 printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \
97 i2c_adapter_id(t->i2c->adapter), \
98 t->i2c->addr, ##arg); \
99 } while (0)
100
101/*
102 * Internal struct used inside the driver
103 */
104
105struct tuner {
106 /* device */
107 struct dvb_frontend fe;
108 struct i2c_client *i2c;
109 struct v4l2_subdev sd;
110 struct list_head list;
111
112 /* keep track of the current settings */
113 v4l2_std_id std;
114 unsigned int tv_freq;
115 unsigned int radio_freq;
116 unsigned int audmode;
117
118 unsigned int mode;
119 unsigned int mode_mask; /* Combination of allowable modes */
120
121 unsigned int type; /* chip type id */
122 unsigned int config;
123 const char *name;
124};
125
126/*
127 * tuner attach/detach logic
128 */
129
Michael Krufkya07c8772008-04-29 03:54:19 -0300130/** This macro allows us to probe dynamically, avoiding static links */
Mauro Carvalho Chehabff138172008-04-29 23:02:33 -0300131#ifdef CONFIG_MEDIA_ATTACH
Michael Krufkya07c8772008-04-29 03:54:19 -0300132#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
133 int __r = -EINVAL; \
134 typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
135 if (__a) { \
136 __r = (int) __a(ARGS); \
Andrew Mortona1355e52008-04-30 11:40:17 -0300137 symbol_put(FUNCTION); \
Michael Krufkya07c8772008-04-29 03:54:19 -0300138 } else { \
139 printk(KERN_ERR "TUNER: Unable to find " \
140 "symbol "#FUNCTION"()\n"); \
141 } \
Michael Krufkya07c8772008-04-29 03:54:19 -0300142 __r; \
143})
144
145static void tuner_detach(struct dvb_frontend *fe)
146{
147 if (fe->ops.tuner_ops.release) {
148 fe->ops.tuner_ops.release(fe);
149 symbol_put_addr(fe->ops.tuner_ops.release);
150 }
151 if (fe->ops.analog_ops.release) {
152 fe->ops.analog_ops.release(fe);
153 symbol_put_addr(fe->ops.analog_ops.release);
154 }
155}
156#else
157#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
158 FUNCTION(ARGS); \
159})
160
161static void tuner_detach(struct dvb_frontend *fe)
162{
163 if (fe->ops.tuner_ops.release)
164 fe->ops.tuner_ops.release(fe);
165 if (fe->ops.analog_ops.release)
166 fe->ops.analog_ops.release(fe);
167}
168#endif
169
Michael Krufkyf7f427e2007-12-16 22:02:26 -0300170
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300171static inline struct tuner *to_tuner(struct v4l2_subdev *sd)
172{
173 return container_of(sd, struct tuner, sd);
174}
175
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300176/*
177 * struct analog_demod_ops callbacks
178 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Michael Krufkyc7919d52007-12-08 17:06:30 -0300180static void fe_set_params(struct dvb_frontend *fe,
181 struct analog_parameters *params)
Michael Krufkye18f9442007-08-21 01:25:48 -0300182{
Michael Krufky4e9154b2007-10-21 19:39:50 -0300183 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
184 struct tuner *t = fe->analog_demod_priv;
Michael Krufkye18f9442007-08-21 01:25:48 -0300185
Michael Krufkye18f9442007-08-21 01:25:48 -0300186 if (NULL == fe_tuner_ops->set_analog_params) {
187 tuner_warn("Tuner frontend module has no way to set freq\n");
188 return;
189 }
Michael Krufkyc7919d52007-12-08 17:06:30 -0300190 fe_tuner_ops->set_analog_params(fe, params);
Michael Krufkye18f9442007-08-21 01:25:48 -0300191}
192
Michael Krufky4e9154b2007-10-21 19:39:50 -0300193static void fe_standby(struct dvb_frontend *fe)
Michael Krufkye18f9442007-08-21 01:25:48 -0300194{
Michael Krufky4e9154b2007-10-21 19:39:50 -0300195 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
Michael Krufkye18f9442007-08-21 01:25:48 -0300196
197 if (fe_tuner_ops->sleep)
Michael Krufky4e9154b2007-10-21 19:39:50 -0300198 fe_tuner_ops->sleep(fe);
Michael Krufkye18f9442007-08-21 01:25:48 -0300199}
200
Michael Krufky4e9154b2007-10-21 19:39:50 -0300201static int fe_has_signal(struct dvb_frontend *fe)
Michael Krufky1f5ef192007-08-31 17:38:02 -0300202{
Michael Krufky14196832007-10-14 18:11:53 -0300203 u16 strength = 0;
Michael Krufky1f5ef192007-08-31 17:38:02 -0300204
Michael Krufky4e9154b2007-10-21 19:39:50 -0300205 if (fe->ops.tuner_ops.get_rf_strength)
206 fe->ops.tuner_ops.get_rf_strength(fe, &strength);
Michael Krufky1f5ef192007-08-31 17:38:02 -0300207
208 return strength;
209}
210
Michael Krufkyf1c9a282007-12-16 19:27:23 -0300211static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg)
212{
213 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
214 struct tuner *t = fe->analog_demod_priv;
215
216 if (fe_tuner_ops->set_config)
217 return fe_tuner_ops->set_config(fe, priv_cfg);
218
219 tuner_warn("Tuner frontend module has no way to set config\n");
220
221 return 0;
222}
223
Michael Krufky4e9154b2007-10-21 19:39:50 -0300224static void tuner_status(struct dvb_frontend *fe);
Michael Krufky1dde7a42007-10-21 13:40:56 -0300225
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300226static struct analog_demod_ops tuner_analog_ops = {
Michael Krufkyc7919d52007-12-08 17:06:30 -0300227 .set_params = fe_set_params,
Michael Krufky1dde7a42007-10-21 13:40:56 -0300228 .standby = fe_standby,
Michael Krufky1dde7a42007-10-21 13:40:56 -0300229 .has_signal = fe_has_signal,
Michael Krufkyf1c9a282007-12-16 19:27:23 -0300230 .set_config = fe_set_config,
Michael Krufky1dde7a42007-10-21 13:40:56 -0300231 .tuner_status = tuner_status
232};
233
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300234/*
235 * Functions that are common to both TV and radio
236 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300238static void set_tv_freq(struct i2c_client *c, unsigned int freq);
239static void set_radio_freq(struct i2c_client *c, unsigned int freq);
240static const struct v4l2_subdev_ops tuner_ops;
Steven Toth27c685a2008-01-05 16:50:14 -0300241
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700242static void set_type(struct i2c_client *c, unsigned int type,
Hartmut Hackmannde956c12007-04-27 12:31:12 -0300243 unsigned int new_mode_mask, unsigned int new_config,
Michael Krufkyd7cba042008-09-12 13:31:45 -0300244 int (*tuner_callback) (void *dev, int component, int cmd, int arg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300246 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Michael Krufkye18f9442007-08-21 01:25:48 -0300247 struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300248 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700249 unsigned char buffer[4];
Michael Krufkyd6eef492009-10-24 16:42:16 -0300250 int tune_now = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700252 if (type == UNSET || type == TUNER_ABSENT) {
253 tuner_dbg ("tuner 0x%02x: Tuner type absent\n",c->addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 return;
255 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 t->type = type;
Michael Krufkye7ddcd92009-03-28 15:35:26 -0300258 /* prevent invalid config values */
Roel Kluinf14a2972009-10-23 07:59:42 -0300259 t->config = new_config < 256 ? new_config : 0;
Hartmut Hackmanncfeb8832007-04-27 12:31:17 -0300260 if (tuner_callback != NULL) {
261 tuner_dbg("defining GPIO callback\n");
Michael Krufkyd7cba042008-09-12 13:31:45 -0300262 t->fe.callback = tuner_callback;
Hartmut Hackmanncfeb8832007-04-27 12:31:17 -0300263 }
Hartmut Hackmann80f90fb2007-04-27 12:31:18 -0300264
Mauro Carvalho Chehab48aa3362007-10-29 11:33:18 -0300265 if (t->mode == T_UNINITIALIZED) {
Hartmut Hackmann80f90fb2007-04-27 12:31:18 -0300266 tuner_dbg ("tuner 0x%02x: called during i2c_client register by adapter's attach_inform\n", c->addr);
267
268 return;
269 }
270
Michael Krufkyb2083192007-05-29 22:54:06 -0300271 /* discard private data, in case set_type() was previously called */
Michael Krufkya07c8772008-04-29 03:54:19 -0300272 tuner_detach(&t->fe);
273 t->fe.analog_demod_priv = NULL;
Michael Krufkybe2b85a2007-06-04 14:40:27 -0300274
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 switch (t->type) {
276 case TUNER_MT2032:
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300277 if (!dvb_attach(microtune_attach,
278 &t->fe, t->i2c->adapter, t->i2c->addr))
279 goto attach_failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 break;
281 case TUNER_PHILIPS_TDA8290:
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300282 {
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300283 struct tda829x_config cfg = {
284 .lna_cfg = t->config,
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300285 };
286 if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter,
287 t->i2c->addr, &cfg))
288 goto attach_failed;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300289 break;
290 }
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700291 case TUNER_TEA5767:
Michael Krufkya07c8772008-04-29 03:54:19 -0300292 if (!dvb_attach(tea5767_attach, &t->fe,
293 t->i2c->adapter, t->i2c->addr))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300294 goto attach_failed;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700295 t->mode_mask = T_RADIO;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700296 break;
Mauro Carvalho Chehab8573a9e2007-04-08 01:09:11 -0300297 case TUNER_TEA5761:
Michael Krufkya07c8772008-04-29 03:54:19 -0300298 if (!dvb_attach(tea5761_attach, &t->fe,
299 t->i2c->adapter, t->i2c->addr))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300300 goto attach_failed;
Mauro Carvalho Chehab8573a9e2007-04-08 01:09:11 -0300301 t->mode_mask = T_RADIO;
302 break;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700303 case TUNER_PHILIPS_FMD1216ME_MK3:
304 buffer[0] = 0x0b;
305 buffer[1] = 0xdc;
306 buffer[2] = 0x9c;
307 buffer[3] = 0x60;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700308 i2c_master_send(c, buffer, 4);
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700309 mdelay(1);
310 buffer[2] = 0x86;
311 buffer[3] = 0x54;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700312 i2c_master_send(c, buffer, 4);
Michael Krufkya07c8772008-04-29 03:54:19 -0300313 if (!dvb_attach(simple_tuner_attach, &t->fe,
314 t->i2c->adapter, t->i2c->addr, t->type))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300315 goto attach_failed;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700316 break;
Hartmut Hackmann93df3412005-11-08 21:36:31 -0800317 case TUNER_PHILIPS_TD1316:
318 buffer[0] = 0x0b;
319 buffer[1] = 0xdc;
320 buffer[2] = 0x86;
321 buffer[3] = 0xa4;
Michael Krufkya07c8772008-04-29 03:54:19 -0300322 i2c_master_send(c, buffer, 4);
323 if (!dvb_attach(simple_tuner_attach, &t->fe,
324 t->i2c->adapter, t->i2c->addr, t->type))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300325 goto attach_failed;
Markus Rechbergerac272ed2006-01-23 17:11:09 -0200326 break;
Mauro Carvalho Chehab690c5442007-10-29 11:33:18 -0300327 case TUNER_XC2028:
328 {
Michel Ludwiga37b4c92007-11-16 07:46:14 -0300329 struct xc2028_config cfg = {
330 .i2c_adap = t->i2c->adapter,
331 .i2c_addr = t->i2c->addr,
Michel Ludwiga37b4c92007-11-16 07:46:14 -0300332 };
Michael Krufkya07c8772008-04-29 03:54:19 -0300333 if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300334 goto attach_failed;
Michael Krufkyd6eef492009-10-24 16:42:16 -0300335 tune_now = 0;
Mauro Carvalho Chehab690c5442007-10-29 11:33:18 -0300336 break;
337 }
Mauro Carvalho Chehab15396232006-06-23 16:13:56 -0300338 case TUNER_TDA9887:
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300339 if (!dvb_attach(tda9887_attach,
340 &t->fe, t->i2c->adapter, t->i2c->addr))
341 goto attach_failed;
Mauro Carvalho Chehab15396232006-06-23 16:13:56 -0300342 break;
Steven Toth27c685a2008-01-05 16:50:14 -0300343 case TUNER_XC5000:
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300344 {
Steven Toth27c685a2008-01-05 16:50:14 -0300345 xc5000_cfg.i2c_address = t->i2c->addr;
Devin Heitmuellerea227862009-03-11 02:58:53 -0300346 /* if_khz will be set when the digital dvb_attach() occurs */
347 xc5000_cfg.if_khz = 0;
Michael Krufkya07c8772008-04-29 03:54:19 -0300348 if (!dvb_attach(xc5000_attach,
Michael Krufky30650962008-09-06 14:56:58 -0300349 &t->fe, t->i2c->adapter, &xc5000_cfg))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300350 goto attach_failed;
Michael Krufkyd6eef492009-10-24 16:42:16 -0300351 tune_now = 0;
Steven Toth27c685a2008-01-05 16:50:14 -0300352 break;
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300353 }
Michael Krufky93463892009-09-15 23:04:18 -0300354 case TUNER_NXP_TDA18271:
355 {
356 struct tda18271_config cfg = {
357 .config = t->config,
Mauro Carvalho Chehabe350d442010-09-26 22:58:28 -0300358 .small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
Michael Krufky93463892009-09-15 23:04:18 -0300359 };
360
361 if (!dvb_attach(tda18271_attach, &t->fe, t->i2c->addr,
362 t->i2c->adapter, &cfg))
363 goto attach_failed;
Michael Krufkyd6eef492009-10-24 16:42:16 -0300364 tune_now = 0;
Michael Krufky93463892009-09-15 23:04:18 -0300365 break;
366 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 default:
Michael Krufkya07c8772008-04-29 03:54:19 -0300368 if (!dvb_attach(simple_tuner_attach, &t->fe,
369 t->i2c->adapter, t->i2c->addr, t->type))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300370 goto attach_failed;
371
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 break;
373 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700374
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300375 if ((NULL == analog_ops->set_params) &&
Michael Krufky1dde7a42007-10-21 13:40:56 -0300376 (fe_tuner_ops->set_analog_params)) {
Michael Krufkya07c8772008-04-29 03:54:19 -0300377
Michael Krufky7271e602008-05-26 16:08:40 +0200378 t->name = fe_tuner_ops->info.name;
Michael Krufkye18f9442007-08-21 01:25:48 -0300379
Michael Krufky4e9154b2007-10-21 19:39:50 -0300380 t->fe.analog_demod_priv = t;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300381 memcpy(analog_ops, &tuner_analog_ops,
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300382 sizeof(struct analog_demod_ops));
Michael Krufkya07c8772008-04-29 03:54:19 -0300383
Michael Krufkya55db8c2007-12-09 13:52:51 -0300384 } else {
Michael Krufky7271e602008-05-26 16:08:40 +0200385 t->name = analog_ops->info.name;
Michael Krufkye18f9442007-08-21 01:25:48 -0300386 }
387
Michael Krufky7271e602008-05-26 16:08:40 +0200388 tuner_dbg("type set to %s\n", t->name);
Michael Krufkye18f9442007-08-21 01:25:48 -0300389
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700390 if (t->mode_mask == T_UNINITIALIZED)
391 t->mode_mask = new_mode_mask;
392
Michael Krufkyd6eef492009-10-24 16:42:16 -0300393 /* Some tuners require more initialization setup before use,
394 such as firmware download or device calibration.
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300395 trying to set a frequency here will just fail
396 FIXME: better to move set_freq to the tuner code. This is needed
397 on analog tuners for PLL to properly work
398 */
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300399 if (tune_now) {
400 if (V4L2_TUNER_RADIO == t->mode)
401 set_radio_freq(c, t->radio_freq);
402 else
403 set_tv_freq(c, t->tv_freq);
404 }
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300405
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700406 tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
Laurent Riffard604f28e2005-11-26 20:43:39 +0100407 c->adapter->name, c->driver->driver.name, c->addr << 1, type,
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700408 t->mode_mask);
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300409 return;
410
411attach_failed:
412 tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
413 t->type = TUNER_ABSENT;
414 t->mode_mask = T_UNINITIALIZED;
415
416 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417}
418
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700419/*
420 * This function apply tuner config to tuner specified
421 * by tun_setup structure. I addr is unset, then admin status
422 * and tun addr status is more precise then current status,
423 * it's applied. Otherwise status and type are applied only to
424 * tuner with exactly the same addr.
425*/
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700426
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700427static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700428{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300429 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700430
Hartmut Hackmannde956c12007-04-27 12:31:12 -0300431 if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
432 (t->mode_mask & tun_setup->mode_mask))) ||
433 (tun_setup->addr == c->addr)) {
434 set_type(c, tun_setup->type, tun_setup->mode_mask,
Hartmut Hackmanncfeb8832007-04-27 12:31:17 -0300435 tun_setup->config, tun_setup->tuner_callback);
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300436 } else
437 tuner_dbg("set addr discarded for type %i, mask %x. "
438 "Asked to change tuner at addr 0x%02x, with mask %x\n",
439 t->type, t->mode_mask,
440 tun_setup->addr, tun_setup->mode_mask);
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700441}
442
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300443static int tuner_s_type_addr(struct v4l2_subdev *sd, struct tuner_setup *type)
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700444{
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300445 struct tuner *t = to_tuner(sd);
446 struct i2c_client *client = v4l2_get_subdevdata(sd);
447
448 tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=0x%02x\n",
449 type->type,
450 type->addr,
451 type->mode_mask,
452 type->config);
453
454 set_addr(client, type);
455 return 0;
456}
457
458static int tuner_s_config(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *cfg)
459{
460 struct tuner *t = to_tuner(sd);
461 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
462
463 if (t->type != cfg->tuner)
464 return 0;
465
466 if (analog_ops->set_config) {
467 analog_ops->set_config(&t->fe, cfg->priv);
468 return 0;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700469 }
Mauro Carvalho Chehab793cf9e2005-09-09 13:03:37 -0700470
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300471 tuner_dbg("Tuner frontend module has no way to set config\n");
Mauro Carvalho Chehab793cf9e2005-09-09 13:03:37 -0700472 return 0;
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700473}
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700474
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300475/* Search for existing radio and/or TV tuners on the given I2C adapter.
476 Note that when this function is called from tuner_probe you can be
477 certain no other devices will be added/deleted at the same time, I2C
478 core protects against that. */
479static void tuner_lookup(struct i2c_adapter *adap,
480 struct tuner **radio, struct tuner **tv)
481{
482 struct tuner *pos;
483
484 *radio = NULL;
485 *tv = NULL;
486
487 list_for_each_entry(pos, &tuner_list, list) {
488 int mode_mask;
489
490 if (pos->i2c->adapter != adap ||
491 strcmp(pos->i2c->driver->driver.name, "tuner"))
492 continue;
493
494 mode_mask = pos->mode_mask & ~T_STANDBY;
495 if (*radio == NULL && mode_mask == T_RADIO)
496 *radio = pos;
497 /* Note: currently TDA9887 is the only demod-only
498 device. If other devices appear then we need to
499 make this test more general. */
500 else if (*tv == NULL && pos->type != TUNER_TDA9887 &&
501 (pos->mode_mask & (T_ANALOG_TV | T_DIGITAL_TV)))
502 *tv = pos;
503 }
504}
505
506/* During client attach, set_type is called by adapter's attach_inform callback.
507 set_type must then be completed by tuner_probe.
508 */
509static int tuner_probe(struct i2c_client *client,
510 const struct i2c_device_id *id)
511{
512 struct tuner *t;
513 struct tuner *radio;
514 struct tuner *tv;
515
516 t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
517 if (NULL == t)
518 return -ENOMEM;
519 v4l2_i2c_subdev_init(&t->sd, client, &tuner_ops);
520 t->i2c = client;
521 t->name = "(tuner unset)";
522 t->type = UNSET;
523 t->audmode = V4L2_TUNER_MODE_STEREO;
524 t->mode_mask = T_UNINITIALIZED;
525
526 if (show_i2c) {
527 unsigned char buffer[16];
528 int i, rc;
529
530 memset(buffer, 0, sizeof(buffer));
531 rc = i2c_master_recv(client, buffer, sizeof(buffer));
532 tuner_info("I2C RECV = ");
533 for (i = 0; i < rc; i++)
534 printk(KERN_CONT "%02x ", buffer[i]);
535 printk("\n");
536 }
537
538 /* autodetection code based on the i2c addr */
539 if (!no_autodetect) {
540 switch (client->addr) {
541 case 0x10:
542 if (tuner_symbol_probe(tea5761_autodetection,
543 t->i2c->adapter,
544 t->i2c->addr) >= 0) {
545 t->type = TUNER_TEA5761;
546 t->mode_mask = T_RADIO;
547 t->mode = T_STANDBY;
548 /* Sets freq to FM range */
549 t->radio_freq = 87.5 * 16000;
550 tuner_lookup(t->i2c->adapter, &radio, &tv);
551 if (tv)
552 tv->mode_mask &= ~T_RADIO;
553
554 goto register_client;
555 }
556 kfree(t);
557 return -ENODEV;
558 case 0x42:
559 case 0x43:
560 case 0x4a:
561 case 0x4b:
562 /* If chip is not tda8290, don't register.
563 since it can be tda9887*/
564 if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
565 t->i2c->addr) >= 0) {
566 tuner_dbg("tda829x detected\n");
567 } else {
568 /* Default is being tda9887 */
569 t->type = TUNER_TDA9887;
570 t->mode_mask = T_RADIO | T_ANALOG_TV |
571 T_DIGITAL_TV;
572 t->mode = T_STANDBY;
573 goto register_client;
574 }
575 break;
576 case 0x60:
577 if (tuner_symbol_probe(tea5767_autodetection,
578 t->i2c->adapter, t->i2c->addr)
579 >= 0) {
580 t->type = TUNER_TEA5767;
581 t->mode_mask = T_RADIO;
582 t->mode = T_STANDBY;
583 /* Sets freq to FM range */
584 t->radio_freq = 87.5 * 16000;
585 tuner_lookup(t->i2c->adapter, &radio, &tv);
586 if (tv)
587 tv->mode_mask &= ~T_RADIO;
588
589 goto register_client;
590 }
591 break;
592 }
593 }
594
595 /* Initializes only the first TV tuner on this adapter. Why only the
596 first? Because there are some devices (notably the ones with TI
597 tuners) that have more than one i2c address for the *same* device.
598 Experience shows that, except for just one case, the first
599 address is the right one. The exception is a Russian tuner
600 (ACORP_Y878F). So, the desired behavior is just to enable the
601 first found TV tuner. */
602 tuner_lookup(t->i2c->adapter, &radio, &tv);
603 if (tv == NULL) {
604 t->mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
605 if (radio == NULL)
606 t->mode_mask |= T_RADIO;
607 tuner_dbg("Setting mode_mask to 0x%02x\n", t->mode_mask);
608 t->tv_freq = 400 * 16; /* Sets freq to VHF High */
609 t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
610 }
611
612 /* Should be just before return */
613register_client:
614 tuner_info("chip found @ 0x%x (%s)\n", client->addr << 1,
615 client->adapter->name);
616
617 /* Sets a default mode */
618 if (t->mode_mask & T_ANALOG_TV) {
619 t->mode = V4L2_TUNER_ANALOG_TV;
620 } else if (t->mode_mask & T_RADIO) {
621 t->mode = V4L2_TUNER_RADIO;
622 } else {
623 t->mode = V4L2_TUNER_DIGITAL_TV;
624 }
625 set_type(client, t->type, t->mode_mask, t->config, t->fe.callback);
626 list_add_tail(&t->list, &tuner_list);
627 return 0;
628}
629
630static int tuner_remove(struct i2c_client *client)
631{
632 struct tuner *t = to_tuner(i2c_get_clientdata(client));
633
634 v4l2_device_unregister_subdev(&t->sd);
635 tuner_detach(&t->fe);
636 t->fe.analog_demod_priv = NULL;
637
638 list_del(&t->list);
639 kfree(t);
640 return 0;
641}
642
643/*
644 * Functions that are specific for TV mode
645 */
646
647/* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */
648static void set_tv_freq(struct i2c_client *c, unsigned int freq)
649{
650 struct tuner *t = to_tuner(i2c_get_clientdata(c));
651 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
652
653 struct analog_parameters params = {
654 .mode = t->mode,
655 .audmode = t->audmode,
656 .std = t->std
657 };
658
659 if (t->type == UNSET) {
660 tuner_warn ("tuner type not set\n");
661 return;
662 }
663 if (NULL == analog_ops->set_params) {
664 tuner_warn ("Tuner has no way to set tv freq\n");
665 return;
666 }
667 if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
668 tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n",
669 freq / 16, freq % 16 * 100 / 16, tv_range[0],
670 tv_range[1]);
671 /* V4L2 spec: if the freq is not possible then the closest
672 possible value should be selected */
673 if (freq < tv_range[0] * 16)
674 freq = tv_range[0] * 16;
675 else
676 freq = tv_range[1] * 16;
677 }
678 params.frequency = freq;
679 tuner_dbg("tv freq set to %d.%02d\n",
680 freq / 16, freq % 16 * 100 / 16);
681 t->tv_freq = freq;
682
683 analog_ops->set_params(&t->fe, &params);
684}
685
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700686/* get more precise norm info from insmod option */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687static int tuner_fixup_std(struct tuner *t)
688{
689 if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 switch (pal[0]) {
Hans Verkuile71ced12006-12-11 15:51:43 -0300691 case '6':
692 tuner_dbg ("insmod fixup: PAL => PAL-60\n");
693 t->std = V4L2_STD_PAL_60;
694 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 case 'b':
696 case 'B':
697 case 'g':
698 case 'G':
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700699 tuner_dbg ("insmod fixup: PAL => PAL-BG\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 t->std = V4L2_STD_PAL_BG;
701 break;
702 case 'i':
703 case 'I':
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700704 tuner_dbg ("insmod fixup: PAL => PAL-I\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 t->std = V4L2_STD_PAL_I;
706 break;
707 case 'd':
708 case 'D':
709 case 'k':
710 case 'K':
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700711 tuner_dbg ("insmod fixup: PAL => PAL-DK\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 t->std = V4L2_STD_PAL_DK;
713 break;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700714 case 'M':
715 case 'm':
716 tuner_dbg ("insmod fixup: PAL => PAL-M\n");
717 t->std = V4L2_STD_PAL_M;
718 break;
719 case 'N':
720 case 'n':
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200721 if (pal[1] == 'c' || pal[1] == 'C') {
722 tuner_dbg("insmod fixup: PAL => PAL-Nc\n");
723 t->std = V4L2_STD_PAL_Nc;
724 } else {
725 tuner_dbg ("insmod fixup: PAL => PAL-N\n");
726 t->std = V4L2_STD_PAL_N;
727 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700728 break;
Mauro Carvalho Chehab21d4df32005-09-09 13:03:59 -0700729 case '-':
730 /* default parameter, do nothing */
731 break;
732 default:
733 tuner_warn ("pal= argument not recognised\n");
734 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 }
736 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700737 if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
738 switch (secam[0]) {
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200739 case 'b':
740 case 'B':
741 case 'g':
742 case 'G':
743 case 'h':
744 case 'H':
745 tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n");
746 t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
747 break;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700748 case 'd':
749 case 'D':
750 case 'k':
751 case 'K':
752 tuner_dbg ("insmod fixup: SECAM => SECAM-DK\n");
753 t->std = V4L2_STD_SECAM_DK;
754 break;
755 case 'l':
756 case 'L':
Mauro Carvalho Chehab800d3c62005-11-13 16:07:48 -0800757 if ((secam[1]=='C')||(secam[1]=='c')) {
758 tuner_dbg ("insmod fixup: SECAM => SECAM-L'\n");
759 t->std = V4L2_STD_SECAM_LC;
760 } else {
761 tuner_dbg ("insmod fixup: SECAM => SECAM-L\n");
762 t->std = V4L2_STD_SECAM_L;
763 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700764 break;
Mauro Carvalho Chehab21d4df32005-09-09 13:03:59 -0700765 case '-':
766 /* default parameter, do nothing */
767 break;
768 default:
769 tuner_warn ("secam= argument not recognised\n");
770 break;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700771 }
772 }
773
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200774 if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
775 switch (ntsc[0]) {
776 case 'm':
777 case 'M':
778 tuner_dbg("insmod fixup: NTSC => NTSC-M\n");
779 t->std = V4L2_STD_NTSC_M;
780 break;
781 case 'j':
782 case 'J':
783 tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
784 t->std = V4L2_STD_NTSC_M_JP;
785 break;
Hans Verkuild97a11e2006-02-07 06:48:40 -0200786 case 'k':
787 case 'K':
788 tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
789 t->std = V4L2_STD_NTSC_M_KR;
790 break;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200791 case '-':
792 /* default parameter, do nothing */
793 break;
794 default:
795 tuner_info("ntsc= argument not recognised\n");
796 break;
797 }
798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 return 0;
800}
801
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300802/*
803 * Functions that are specific for Radio mode
804 */
805
806static void set_radio_freq(struct i2c_client *c, unsigned int freq)
807{
808 struct tuner *t = to_tuner(i2c_get_clientdata(c));
809 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
810
811 struct analog_parameters params = {
812 .mode = t->mode,
813 .audmode = t->audmode,
814 .std = t->std
815 };
816
817 if (t->type == UNSET) {
818 tuner_warn ("tuner type not set\n");
819 return;
820 }
821 if (NULL == analog_ops->set_params) {
822 tuner_warn ("tuner has no way to set radio frequency\n");
823 return;
824 }
825 if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
826 tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n",
827 freq / 16000, freq % 16000 * 100 / 16000,
828 radio_range[0], radio_range[1]);
829 /* V4L2 spec: if the freq is not possible then the closest
830 possible value should be selected */
831 if (freq < radio_range[0] * 16000)
832 freq = radio_range[0] * 16000;
833 else
834 freq = radio_range[1] * 16000;
835 }
836 params.frequency = freq;
837 tuner_dbg("radio freq set to %d.%02d\n",
838 freq / 16000, freq % 16000 * 100 / 16000);
839 t->radio_freq = freq;
840
841 analog_ops->set_params(&t->fe, &params);
842}
843
844/*
845 * Functions that should be broken into separate radio/TV functions
846 */
847
848static inline int check_mode(struct tuner *t, char *cmd)
849{
850 if ((1 << t->mode & t->mode_mask) == 0) {
851 return -EINVAL;
852 }
853
854 switch (t->mode) {
855 case V4L2_TUNER_RADIO:
856 tuner_dbg("Cmd %s accepted for radio\n", cmd);
857 break;
858 case V4L2_TUNER_ANALOG_TV:
859 tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
860 break;
861 case V4L2_TUNER_DIGITAL_TV:
862 tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
863 break;
864 }
865 return 0;
866}
867
868/*
869 * Switch tuner to other mode. If tuner support both tv and radio,
870 * set another frequency to some value (This is needed for some pal
871 * tuners to avoid locking). Otherwise, just put second tuner in
872 * standby mode.
873 */
874
875static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd)
876{
877 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
878
879 if (mode == t->mode)
880 return 0;
881
882 t->mode = mode;
883
884 if (check_mode(t, cmd) == -EINVAL) {
885 tuner_dbg("Tuner doesn't support this mode. "
886 "Putting tuner to sleep\n");
887 t->mode = T_STANDBY;
888 if (analog_ops->standby)
889 analog_ops->standby(&t->fe);
890 return -EINVAL;
891 }
892 return 0;
893}
894
895static void set_freq(struct i2c_client *c, unsigned long freq)
896{
897 struct tuner *t = to_tuner(i2c_get_clientdata(c));
898
899 switch (t->mode) {
900 case V4L2_TUNER_RADIO:
901 set_radio_freq(c, freq);
902 break;
903 case V4L2_TUNER_ANALOG_TV:
904 case V4L2_TUNER_DIGITAL_TV:
905 set_tv_freq(c, freq);
906 break;
907 default:
908 tuner_dbg("freq set: unknown mode: 0x%04x!\n",t->mode);
909 }
910}
911
Michael Krufky4e9154b2007-10-21 19:39:50 -0300912static void tuner_status(struct dvb_frontend *fe)
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200913{
Michael Krufky4e9154b2007-10-21 19:39:50 -0300914 struct tuner *t = fe->analog_demod_priv;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200915 unsigned long freq, freq_fraction;
Michael Krufkya07c8772008-04-29 03:54:19 -0300916 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
917 struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200918 const char *p;
919
920 switch (t->mode) {
921 case V4L2_TUNER_RADIO: p = "radio"; break;
922 case V4L2_TUNER_ANALOG_TV: p = "analog TV"; break;
923 case V4L2_TUNER_DIGITAL_TV: p = "digital TV"; break;
924 default: p = "undefined"; break;
925 }
926 if (t->mode == V4L2_TUNER_RADIO) {
Hans Verkuil27487d42006-01-15 15:04:52 -0200927 freq = t->radio_freq / 16000;
928 freq_fraction = (t->radio_freq % 16000) * 100 / 16000;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200929 } else {
Hans Verkuil27487d42006-01-15 15:04:52 -0200930 freq = t->tv_freq / 16;
931 freq_fraction = (t->tv_freq % 16) * 100 / 16;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200932 }
933 tuner_info("Tuner mode: %s\n", p);
934 tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
Mauro Carvalho Chehab4ae5c2e2006-03-25 15:53:38 -0300935 tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std);
Hans Verkuil8a4b2752006-01-23 17:11:09 -0200936 if (t->mode != V4L2_TUNER_RADIO)
937 return;
Michael Krufkye18f9442007-08-21 01:25:48 -0300938 if (fe_tuner_ops->get_status) {
939 u32 tuner_status;
940
941 fe_tuner_ops->get_status(&t->fe, &tuner_status);
942 if (tuner_status & TUNER_STATUS_LOCKED)
943 tuner_info("Tuner is locked.\n");
944 if (tuner_status & TUNER_STATUS_STEREO)
945 tuner_info("Stereo: yes\n");
946 }
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300947 if (analog_ops->has_signal)
948 tuner_info("Signal strength: %d\n",
949 analog_ops->has_signal(fe));
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200950}
Hans Verkuil8a4b2752006-01-23 17:11:09 -0200951
Laurent Pinchart622b8282009-10-05 10:48:17 -0300952static int tuner_s_power(struct v4l2_subdev *sd, int on)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300953{
954 struct tuner *t = to_tuner(sd);
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300955 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956
Laurent Pinchart622b8282009-10-05 10:48:17 -0300957 if (on)
958 return 0;
959
Mauro Carvalho Chehab16a5e532008-12-20 07:17:10 -0300960 tuner_dbg("Putting tuner to sleep\n");
961
Laurent Pinchart622b8282009-10-05 10:48:17 -0300962 if (check_mode(t, "s_power") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300963 return 0;
964 t->mode = T_STANDBY;
965 if (analog_ops->standby)
966 analog_ops->standby(&t->fe);
967 return 0;
968}
969
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300970/* ---------------------------------------------------------------------- */
971
972
973static int tuner_s_radio(struct v4l2_subdev *sd)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300974{
975 struct tuner *t = to_tuner(sd);
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300976 struct i2c_client *client = v4l2_get_subdevdata(sd);
Mauro Carvalho Chehab7f171122007-10-18 19:56:47 -0300977
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300978 if (set_mode(client, t, V4L2_TUNER_RADIO, "s_radio") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300979 return 0;
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300980 if (t->radio_freq)
981 set_freq(client, t->radio_freq);
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300982 return 0;
983}
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700984
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300985/* --- v4l ioctls --- */
986/* take care: bttv does userspace copying, we'll get a
987 kernel pointer here... */
988static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
989{
990 struct tuner *t = to_tuner(sd);
991 struct i2c_client *client = v4l2_get_subdevdata(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
Hans Verkuilbccfa442009-03-30 06:55:27 -0300993 if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "s_std") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300994 return 0;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700995
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300996 t->std = std;
997 tuner_fixup_std(t);
998 if (t->tv_freq)
999 set_freq(client, t->tv_freq);
1000 return 0;
1001}
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -07001002
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001003static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
1004{
1005 struct tuner *t = to_tuner(sd);
1006 struct i2c_client *client = v4l2_get_subdevdata(sd);
Michael Krufkye18f9442007-08-21 01:25:48 -03001007
Hans Verkuilbccfa442009-03-30 06:55:27 -03001008 if (set_mode(client, t, f->type, "s_frequency") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001009 return 0;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001010 set_freq(client, f->frequency);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
1012 return 0;
1013}
1014
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001015static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
1016{
1017 struct tuner *t = to_tuner(sd);
1018 struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
1019
Hans Verkuilbccfa442009-03-30 06:55:27 -03001020 if (check_mode(t, "g_frequency") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001021 return 0;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001022 f->type = t->mode;
1023 if (fe_tuner_ops->get_frequency) {
1024 u32 abs_freq;
1025
1026 fe_tuner_ops->get_frequency(&t->fe, &abs_freq);
1027 f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
Julia Lawall75b697f2009-08-01 16:48:41 -03001028 DIV_ROUND_CLOSEST(abs_freq * 2, 125) :
1029 DIV_ROUND_CLOSEST(abs_freq, 62500);
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001030 return 0;
1031 }
1032 f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
1033 t->radio_freq : t->tv_freq;
1034 return 0;
1035}
1036
1037static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1038{
1039 struct tuner *t = to_tuner(sd);
1040 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
1041 struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
1042
Hans Verkuilbccfa442009-03-30 06:55:27 -03001043 if (check_mode(t, "g_tuner") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001044 return 0;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001045
1046 vt->type = t->mode;
1047 if (analog_ops->get_afc)
1048 vt->afc = analog_ops->get_afc(&t->fe);
1049 if (t->mode == V4L2_TUNER_ANALOG_TV)
1050 vt->capability |= V4L2_TUNER_CAP_NORM;
1051 if (t->mode != V4L2_TUNER_RADIO) {
1052 vt->rangelow = tv_range[0] * 16;
1053 vt->rangehigh = tv_range[1] * 16;
1054 return 0;
1055 }
1056
1057 /* radio mode */
1058 vt->rxsubchans =
1059 V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
1060 if (fe_tuner_ops->get_status) {
1061 u32 tuner_status;
1062
1063 fe_tuner_ops->get_status(&t->fe, &tuner_status);
1064 vt->rxsubchans =
1065 (tuner_status & TUNER_STATUS_STEREO) ?
1066 V4L2_TUNER_SUB_STEREO :
1067 V4L2_TUNER_SUB_MONO;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001068 }
1069 if (analog_ops->has_signal)
1070 vt->signal = analog_ops->has_signal(&t->fe);
1071 vt->capability |=
1072 V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
1073 vt->audmode = t->audmode;
1074 vt->rangelow = radio_range[0] * 16000;
1075 vt->rangehigh = radio_range[1] * 16000;
1076 return 0;
1077}
1078
1079static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1080{
1081 struct tuner *t = to_tuner(sd);
1082 struct i2c_client *client = v4l2_get_subdevdata(sd);
1083
Hans Verkuilbccfa442009-03-30 06:55:27 -03001084 if (check_mode(t, "s_tuner") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001085 return 0;
1086
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001087 /* do nothing unless we're a radio tuner */
1088 if (t->mode != V4L2_TUNER_RADIO)
1089 return 0;
1090 t->audmode = vt->audmode;
1091 set_radio_freq(client, t->radio_freq);
1092 return 0;
1093}
1094
1095static int tuner_log_status(struct v4l2_subdev *sd)
1096{
1097 struct tuner *t = to_tuner(sd);
1098 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
1099
1100 if (analog_ops->tuner_status)
1101 analog_ops->tuner_status(&t->fe);
1102 return 0;
1103}
1104
Jean Delvare21b48a72007-03-12 19:20:15 -03001105static int tuner_suspend(struct i2c_client *c, pm_message_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001107 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
Hans Verkuil9dd659d2007-11-04 11:03:36 -03001109 tuner_dbg("suspend\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 /* FIXME: power down ??? */
1111 return 0;
1112}
1113
Jean Delvare21b48a72007-03-12 19:20:15 -03001114static int tuner_resume(struct i2c_client *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001116 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Hans Verkuil9dd659d2007-11-04 11:03:36 -03001118 tuner_dbg("resume\n");
Hans Verkuil27487d42006-01-15 15:04:52 -02001119 if (V4L2_TUNER_RADIO == t->mode) {
1120 if (t->radio_freq)
1121 set_freq(c, t->radio_freq);
1122 } else {
1123 if (t->tv_freq)
1124 set_freq(c, t->tv_freq);
1125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 return 0;
1127}
1128
Hans Verkuil75b4c262009-04-01 03:32:22 -03001129static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg)
1130{
1131 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1132
1133 /* TUNER_SET_CONFIG is still called by tuner-simple.c, so we have
1134 to handle it here.
1135 There must be a better way of doing this... */
1136 switch (cmd) {
1137 case TUNER_SET_CONFIG:
1138 return tuner_s_config(sd, arg);
1139 }
1140 return -ENOIOCTLCMD;
1141}
1142
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001143/* ----------------------------------------------------------------------- */
1144
1145static const struct v4l2_subdev_core_ops tuner_core_ops = {
1146 .log_status = tuner_log_status,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001147 .s_std = tuner_s_std,
Laurent Pinchart622b8282009-10-05 10:48:17 -03001148 .s_power = tuner_s_power,
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001149};
1150
1151static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = {
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001152 .s_radio = tuner_s_radio,
1153 .g_tuner = tuner_g_tuner,
1154 .s_tuner = tuner_s_tuner,
1155 .s_frequency = tuner_s_frequency,
1156 .g_frequency = tuner_g_frequency,
1157 .s_type_addr = tuner_s_type_addr,
1158 .s_config = tuner_s_config,
1159};
1160
1161static const struct v4l2_subdev_ops tuner_ops = {
1162 .core = &tuner_core_ops,
1163 .tuner = &tuner_tuner_ops,
1164};
1165
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166/* ----------------------------------------------------------------------- */
1167
Jean Delvareaf294862008-05-18 20:49:40 +02001168/* This driver supports many devices and the idea is to let the driver
1169 detect which device is present. So rather than listing all supported
1170 devices here, we pretend to support a single, fake device type. */
1171static const struct i2c_device_id tuner_id[] = {
1172 { "tuner", }, /* autodetect */
1173 { }
1174};
1175MODULE_DEVICE_TABLE(i2c, tuner_id);
1176
Hans Verkuil02a20982010-09-15 15:36:23 -03001177static struct i2c_driver tuner_driver = {
1178 .driver = {
1179 .owner = THIS_MODULE,
1180 .name = "tuner",
1181 },
1182 .probe = tuner_probe,
1183 .remove = tuner_remove,
1184 .command = tuner_command,
1185 .suspend = tuner_suspend,
1186 .resume = tuner_resume,
1187 .id_table = tuner_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188};
1189
Hans Verkuil02a20982010-09-15 15:36:23 -03001190static __init int init_tuner(void)
1191{
1192 return i2c_add_driver(&tuner_driver);
1193}
1194
1195static __exit void exit_tuner(void)
1196{
1197 i2c_del_driver(&tuner_driver);
1198}
1199
1200module_init(init_tuner);
1201module_exit(exit_tuner);
1202
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -03001203MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
1204MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
1205MODULE_LICENSE("GPL");