blob: 2a0bea145a7847b611172ffcaf92cfda469ed2ed [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
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -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
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -030058module_param_named(debug, tuner_debug, int, 0644);
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -030059module_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
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -030069static LIST_HEAD(tuner_list);
70
71/*
72 * Debug macros
73 */
74
75#define tuner_warn(fmt, arg...) do { \
76 printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \
77 i2c_adapter_id(t->i2c->adapter), \
78 t->i2c->addr, ##arg); \
79 } while (0)
80
81#define tuner_info(fmt, arg...) do { \
82 printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \
83 i2c_adapter_id(t->i2c->adapter), \
84 t->i2c->addr, ##arg); \
85 } while (0)
86
87#define tuner_err(fmt, arg...) do { \
88 printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \
89 i2c_adapter_id(t->i2c->adapter), \
90 t->i2c->addr, ##arg); \
91 } while (0)
92
93#define tuner_dbg(fmt, arg...) do { \
94 if (tuner_debug) \
95 printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \
96 i2c_adapter_id(t->i2c->adapter), \
97 t->i2c->addr, ##arg); \
98 } while (0)
99
100/*
101 * Internal struct used inside the driver
102 */
103
104struct tuner {
105 /* device */
106 struct dvb_frontend fe;
107 struct i2c_client *i2c;
108 struct v4l2_subdev sd;
109 struct list_head list;
110
111 /* keep track of the current settings */
112 v4l2_std_id std;
113 unsigned int tv_freq;
114 unsigned int radio_freq;
115 unsigned int audmode;
116
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300117 enum v4l2_tuner_type mode;
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300118 unsigned int mode_mask; /* Combination of allowable modes */
119
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300120 bool standby; /* Standby mode */
121
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300122 unsigned int type; /* chip type id */
123 unsigned int config;
124 const char *name;
125};
126
127/*
128 * tuner attach/detach logic
129 */
130
Michael Krufkya07c8772008-04-29 03:54:19 -0300131/** This macro allows us to probe dynamically, avoiding static links */
Mauro Carvalho Chehabff138172008-04-29 23:02:33 -0300132#ifdef CONFIG_MEDIA_ATTACH
Michael Krufkya07c8772008-04-29 03:54:19 -0300133#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
134 int __r = -EINVAL; \
135 typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
136 if (__a) { \
137 __r = (int) __a(ARGS); \
Andrew Mortona1355e52008-04-30 11:40:17 -0300138 symbol_put(FUNCTION); \
Michael Krufkya07c8772008-04-29 03:54:19 -0300139 } else { \
140 printk(KERN_ERR "TUNER: Unable to find " \
141 "symbol "#FUNCTION"()\n"); \
142 } \
Michael Krufkya07c8772008-04-29 03:54:19 -0300143 __r; \
144})
145
146static void tuner_detach(struct dvb_frontend *fe)
147{
148 if (fe->ops.tuner_ops.release) {
149 fe->ops.tuner_ops.release(fe);
150 symbol_put_addr(fe->ops.tuner_ops.release);
151 }
152 if (fe->ops.analog_ops.release) {
153 fe->ops.analog_ops.release(fe);
154 symbol_put_addr(fe->ops.analog_ops.release);
155 }
156}
157#else
158#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
159 FUNCTION(ARGS); \
160})
161
162static void tuner_detach(struct dvb_frontend *fe)
163{
164 if (fe->ops.tuner_ops.release)
165 fe->ops.tuner_ops.release(fe);
166 if (fe->ops.analog_ops.release)
167 fe->ops.analog_ops.release(fe);
168}
169#endif
170
Michael Krufkyf7f427e2007-12-16 22:02:26 -0300171
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300172static inline struct tuner *to_tuner(struct v4l2_subdev *sd)
173{
174 return container_of(sd, struct tuner, sd);
175}
176
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300177/*
178 * struct analog_demod_ops callbacks
179 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
Michael Krufkyc7919d52007-12-08 17:06:30 -0300181static void fe_set_params(struct dvb_frontend *fe,
182 struct analog_parameters *params)
Michael Krufkye18f9442007-08-21 01:25:48 -0300183{
Michael Krufky4e9154b2007-10-21 19:39:50 -0300184 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
185 struct tuner *t = fe->analog_demod_priv;
Michael Krufkye18f9442007-08-21 01:25:48 -0300186
Michael Krufkye18f9442007-08-21 01:25:48 -0300187 if (NULL == fe_tuner_ops->set_analog_params) {
188 tuner_warn("Tuner frontend module has no way to set freq\n");
189 return;
190 }
Michael Krufkyc7919d52007-12-08 17:06:30 -0300191 fe_tuner_ops->set_analog_params(fe, params);
Michael Krufkye18f9442007-08-21 01:25:48 -0300192}
193
Michael Krufky4e9154b2007-10-21 19:39:50 -0300194static void fe_standby(struct dvb_frontend *fe)
Michael Krufkye18f9442007-08-21 01:25:48 -0300195{
Michael Krufky4e9154b2007-10-21 19:39:50 -0300196 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
Michael Krufkye18f9442007-08-21 01:25:48 -0300197
198 if (fe_tuner_ops->sleep)
Michael Krufky4e9154b2007-10-21 19:39:50 -0300199 fe_tuner_ops->sleep(fe);
Michael Krufkye18f9442007-08-21 01:25:48 -0300200}
201
Michael Krufky4e9154b2007-10-21 19:39:50 -0300202static int fe_has_signal(struct dvb_frontend *fe)
Michael Krufky1f5ef192007-08-31 17:38:02 -0300203{
Michael Krufky14196832007-10-14 18:11:53 -0300204 u16 strength = 0;
Michael Krufky1f5ef192007-08-31 17:38:02 -0300205
Michael Krufky4e9154b2007-10-21 19:39:50 -0300206 if (fe->ops.tuner_ops.get_rf_strength)
207 fe->ops.tuner_ops.get_rf_strength(fe, &strength);
Michael Krufky1f5ef192007-08-31 17:38:02 -0300208
209 return strength;
210}
211
Michael Krufkyf1c9a282007-12-16 19:27:23 -0300212static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg)
213{
214 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
215 struct tuner *t = fe->analog_demod_priv;
216
217 if (fe_tuner_ops->set_config)
218 return fe_tuner_ops->set_config(fe, priv_cfg);
219
220 tuner_warn("Tuner frontend module has no way to set config\n");
221
222 return 0;
223}
224
Michael Krufky4e9154b2007-10-21 19:39:50 -0300225static void tuner_status(struct dvb_frontend *fe);
Michael Krufky1dde7a42007-10-21 13:40:56 -0300226
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300227static struct analog_demod_ops tuner_analog_ops = {
Michael Krufkyc7919d52007-12-08 17:06:30 -0300228 .set_params = fe_set_params,
Michael Krufky1dde7a42007-10-21 13:40:56 -0300229 .standby = fe_standby,
Michael Krufky1dde7a42007-10-21 13:40:56 -0300230 .has_signal = fe_has_signal,
Michael Krufkyf1c9a282007-12-16 19:27:23 -0300231 .set_config = fe_set_config,
Michael Krufky1dde7a42007-10-21 13:40:56 -0300232 .tuner_status = tuner_status
233};
234
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300235/*
236 * Functions that are common to both TV and radio
237 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300239static void set_tv_freq(struct i2c_client *c, unsigned int freq);
240static void set_radio_freq(struct i2c_client *c, unsigned int freq);
241static const struct v4l2_subdev_ops tuner_ops;
Steven Toth27c685a2008-01-05 16:50:14 -0300242
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700243static void set_type(struct i2c_client *c, unsigned int type,
Hartmut Hackmannde956c12007-04-27 12:31:12 -0300244 unsigned int new_mode_mask, unsigned int new_config,
Michael Krufkyd7cba042008-09-12 13:31:45 -0300245 int (*tuner_callback) (void *dev, int component, int cmd, int arg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300247 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Michael Krufkye18f9442007-08-21 01:25:48 -0300248 struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300249 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700250 unsigned char buffer[4];
Michael Krufkyd6eef492009-10-24 16:42:16 -0300251 int tune_now = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700253 if (type == UNSET || type == TUNER_ABSENT) {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300254 tuner_dbg("tuner 0x%02x: Tuner type absent\n", c->addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 return;
256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 t->type = type;
Michael Krufkye7ddcd92009-03-28 15:35:26 -0300259 /* prevent invalid config values */
Roel Kluinf14a2972009-10-23 07:59:42 -0300260 t->config = new_config < 256 ? new_config : 0;
Hartmut Hackmanncfeb8832007-04-27 12:31:17 -0300261 if (tuner_callback != NULL) {
262 tuner_dbg("defining GPIO callback\n");
Michael Krufkyd7cba042008-09-12 13:31:45 -0300263 t->fe.callback = tuner_callback;
Hartmut Hackmanncfeb8832007-04-27 12:31:17 -0300264 }
Hartmut Hackmann80f90fb2007-04-27 12:31:18 -0300265
Michael Krufkyb2083192007-05-29 22:54:06 -0300266 /* discard private data, in case set_type() was previously called */
Michael Krufkya07c8772008-04-29 03:54:19 -0300267 tuner_detach(&t->fe);
268 t->fe.analog_demod_priv = NULL;
Michael Krufkybe2b85a2007-06-04 14:40:27 -0300269
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 switch (t->type) {
271 case TUNER_MT2032:
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300272 if (!dvb_attach(microtune_attach,
273 &t->fe, t->i2c->adapter, t->i2c->addr))
274 goto attach_failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 break;
276 case TUNER_PHILIPS_TDA8290:
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300277 {
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300278 struct tda829x_config cfg = {
279 .lna_cfg = t->config,
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300280 };
281 if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter,
282 t->i2c->addr, &cfg))
283 goto attach_failed;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300284 break;
285 }
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700286 case TUNER_TEA5767:
Michael Krufkya07c8772008-04-29 03:54:19 -0300287 if (!dvb_attach(tea5767_attach, &t->fe,
288 t->i2c->adapter, t->i2c->addr))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300289 goto attach_failed;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700290 t->mode_mask = T_RADIO;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700291 break;
Mauro Carvalho Chehab8573a9e2007-04-08 01:09:11 -0300292 case TUNER_TEA5761:
Michael Krufkya07c8772008-04-29 03:54:19 -0300293 if (!dvb_attach(tea5761_attach, &t->fe,
294 t->i2c->adapter, t->i2c->addr))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300295 goto attach_failed;
Mauro Carvalho Chehab8573a9e2007-04-08 01:09:11 -0300296 t->mode_mask = T_RADIO;
297 break;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700298 case TUNER_PHILIPS_FMD1216ME_MK3:
299 buffer[0] = 0x0b;
300 buffer[1] = 0xdc;
301 buffer[2] = 0x9c;
302 buffer[3] = 0x60;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700303 i2c_master_send(c, buffer, 4);
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700304 mdelay(1);
305 buffer[2] = 0x86;
306 buffer[3] = 0x54;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700307 i2c_master_send(c, buffer, 4);
Michael Krufkya07c8772008-04-29 03:54:19 -0300308 if (!dvb_attach(simple_tuner_attach, &t->fe,
309 t->i2c->adapter, t->i2c->addr, t->type))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300310 goto attach_failed;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700311 break;
Hartmut Hackmann93df3412005-11-08 21:36:31 -0800312 case TUNER_PHILIPS_TD1316:
313 buffer[0] = 0x0b;
314 buffer[1] = 0xdc;
315 buffer[2] = 0x86;
316 buffer[3] = 0xa4;
Michael Krufkya07c8772008-04-29 03:54:19 -0300317 i2c_master_send(c, buffer, 4);
318 if (!dvb_attach(simple_tuner_attach, &t->fe,
319 t->i2c->adapter, t->i2c->addr, t->type))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300320 goto attach_failed;
Markus Rechbergerac272ed2006-01-23 17:11:09 -0200321 break;
Mauro Carvalho Chehab690c5442007-10-29 11:33:18 -0300322 case TUNER_XC2028:
323 {
Michel Ludwiga37b4c92007-11-16 07:46:14 -0300324 struct xc2028_config cfg = {
325 .i2c_adap = t->i2c->adapter,
326 .i2c_addr = t->i2c->addr,
Michel Ludwiga37b4c92007-11-16 07:46:14 -0300327 };
Michael Krufkya07c8772008-04-29 03:54:19 -0300328 if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300329 goto attach_failed;
Michael Krufkyd6eef492009-10-24 16:42:16 -0300330 tune_now = 0;
Mauro Carvalho Chehab690c5442007-10-29 11:33:18 -0300331 break;
332 }
Mauro Carvalho Chehab15396232006-06-23 16:13:56 -0300333 case TUNER_TDA9887:
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300334 if (!dvb_attach(tda9887_attach,
335 &t->fe, t->i2c->adapter, t->i2c->addr))
336 goto attach_failed;
Mauro Carvalho Chehab15396232006-06-23 16:13:56 -0300337 break;
Steven Toth27c685a2008-01-05 16:50:14 -0300338 case TUNER_XC5000:
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300339 {
Mauro Carvalho Chehab900f7342011-02-04 12:56:39 -0300340 struct xc5000_config xc5000_cfg = {
341 .i2c_address = t->i2c->addr,
342 /* if_khz will be set at dvb_attach() */
343 .if_khz = 0,
344 };
345
Michael Krufkya07c8772008-04-29 03:54:19 -0300346 if (!dvb_attach(xc5000_attach,
Michael Krufky30650962008-09-06 14:56:58 -0300347 &t->fe, t->i2c->adapter, &xc5000_cfg))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300348 goto attach_failed;
Michael Krufkyd6eef492009-10-24 16:42:16 -0300349 tune_now = 0;
Steven Toth27c685a2008-01-05 16:50:14 -0300350 break;
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300351 }
Michael Krufky93463892009-09-15 23:04:18 -0300352 case TUNER_NXP_TDA18271:
353 {
354 struct tda18271_config cfg = {
355 .config = t->config,
Mauro Carvalho Chehabe350d442010-09-26 22:58:28 -0300356 .small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
Michael Krufky93463892009-09-15 23:04:18 -0300357 };
358
359 if (!dvb_attach(tda18271_attach, &t->fe, t->i2c->addr,
360 t->i2c->adapter, &cfg))
361 goto attach_failed;
Michael Krufkyd6eef492009-10-24 16:42:16 -0300362 tune_now = 0;
Michael Krufky93463892009-09-15 23:04:18 -0300363 break;
364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 default:
Michael Krufkya07c8772008-04-29 03:54:19 -0300366 if (!dvb_attach(simple_tuner_attach, &t->fe,
367 t->i2c->adapter, t->i2c->addr, t->type))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300368 goto attach_failed;
369
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 break;
371 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700372
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300373 if ((NULL == analog_ops->set_params) &&
Michael Krufky1dde7a42007-10-21 13:40:56 -0300374 (fe_tuner_ops->set_analog_params)) {
Michael Krufkya07c8772008-04-29 03:54:19 -0300375
Michael Krufky7271e602008-05-26 16:08:40 +0200376 t->name = fe_tuner_ops->info.name;
Michael Krufkye18f9442007-08-21 01:25:48 -0300377
Michael Krufky4e9154b2007-10-21 19:39:50 -0300378 t->fe.analog_demod_priv = t;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300379 memcpy(analog_ops, &tuner_analog_ops,
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300380 sizeof(struct analog_demod_ops));
Michael Krufkya07c8772008-04-29 03:54:19 -0300381
Michael Krufkya55db8c2007-12-09 13:52:51 -0300382 } else {
Michael Krufky7271e602008-05-26 16:08:40 +0200383 t->name = analog_ops->info.name;
Michael Krufkye18f9442007-08-21 01:25:48 -0300384 }
385
Michael Krufky7271e602008-05-26 16:08:40 +0200386 tuner_dbg("type set to %s\n", t->name);
Michael Krufkye18f9442007-08-21 01:25:48 -0300387
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300388 t->mode_mask = new_mode_mask;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700389
Michael Krufkyd6eef492009-10-24 16:42:16 -0300390 /* Some tuners require more initialization setup before use,
391 such as firmware download or device calibration.
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300392 trying to set a frequency here will just fail
393 FIXME: better to move set_freq to the tuner code. This is needed
394 on analog tuners for PLL to properly work
395 */
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300396 if (tune_now) {
397 if (V4L2_TUNER_RADIO == t->mode)
398 set_radio_freq(c, t->radio_freq);
399 else
400 set_tv_freq(c, t->tv_freq);
401 }
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300402
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700403 tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
Laurent Riffard604f28e2005-11-26 20:43:39 +0100404 c->adapter->name, c->driver->driver.name, c->addr << 1, type,
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700405 t->mode_mask);
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300406 return;
407
408attach_failed:
409 tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
410 t->type = TUNER_ABSENT;
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300411
412 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413}
414
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700415/*
416 * This function apply tuner config to tuner specified
417 * by tun_setup structure. I addr is unset, then admin status
418 * and tun addr status is more precise then current status,
419 * it's applied. Otherwise status and type are applied only to
420 * tuner with exactly the same addr.
421*/
Mauro Carvalho Chehaba34ec5f2011-02-15 00:55:18 -0300422static int tuner_s_type_addr(struct v4l2_subdev *sd,
423 struct tuner_setup *tun_setup)
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700424{
Mauro Carvalho Chehaba34ec5f2011-02-15 00:55:18 -0300425 struct tuner *t = to_tuner(sd);
426 struct i2c_client *c = v4l2_get_subdevdata(sd);
427
428 tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=0x%02x\n",
429 tun_setup->type,
430 tun_setup->addr,
431 tun_setup->mode_mask,
432 tun_setup->config);
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700433
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300434 if ((t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
435 (t->mode_mask & tun_setup->mode_mask))) ||
436 (tun_setup->addr == c->addr)) {
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300437 set_type(c, tun_setup->type, tun_setup->mode_mask,
438 tun_setup->config, tun_setup->tuner_callback);
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300439 } else
440 tuner_dbg("set addr discarded for type %i, mask %x. "
441 "Asked to change tuner at addr 0x%02x, with mask %x\n",
442 t->type, t->mode_mask,
443 tun_setup->addr, tun_setup->mode_mask);
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700444
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300445 return 0;
446}
447
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300448static int tuner_s_config(struct v4l2_subdev *sd,
449 const struct v4l2_priv_tun_config *cfg)
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300450{
451 struct tuner *t = to_tuner(sd);
452 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
453
454 if (t->type != cfg->tuner)
455 return 0;
456
457 if (analog_ops->set_config) {
458 analog_ops->set_config(&t->fe, cfg->priv);
459 return 0;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700460 }
Mauro Carvalho Chehab793cf9e2005-09-09 13:03:37 -0700461
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300462 tuner_dbg("Tuner frontend module has no way to set config\n");
Mauro Carvalho Chehab793cf9e2005-09-09 13:03:37 -0700463 return 0;
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700464}
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700465
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300466/* Search for existing radio and/or TV tuners on the given I2C adapter.
467 Note that when this function is called from tuner_probe you can be
468 certain no other devices will be added/deleted at the same time, I2C
469 core protects against that. */
470static void tuner_lookup(struct i2c_adapter *adap,
471 struct tuner **radio, struct tuner **tv)
472{
473 struct tuner *pos;
474
475 *radio = NULL;
476 *tv = NULL;
477
478 list_for_each_entry(pos, &tuner_list, list) {
479 int mode_mask;
480
481 if (pos->i2c->adapter != adap ||
482 strcmp(pos->i2c->driver->driver.name, "tuner"))
483 continue;
484
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300485 mode_mask = pos->mode_mask;
486 pos->standby = 1;
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300487 if (*radio == NULL && mode_mask == T_RADIO)
488 *radio = pos;
489 /* Note: currently TDA9887 is the only demod-only
490 device. If other devices appear then we need to
491 make this test more general. */
492 else if (*tv == NULL && pos->type != TUNER_TDA9887 &&
493 (pos->mode_mask & (T_ANALOG_TV | T_DIGITAL_TV)))
494 *tv = pos;
495 }
496}
497
498/* During client attach, set_type is called by adapter's attach_inform callback.
499 set_type must then be completed by tuner_probe.
500 */
501static int tuner_probe(struct i2c_client *client,
502 const struct i2c_device_id *id)
503{
504 struct tuner *t;
505 struct tuner *radio;
506 struct tuner *tv;
507
508 t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
509 if (NULL == t)
510 return -ENOMEM;
511 v4l2_i2c_subdev_init(&t->sd, client, &tuner_ops);
512 t->i2c = client;
513 t->name = "(tuner unset)";
514 t->type = UNSET;
515 t->audmode = V4L2_TUNER_MODE_STEREO;
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300516 t->standby = 1;
517 t->radio_freq = 87.5 * 16000; /* Initial freq range */
518 t->tv_freq = 400 * 16; /* Sets freq to VHF High - needed for some PLL's to properly start */
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300519
520 if (show_i2c) {
521 unsigned char buffer[16];
522 int i, rc;
523
524 memset(buffer, 0, sizeof(buffer));
525 rc = i2c_master_recv(client, buffer, sizeof(buffer));
526 tuner_info("I2C RECV = ");
527 for (i = 0; i < rc; i++)
528 printk(KERN_CONT "%02x ", buffer[i]);
529 printk("\n");
530 }
531
532 /* autodetection code based on the i2c addr */
533 if (!no_autodetect) {
534 switch (client->addr) {
535 case 0x10:
536 if (tuner_symbol_probe(tea5761_autodetection,
537 t->i2c->adapter,
538 t->i2c->addr) >= 0) {
539 t->type = TUNER_TEA5761;
540 t->mode_mask = T_RADIO;
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300541 tuner_lookup(t->i2c->adapter, &radio, &tv);
542 if (tv)
543 tv->mode_mask &= ~T_RADIO;
544
545 goto register_client;
546 }
547 kfree(t);
548 return -ENODEV;
549 case 0x42:
550 case 0x43:
551 case 0x4a:
552 case 0x4b:
553 /* If chip is not tda8290, don't register.
554 since it can be tda9887*/
555 if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
556 t->i2c->addr) >= 0) {
557 tuner_dbg("tda829x detected\n");
558 } else {
559 /* Default is being tda9887 */
560 t->type = TUNER_TDA9887;
561 t->mode_mask = T_RADIO | T_ANALOG_TV |
562 T_DIGITAL_TV;
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300563 goto register_client;
564 }
565 break;
566 case 0x60:
567 if (tuner_symbol_probe(tea5767_autodetection,
568 t->i2c->adapter, t->i2c->addr)
569 >= 0) {
570 t->type = TUNER_TEA5767;
571 t->mode_mask = T_RADIO;
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300572 /* Sets freq to FM range */
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300573 tuner_lookup(t->i2c->adapter, &radio, &tv);
574 if (tv)
575 tv->mode_mask &= ~T_RADIO;
576
577 goto register_client;
578 }
579 break;
580 }
581 }
582
583 /* Initializes only the first TV tuner on this adapter. Why only the
584 first? Because there are some devices (notably the ones with TI
585 tuners) that have more than one i2c address for the *same* device.
586 Experience shows that, except for just one case, the first
587 address is the right one. The exception is a Russian tuner
588 (ACORP_Y878F). So, the desired behavior is just to enable the
589 first found TV tuner. */
590 tuner_lookup(t->i2c->adapter, &radio, &tv);
591 if (tv == NULL) {
592 t->mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
593 if (radio == NULL)
594 t->mode_mask |= T_RADIO;
595 tuner_dbg("Setting mode_mask to 0x%02x\n", t->mode_mask);
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300596 }
597
598 /* Should be just before return */
599register_client:
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300600 /* Sets a default mode */
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300601 if (t->mode_mask & T_ANALOG_TV)
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300602 t->mode = V4L2_TUNER_ANALOG_TV;
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300603 else if (t->mode_mask & T_RADIO)
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300604 t->mode = V4L2_TUNER_RADIO;
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300605 else
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300606 t->mode = V4L2_TUNER_DIGITAL_TV;
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300607 set_type(client, t->type, t->mode_mask, t->config, t->fe.callback);
608 list_add_tail(&t->list, &tuner_list);
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300609
610 tuner_info("Tuner %d found with type(s)%s%s%s.\n",
611 t->type,
612 t->mode_mask & T_RADIO ? " radio" : "",
613 t->mode_mask & T_ANALOG_TV ? " TV" : "",
614 t->mode_mask & T_ANALOG_TV ? " DTV" : "");
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300615 return 0;
616}
617
618static int tuner_remove(struct i2c_client *client)
619{
620 struct tuner *t = to_tuner(i2c_get_clientdata(client));
621
622 v4l2_device_unregister_subdev(&t->sd);
623 tuner_detach(&t->fe);
624 t->fe.analog_demod_priv = NULL;
625
626 list_del(&t->list);
627 kfree(t);
628 return 0;
629}
630
631/*
632 * Functions that are specific for TV mode
633 */
634
635/* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */
636static void set_tv_freq(struct i2c_client *c, unsigned int freq)
637{
638 struct tuner *t = to_tuner(i2c_get_clientdata(c));
639 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
640
641 struct analog_parameters params = {
642 .mode = t->mode,
643 .audmode = t->audmode,
644 .std = t->std
645 };
646
647 if (t->type == UNSET) {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300648 tuner_warn("tuner type not set\n");
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300649 return;
650 }
651 if (NULL == analog_ops->set_params) {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300652 tuner_warn("Tuner has no way to set tv freq\n");
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300653 return;
654 }
655 if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300656 tuner_dbg("TV freq (%d.%02d) out of range (%d-%d)\n",
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300657 freq / 16, freq % 16 * 100 / 16, tv_range[0],
658 tv_range[1]);
659 /* V4L2 spec: if the freq is not possible then the closest
660 possible value should be selected */
661 if (freq < tv_range[0] * 16)
662 freq = tv_range[0] * 16;
663 else
664 freq = tv_range[1] * 16;
665 }
666 params.frequency = freq;
667 tuner_dbg("tv freq set to %d.%02d\n",
668 freq / 16, freq % 16 * 100 / 16);
669 t->tv_freq = freq;
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300670 t->standby = false;
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300671
672 analog_ops->set_params(&t->fe, &params);
673}
674
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700675/* get more precise norm info from insmod option */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676static int tuner_fixup_std(struct tuner *t)
677{
678 if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 switch (pal[0]) {
Hans Verkuile71ced12006-12-11 15:51:43 -0300680 case '6':
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300681 tuner_dbg("insmod fixup: PAL => PAL-60\n");
Hans Verkuile71ced12006-12-11 15:51:43 -0300682 t->std = V4L2_STD_PAL_60;
683 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 case 'b':
685 case 'B':
686 case 'g':
687 case 'G':
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300688 tuner_dbg("insmod fixup: PAL => PAL-BG\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 t->std = V4L2_STD_PAL_BG;
690 break;
691 case 'i':
692 case 'I':
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300693 tuner_dbg("insmod fixup: PAL => PAL-I\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 t->std = V4L2_STD_PAL_I;
695 break;
696 case 'd':
697 case 'D':
698 case 'k':
699 case 'K':
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300700 tuner_dbg("insmod fixup: PAL => PAL-DK\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 t->std = V4L2_STD_PAL_DK;
702 break;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700703 case 'M':
704 case 'm':
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300705 tuner_dbg("insmod fixup: PAL => PAL-M\n");
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700706 t->std = V4L2_STD_PAL_M;
707 break;
708 case 'N':
709 case 'n':
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200710 if (pal[1] == 'c' || pal[1] == 'C') {
711 tuner_dbg("insmod fixup: PAL => PAL-Nc\n");
712 t->std = V4L2_STD_PAL_Nc;
713 } else {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300714 tuner_dbg("insmod fixup: PAL => PAL-N\n");
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200715 t->std = V4L2_STD_PAL_N;
716 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700717 break;
Mauro Carvalho Chehab21d4df32005-09-09 13:03:59 -0700718 case '-':
719 /* default parameter, do nothing */
720 break;
721 default:
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300722 tuner_warn("pal= argument not recognised\n");
Mauro Carvalho Chehab21d4df32005-09-09 13:03:59 -0700723 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 }
725 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700726 if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
727 switch (secam[0]) {
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200728 case 'b':
729 case 'B':
730 case 'g':
731 case 'G':
732 case 'h':
733 case 'H':
734 tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n");
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300735 t->std = V4L2_STD_SECAM_B |
736 V4L2_STD_SECAM_G |
737 V4L2_STD_SECAM_H;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200738 break;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700739 case 'd':
740 case 'D':
741 case 'k':
742 case 'K':
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300743 tuner_dbg("insmod fixup: SECAM => SECAM-DK\n");
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700744 t->std = V4L2_STD_SECAM_DK;
745 break;
746 case 'l':
747 case 'L':
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300748 if ((secam[1] == 'C') || (secam[1] == 'c')) {
749 tuner_dbg("insmod fixup: SECAM => SECAM-L'\n");
Mauro Carvalho Chehab800d3c62005-11-13 16:07:48 -0800750 t->std = V4L2_STD_SECAM_LC;
751 } else {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300752 tuner_dbg("insmod fixup: SECAM => SECAM-L\n");
Mauro Carvalho Chehab800d3c62005-11-13 16:07:48 -0800753 t->std = V4L2_STD_SECAM_L;
754 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700755 break;
Mauro Carvalho Chehab21d4df32005-09-09 13:03:59 -0700756 case '-':
757 /* default parameter, do nothing */
758 break;
759 default:
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300760 tuner_warn("secam= argument not recognised\n");
Mauro Carvalho Chehab21d4df32005-09-09 13:03:59 -0700761 break;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700762 }
763 }
764
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200765 if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
766 switch (ntsc[0]) {
767 case 'm':
768 case 'M':
769 tuner_dbg("insmod fixup: NTSC => NTSC-M\n");
770 t->std = V4L2_STD_NTSC_M;
771 break;
772 case 'j':
773 case 'J':
774 tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
775 t->std = V4L2_STD_NTSC_M_JP;
776 break;
Hans Verkuild97a11e2006-02-07 06:48:40 -0200777 case 'k':
778 case 'K':
779 tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
780 t->std = V4L2_STD_NTSC_M_KR;
781 break;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200782 case '-':
783 /* default parameter, do nothing */
784 break;
785 default:
786 tuner_info("ntsc= argument not recognised\n");
787 break;
788 }
789 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 return 0;
791}
792
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300793/*
794 * Functions that are specific for Radio mode
795 */
796
797static void set_radio_freq(struct i2c_client *c, unsigned int freq)
798{
799 struct tuner *t = to_tuner(i2c_get_clientdata(c));
800 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
801
802 struct analog_parameters params = {
803 .mode = t->mode,
804 .audmode = t->audmode,
805 .std = t->std
806 };
807
808 if (t->type == UNSET) {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300809 tuner_warn("tuner type not set\n");
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300810 return;
811 }
812 if (NULL == analog_ops->set_params) {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300813 tuner_warn("tuner has no way to set radio frequency\n");
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300814 return;
815 }
816 if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300817 tuner_dbg("radio freq (%d.%02d) out of range (%d-%d)\n",
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300818 freq / 16000, freq % 16000 * 100 / 16000,
819 radio_range[0], radio_range[1]);
820 /* V4L2 spec: if the freq is not possible then the closest
821 possible value should be selected */
822 if (freq < radio_range[0] * 16000)
823 freq = radio_range[0] * 16000;
824 else
825 freq = radio_range[1] * 16000;
826 }
827 params.frequency = freq;
828 tuner_dbg("radio freq set to %d.%02d\n",
829 freq / 16000, freq % 16000 * 100 / 16000);
830 t->radio_freq = freq;
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300831 t->standby = false;
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300832
833 analog_ops->set_params(&t->fe, &params);
834}
835
Mauro Carvalho Chehabe2d25a22011-02-04 10:09:07 -0300836/**
837 * check_mode - Verify if tuner supports the requested mode
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300838 * @t: a pointer to the module's internal struct_tuner
Mauro Carvalho Chehabe2d25a22011-02-04 10:09:07 -0300839 *
840 * This function checks if the tuner is capable of tuning analog TV,
841 * digital TV or radio, depending on what the caller wants. If the
842 * tuner can't support that mode, it returns -EINVAL. Otherwise, it
843 * returns 0.
844 * This function is needed for boards that have a separate tuner for
845 * radio (like devices with tea5767).
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300846 */
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300847static inline int check_mode(struct tuner *t, enum v4l2_tuner_type mode)
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300848{
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300849 if ((1 << mode & t->mode_mask) == 0)
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300850 return -EINVAL;
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300851
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300852 return 0;
853}
854
Mauro Carvalho Chehabe2d25a22011-02-04 10:09:07 -0300855/**
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300856 * set_mode_freq - Switch tuner to other mode.
857 * @client: struct i2c_client pointer
858 * @t: a pointer to the module's internal struct_tuner
859 * @mode: enum v4l2_type (radio or TV)
860 * @freq: frequency to set (0 means to use the previous one)
Mauro Carvalho Chehabe2d25a22011-02-04 10:09:07 -0300861 *
862 * If tuner doesn't support the needed mode (radio or TV), prints a
863 * debug message and returns -EINVAL, changing internal state to T_STANDBY.
864 * Otherwise, changes the state and sets frequency to the last value, if
865 * the tuner can sleep or if it supports both Radio and TV.
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300866 */
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300867static int set_mode_freq(struct i2c_client *client, struct tuner *t,
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300868 enum v4l2_tuner_type mode, unsigned int freq)
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300869{
870 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
871
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300872 if (mode != t->mode) {
873 if (check_mode(t, mode) == -EINVAL) {
874 tuner_dbg("Tuner doesn't support mode %d. "
875 "Putting tuner to sleep\n", mode);
876 t->standby = true;
877 if (analog_ops->standby)
878 analog_ops->standby(&t->fe);
879 return -EINVAL;
880 }
881 t->mode = mode;
882 tuner_dbg("Changing to mode %d\n", mode);
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300883 }
Mauro Carvalho Chehabe2d25a22011-02-04 10:09:07 -0300884 if (t->mode == V4L2_TUNER_RADIO) {
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300885 if (freq)
886 t->radio_freq = freq;
887 set_radio_freq(client, t->radio_freq);
Mauro Carvalho Chehabe2d25a22011-02-04 10:09:07 -0300888 } else {
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300889 if (freq)
890 t->tv_freq = freq;
891 set_tv_freq(client, t->tv_freq);
Mauro Carvalho Chehabe2d25a22011-02-04 10:09:07 -0300892 }
893
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300894 return 0;
895}
896
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300897/**
898 * tuner_status - Dumps the current tuner status at dmesg
899 * @fe: pointer to struct dvb_frontend
900 *
901 * This callback is used only for driver debug purposes, answering to
902 * VIDIOC_LOG_STATUS. No changes should happen on this call.
903 */
Michael Krufky4e9154b2007-10-21 19:39:50 -0300904static void tuner_status(struct dvb_frontend *fe)
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200905{
Michael Krufky4e9154b2007-10-21 19:39:50 -0300906 struct tuner *t = fe->analog_demod_priv;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200907 unsigned long freq, freq_fraction;
Michael Krufkya07c8772008-04-29 03:54:19 -0300908 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
909 struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200910 const char *p;
911
912 switch (t->mode) {
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300913 case V4L2_TUNER_RADIO:
914 p = "radio";
915 break;
916 case V4L2_TUNER_DIGITAL_TV:
917 p = "digital TV";
918 break;
919 case V4L2_TUNER_ANALOG_TV:
920 default:
921 p = "analog TV";
922 break;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200923 }
924 if (t->mode == V4L2_TUNER_RADIO) {
Hans Verkuil27487d42006-01-15 15:04:52 -0200925 freq = t->radio_freq / 16000;
926 freq_fraction = (t->radio_freq % 16000) * 100 / 16000;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200927 } else {
Hans Verkuil27487d42006-01-15 15:04:52 -0200928 freq = t->tv_freq / 16;
929 freq_fraction = (t->tv_freq % 16) * 100 / 16;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200930 }
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300931 tuner_info("Tuner mode: %s%s\n", p,
932 t->standby ? " on standby mode" : "");
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200933 tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
Mauro Carvalho Chehab4ae5c2e2006-03-25 15:53:38 -0300934 tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std);
Hans Verkuil8a4b2752006-01-23 17:11:09 -0200935 if (t->mode != V4L2_TUNER_RADIO)
Mauro Carvalho Chehab7d275bf2011-02-04 11:28:00 -0300936 return;
Michael Krufkye18f9442007-08-21 01:25:48 -0300937 if (fe_tuner_ops->get_status) {
938 u32 tuner_status;
939
940 fe_tuner_ops->get_status(&t->fe, &tuner_status);
941 if (tuner_status & TUNER_STATUS_LOCKED)
942 tuner_info("Tuner is locked.\n");
943 if (tuner_status & TUNER_STATUS_STEREO)
944 tuner_info("Stereo: yes\n");
945 }
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300946 if (analog_ops->has_signal)
947 tuner_info("Signal strength: %d\n",
948 analog_ops->has_signal(fe));
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200949}
Hans Verkuil8a4b2752006-01-23 17:11:09 -0200950
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300951/**
952 * tuner_s_power - controls the power state of the tuner
953 * @sd: pointer to struct v4l2_subdev
954 * @on: a zero value puts the tuner to sleep
955 */
Laurent Pinchart622b8282009-10-05 10:48:17 -0300956static int tuner_s_power(struct v4l2_subdev *sd, int on)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300957{
958 struct tuner *t = to_tuner(sd);
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300959 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300961 /* FIXME: Why this function don't wake the tuner if on != 0 ? */
Laurent Pinchart622b8282009-10-05 10:48:17 -0300962 if (on)
963 return 0;
964
Mauro Carvalho Chehab16a5e532008-12-20 07:17:10 -0300965 tuner_dbg("Putting tuner to sleep\n");
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300966 t->standby = true;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300967 if (analog_ops->standby)
968 analog_ops->standby(&t->fe);
969 return 0;
970}
971
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300972/* ---------------------------------------------------------------------- */
973
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300974static int tuner_s_radio(struct v4l2_subdev *sd)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300975{
976 struct tuner *t = to_tuner(sd);
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -0300977 struct i2c_client *client = v4l2_get_subdevdata(sd);
Mauro Carvalho Chehab7f171122007-10-18 19:56:47 -0300978
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300979 if (set_mode_freq(client, t, V4L2_TUNER_RADIO, 0) == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300980 return 0;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300981 return 0;
982}
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700983
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300984/* --- v4l ioctls --- */
985/* take care: bttv does userspace copying, we'll get a
986 kernel pointer here... */
987static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
988{
989 struct tuner *t = to_tuner(sd);
990 struct i2c_client *client = v4l2_get_subdevdata(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300992 if (set_mode_freq(client, t, V4L2_TUNER_ANALOG_TV, 0) == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300993 return 0;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700994
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300995 t->std = std;
996 tuner_fixup_std(t);
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -0300997
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300998 return 0;
999}
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -07001000
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001001static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
1002{
1003 struct tuner *t = to_tuner(sd);
1004 struct i2c_client *client = v4l2_get_subdevdata(sd);
Michael Krufkye18f9442007-08-21 01:25:48 -03001005
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001006 if (set_mode_freq(client, t, f->type, f->frequency) == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001007 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
1009 return 0;
1010}
1011
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001012static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
1013{
1014 struct tuner *t = to_tuner(sd);
1015 struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
1016
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001017 if (check_mode(t, f->type) == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001018 return 0;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001019 f->type = t->mode;
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001020 if (fe_tuner_ops->get_frequency && !t->standby) {
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001021 u32 abs_freq;
1022
1023 fe_tuner_ops->get_frequency(&t->fe, &abs_freq);
1024 f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
Julia Lawall75b697f2009-08-01 16:48:41 -03001025 DIV_ROUND_CLOSEST(abs_freq * 2, 125) :
1026 DIV_ROUND_CLOSEST(abs_freq, 62500);
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001027 } else {
1028 f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
1029 t->radio_freq : t->tv_freq;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001030 }
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001031 return 0;
1032}
1033
1034static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1035{
1036 struct tuner *t = to_tuner(sd);
1037 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
1038 struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
1039
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001040 if (check_mode(t, vt->type) == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001041 return 0;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001042 vt->type = t->mode;
1043 if (analog_ops->get_afc)
1044 vt->afc = analog_ops->get_afc(&t->fe);
1045 if (t->mode == V4L2_TUNER_ANALOG_TV)
1046 vt->capability |= V4L2_TUNER_CAP_NORM;
1047 if (t->mode != V4L2_TUNER_RADIO) {
1048 vt->rangelow = tv_range[0] * 16;
1049 vt->rangehigh = tv_range[1] * 16;
1050 return 0;
1051 }
1052
1053 /* radio mode */
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001054 vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001055 if (fe_tuner_ops->get_status) {
1056 u32 tuner_status;
1057
1058 fe_tuner_ops->get_status(&t->fe, &tuner_status);
1059 vt->rxsubchans =
1060 (tuner_status & TUNER_STATUS_STEREO) ?
1061 V4L2_TUNER_SUB_STEREO :
1062 V4L2_TUNER_SUB_MONO;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001063 }
1064 if (analog_ops->has_signal)
1065 vt->signal = analog_ops->has_signal(&t->fe);
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001066 vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001067 vt->audmode = t->audmode;
1068 vt->rangelow = radio_range[0] * 16000;
1069 vt->rangehigh = radio_range[1] * 16000;
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001070
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001071 return 0;
1072}
1073
1074static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1075{
1076 struct tuner *t = to_tuner(sd);
1077 struct i2c_client *client = v4l2_get_subdevdata(sd);
1078
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001079 if (set_mode_freq(client, t, vt->type, 0) == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001080 return 0;
1081
Mauro Carvalho Chehabcbde6892011-02-04 10:42:09 -03001082 if (t->mode == V4L2_TUNER_RADIO)
1083 t->audmode = vt->audmode;
1084
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001085 return 0;
1086}
1087
1088static int tuner_log_status(struct v4l2_subdev *sd)
1089{
1090 struct tuner *t = to_tuner(sd);
1091 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
1092
1093 if (analog_ops->tuner_status)
1094 analog_ops->tuner_status(&t->fe);
1095 return 0;
1096}
1097
Jean Delvare21b48a72007-03-12 19:20:15 -03001098static int tuner_suspend(struct i2c_client *c, pm_message_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001100 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Mauro Carvalho Chehabe2f63d92011-02-04 11:15:21 -03001101 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
Hans Verkuil9dd659d2007-11-04 11:03:36 -03001103 tuner_dbg("suspend\n");
Mauro Carvalho Chehabe2f63d92011-02-04 11:15:21 -03001104
1105 if (!t->standby && analog_ops->standby)
1106 analog_ops->standby(&t->fe);
1107
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 return 0;
1109}
1110
Jean Delvare21b48a72007-03-12 19:20:15 -03001111static int tuner_resume(struct i2c_client *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001113 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
Hans Verkuil9dd659d2007-11-04 11:03:36 -03001115 tuner_dbg("resume\n");
Mauro Carvalho Chehabe2f63d92011-02-04 11:15:21 -03001116
1117 if (!t->standby)
1118 set_mode_freq(c, t, t->type, 0);
1119
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 return 0;
1121}
1122
Hans Verkuil75b4c262009-04-01 03:32:22 -03001123static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg)
1124{
1125 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1126
1127 /* TUNER_SET_CONFIG is still called by tuner-simple.c, so we have
1128 to handle it here.
1129 There must be a better way of doing this... */
1130 switch (cmd) {
1131 case TUNER_SET_CONFIG:
1132 return tuner_s_config(sd, arg);
1133 }
1134 return -ENOIOCTLCMD;
1135}
1136
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001137/* ----------------------------------------------------------------------- */
1138
1139static const struct v4l2_subdev_core_ops tuner_core_ops = {
1140 .log_status = tuner_log_status,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001141 .s_std = tuner_s_std,
Laurent Pinchart622b8282009-10-05 10:48:17 -03001142 .s_power = tuner_s_power,
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001143};
1144
1145static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = {
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001146 .s_radio = tuner_s_radio,
1147 .g_tuner = tuner_g_tuner,
1148 .s_tuner = tuner_s_tuner,
1149 .s_frequency = tuner_s_frequency,
1150 .g_frequency = tuner_g_frequency,
1151 .s_type_addr = tuner_s_type_addr,
1152 .s_config = tuner_s_config,
1153};
1154
1155static const struct v4l2_subdev_ops tuner_ops = {
1156 .core = &tuner_core_ops,
1157 .tuner = &tuner_tuner_ops,
1158};
1159
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160/* ----------------------------------------------------------------------- */
1161
Jean Delvareaf294862008-05-18 20:49:40 +02001162/* This driver supports many devices and the idea is to let the driver
1163 detect which device is present. So rather than listing all supported
1164 devices here, we pretend to support a single, fake device type. */
1165static const struct i2c_device_id tuner_id[] = {
1166 { "tuner", }, /* autodetect */
1167 { }
1168};
1169MODULE_DEVICE_TABLE(i2c, tuner_id);
1170
Hans Verkuil02a20982010-09-15 15:36:23 -03001171static struct i2c_driver tuner_driver = {
1172 .driver = {
1173 .owner = THIS_MODULE,
1174 .name = "tuner",
1175 },
1176 .probe = tuner_probe,
1177 .remove = tuner_remove,
1178 .command = tuner_command,
1179 .suspend = tuner_suspend,
1180 .resume = tuner_resume,
1181 .id_table = tuner_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182};
1183
Hans Verkuil02a20982010-09-15 15:36:23 -03001184static __init int init_tuner(void)
1185{
1186 return i2c_add_driver(&tuner_driver);
1187}
1188
1189static __exit void exit_tuner(void)
1190{
1191 i2c_del_driver(&tuner_driver);
1192}
1193
1194module_init(init_tuner);
1195module_exit(exit_tuner);
1196
Mauro Carvalho Chehab9f3f71e2011-02-03 23:32:07 -03001197MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
1198MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
1199MODULE_LICENSE("GPL");