blob: 912d8e87658fca3ad56c567f337eab315392a63a [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
Michael Krufkya07c8772008-04-29 03:54:19 -030037/** This macro allows us to probe dynamically, avoiding static links */
Mauro Carvalho Chehabff138172008-04-29 23:02:33 -030038#ifdef CONFIG_MEDIA_ATTACH
Michael Krufkya07c8772008-04-29 03:54:19 -030039#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
40 int __r = -EINVAL; \
41 typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
42 if (__a) { \
43 __r = (int) __a(ARGS); \
Andrew Mortona1355e52008-04-30 11:40:17 -030044 symbol_put(FUNCTION); \
Michael Krufkya07c8772008-04-29 03:54:19 -030045 } else { \
46 printk(KERN_ERR "TUNER: Unable to find " \
47 "symbol "#FUNCTION"()\n"); \
48 } \
Michael Krufkya07c8772008-04-29 03:54:19 -030049 __r; \
50})
51
52static void tuner_detach(struct dvb_frontend *fe)
53{
54 if (fe->ops.tuner_ops.release) {
55 fe->ops.tuner_ops.release(fe);
56 symbol_put_addr(fe->ops.tuner_ops.release);
57 }
58 if (fe->ops.analog_ops.release) {
59 fe->ops.analog_ops.release(fe);
60 symbol_put_addr(fe->ops.analog_ops.release);
61 }
62}
63#else
64#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
65 FUNCTION(ARGS); \
66})
67
68static void tuner_detach(struct dvb_frontend *fe)
69{
70 if (fe->ops.tuner_ops.release)
71 fe->ops.tuner_ops.release(fe);
72 if (fe->ops.analog_ops.release)
73 fe->ops.analog_ops.release(fe);
74}
75#endif
76
Michael Krufkyf7f427e2007-12-16 22:02:26 -030077struct tuner {
78 /* device */
79 struct dvb_frontend fe;
80 struct i2c_client *i2c;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -030081 struct v4l2_subdev sd;
Michael Krufkyf7f427e2007-12-16 22:02:26 -030082 struct list_head list;
Michael Krufkyf7f427e2007-12-16 22:02:26 -030083
84 /* keep track of the current settings */
85 v4l2_std_id std;
86 unsigned int tv_freq;
87 unsigned int radio_freq;
88 unsigned int audmode;
89
90 unsigned int mode;
91 unsigned int mode_mask; /* Combination of allowable modes */
92
93 unsigned int type; /* chip type id */
94 unsigned int config;
Michael Krufky7271e602008-05-26 16:08:40 +020095 const char *name;
Michael Krufkyf7f427e2007-12-16 22:02:26 -030096};
97
Hans Verkuile8a4a9e2008-11-24 18:21:40 -030098static inline struct tuner *to_tuner(struct v4l2_subdev *sd)
99{
100 return container_of(sd, struct tuner, sd);
101}
102
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104/* insmod options used at init time => read/only */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300105static unsigned int addr;
106static unsigned int no_autodetect;
107static unsigned int show_i2c;
Mauro Carvalho Chehabfd3113e2005-07-31 22:34:43 -0700108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109/* insmod options used at runtime => read/write */
Michael Krufkyab166052007-12-09 02:26:48 -0300110static int tuner_debug;
111
112#define tuner_warn(fmt, arg...) do { \
113 printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \
114 i2c_adapter_id(t->i2c->adapter), \
115 t->i2c->addr, ##arg); \
116 } while (0)
117
118#define tuner_info(fmt, arg...) do { \
119 printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \
120 i2c_adapter_id(t->i2c->adapter), \
121 t->i2c->addr, ##arg); \
122 } while (0)
123
124#define tuner_err(fmt, arg...) do { \
125 printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \
126 i2c_adapter_id(t->i2c->adapter), \
127 t->i2c->addr, ##arg); \
128 } while (0)
129
130#define tuner_dbg(fmt, arg...) do { \
131 if (tuner_debug) \
132 printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \
133 i2c_adapter_id(t->i2c->adapter), \
134 t->i2c->addr, ##arg); \
135 } while (0)
136
137/* ------------------------------------------------------------------------ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700139static unsigned int tv_range[2] = { 44, 958 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140static unsigned int radio_range[2] = { 65, 108 };
141
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200142static char pal[] = "--";
143static char secam[] = "--";
144static char ntsc[] = "-";
145
Hans Verkuilf9195de2006-01-11 19:01:01 -0200146
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200147module_param(addr, int, 0444);
148module_param(no_autodetect, int, 0444);
149module_param(show_i2c, int, 0444);
Hans Verkuilf9195de2006-01-11 19:01:01 -0200150module_param_named(debug,tuner_debug, int, 0644);
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200151module_param_string(pal, pal, sizeof(pal), 0644);
152module_param_string(secam, secam, sizeof(secam), 0644);
153module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700154module_param_array(tv_range, int, NULL, 0644);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155module_param_array(radio_range, int, NULL, 0644);
156
157MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
158MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
159MODULE_LICENSE("GPL");
160
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161/* ---------------------------------------------------------------------- */
162
Michael Krufkyc7919d52007-12-08 17:06:30 -0300163static void fe_set_params(struct dvb_frontend *fe,
164 struct analog_parameters *params)
Michael Krufkye18f9442007-08-21 01:25:48 -0300165{
Michael Krufky4e9154b2007-10-21 19:39:50 -0300166 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
167 struct tuner *t = fe->analog_demod_priv;
Michael Krufkye18f9442007-08-21 01:25:48 -0300168
Michael Krufkye18f9442007-08-21 01:25:48 -0300169 if (NULL == fe_tuner_ops->set_analog_params) {
170 tuner_warn("Tuner frontend module has no way to set freq\n");
171 return;
172 }
Michael Krufkyc7919d52007-12-08 17:06:30 -0300173 fe_tuner_ops->set_analog_params(fe, params);
Michael Krufkye18f9442007-08-21 01:25:48 -0300174}
175
Michael Krufky4e9154b2007-10-21 19:39:50 -0300176static void fe_standby(struct dvb_frontend *fe)
Michael Krufkye18f9442007-08-21 01:25:48 -0300177{
Michael Krufky4e9154b2007-10-21 19:39:50 -0300178 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
Michael Krufkye18f9442007-08-21 01:25:48 -0300179
180 if (fe_tuner_ops->sleep)
Michael Krufky4e9154b2007-10-21 19:39:50 -0300181 fe_tuner_ops->sleep(fe);
Michael Krufkye18f9442007-08-21 01:25:48 -0300182}
183
Michael Krufky4e9154b2007-10-21 19:39:50 -0300184static int fe_has_signal(struct dvb_frontend *fe)
Michael Krufky1f5ef192007-08-31 17:38:02 -0300185{
Michael Krufky14196832007-10-14 18:11:53 -0300186 u16 strength = 0;
Michael Krufky1f5ef192007-08-31 17:38:02 -0300187
Michael Krufky4e9154b2007-10-21 19:39:50 -0300188 if (fe->ops.tuner_ops.get_rf_strength)
189 fe->ops.tuner_ops.get_rf_strength(fe, &strength);
Michael Krufky1f5ef192007-08-31 17:38:02 -0300190
191 return strength;
192}
193
Michael Krufkyf1c9a282007-12-16 19:27:23 -0300194static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg)
195{
196 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
197 struct tuner *t = fe->analog_demod_priv;
198
199 if (fe_tuner_ops->set_config)
200 return fe_tuner_ops->set_config(fe, priv_cfg);
201
202 tuner_warn("Tuner frontend module has no way to set config\n");
203
204 return 0;
205}
206
Michael Krufky4e9154b2007-10-21 19:39:50 -0300207static void tuner_status(struct dvb_frontend *fe);
Michael Krufky1dde7a42007-10-21 13:40:56 -0300208
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300209static struct analog_demod_ops tuner_analog_ops = {
Michael Krufkyc7919d52007-12-08 17:06:30 -0300210 .set_params = fe_set_params,
Michael Krufky1dde7a42007-10-21 13:40:56 -0300211 .standby = fe_standby,
Michael Krufky1dde7a42007-10-21 13:40:56 -0300212 .has_signal = fe_has_signal,
Michael Krufkyf1c9a282007-12-16 19:27:23 -0300213 .set_config = fe_set_config,
Michael Krufky1dde7a42007-10-21 13:40:56 -0300214 .tuner_status = tuner_status
215};
216
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700217/* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218static void set_tv_freq(struct i2c_client *c, unsigned int freq)
219{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300220 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300221 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
Michael Krufkyc7919d52007-12-08 17:06:30 -0300223 struct analog_parameters params = {
224 .mode = t->mode,
225 .audmode = t->audmode,
226 .std = t->std
227 };
228
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 if (t->type == UNSET) {
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700230 tuner_warn ("tuner type not set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 return;
232 }
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300233 if (NULL == analog_ops->set_params) {
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700234 tuner_warn ("Tuner has no way to set tv freq\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 return;
236 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700237 if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
238 tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n",
239 freq / 16, freq % 16 * 100 / 16, tv_range[0],
240 tv_range[1]);
Hans Verkuil27487d42006-01-15 15:04:52 -0200241 /* V4L2 spec: if the freq is not possible then the closest
242 possible value should be selected */
243 if (freq < tv_range[0] * 16)
244 freq = tv_range[0] * 16;
245 else
246 freq = tv_range[1] * 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 }
Michael Krufkyc7919d52007-12-08 17:06:30 -0300248 params.frequency = freq;
249
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300250 analog_ops->set_params(&t->fe, &params);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251}
252
253static void set_radio_freq(struct i2c_client *c, unsigned int freq)
254{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300255 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300256 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
Michael Krufkyc7919d52007-12-08 17:06:30 -0300258 struct analog_parameters params = {
259 .mode = t->mode,
260 .audmode = t->audmode,
261 .std = t->std
262 };
263
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 if (t->type == UNSET) {
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700265 tuner_warn ("tuner type not set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 return;
267 }
Mauro Carvalho Chehabe545d6e2008-01-05 16:37:04 -0300268 if (NULL == analog_ops->set_params) {
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700269 tuner_warn ("tuner has no way to set radio frequency\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 return;
271 }
Hans Verkuil27487d42006-01-15 15:04:52 -0200272 if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700273 tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n",
274 freq / 16000, freq % 16000 * 100 / 16000,
275 radio_range[0], radio_range[1]);
Hans Verkuil27487d42006-01-15 15:04:52 -0200276 /* V4L2 spec: if the freq is not possible then the closest
277 possible value should be selected */
278 if (freq < radio_range[0] * 16000)
279 freq = radio_range[0] * 16000;
280 else
281 freq = radio_range[1] * 16000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 }
Michael Krufkyc7919d52007-12-08 17:06:30 -0300283 params.frequency = freq;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700284
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300285 analog_ops->set_params(&t->fe, &params);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286}
287
288static void set_freq(struct i2c_client *c, unsigned long freq)
289{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300290 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
292 switch (t->mode) {
293 case V4L2_TUNER_RADIO:
294 tuner_dbg("radio freq set to %lu.%02lu\n",
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700295 freq / 16000, freq % 16000 * 100 / 16000);
296 set_radio_freq(c, freq);
Hans Verkuil27487d42006-01-15 15:04:52 -0200297 t->radio_freq = freq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 break;
299 case V4L2_TUNER_ANALOG_TV:
300 case V4L2_TUNER_DIGITAL_TV:
301 tuner_dbg("tv freq set to %lu.%02lu\n",
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700302 freq / 16, freq % 16 * 100 / 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 set_tv_freq(c, freq);
Hans Verkuil27487d42006-01-15 15:04:52 -0200304 t->tv_freq = freq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 break;
Mauro Carvalho Chehab6cb45872007-10-02 11:57:03 -0300306 default:
307 tuner_dbg("freq set: unknown mode: 0x%04x!\n",t->mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309}
310
Steven Toth27c685a2008-01-05 16:50:14 -0300311static struct xc5000_config xc5000_cfg;
312
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700313static void set_type(struct i2c_client *c, unsigned int type,
Hartmut Hackmannde956c12007-04-27 12:31:12 -0300314 unsigned int new_mode_mask, unsigned int new_config,
Michael Krufkyd7cba042008-09-12 13:31:45 -0300315 int (*tuner_callback) (void *dev, int component, int cmd, int arg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300317 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Michael Krufkye18f9442007-08-21 01:25:48 -0300318 struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300319 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700320 unsigned char buffer[4];
Michael Krufkyd6eef492009-10-24 16:42:16 -0300321 int tune_now = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700323 if (type == UNSET || type == TUNER_ABSENT) {
324 tuner_dbg ("tuner 0x%02x: Tuner type absent\n",c->addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 return;
326 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 t->type = type;
Michael Krufkye7ddcd92009-03-28 15:35:26 -0300329 /* prevent invalid config values */
Roel Kluinf14a2972009-10-23 07:59:42 -0300330 t->config = new_config < 256 ? new_config : 0;
Hartmut Hackmanncfeb8832007-04-27 12:31:17 -0300331 if (tuner_callback != NULL) {
332 tuner_dbg("defining GPIO callback\n");
Michael Krufkyd7cba042008-09-12 13:31:45 -0300333 t->fe.callback = tuner_callback;
Hartmut Hackmanncfeb8832007-04-27 12:31:17 -0300334 }
Hartmut Hackmann80f90fb2007-04-27 12:31:18 -0300335
Mauro Carvalho Chehab48aa3362007-10-29 11:33:18 -0300336 if (t->mode == T_UNINITIALIZED) {
Hartmut Hackmann80f90fb2007-04-27 12:31:18 -0300337 tuner_dbg ("tuner 0x%02x: called during i2c_client register by adapter's attach_inform\n", c->addr);
338
339 return;
340 }
341
Michael Krufkyb2083192007-05-29 22:54:06 -0300342 /* discard private data, in case set_type() was previously called */
Michael Krufkya07c8772008-04-29 03:54:19 -0300343 tuner_detach(&t->fe);
344 t->fe.analog_demod_priv = NULL;
Michael Krufkybe2b85a2007-06-04 14:40:27 -0300345
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 switch (t->type) {
347 case TUNER_MT2032:
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300348 if (!dvb_attach(microtune_attach,
349 &t->fe, t->i2c->adapter, t->i2c->addr))
350 goto attach_failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 break;
352 case TUNER_PHILIPS_TDA8290:
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300353 {
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300354 struct tda829x_config cfg = {
355 .lna_cfg = t->config,
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300356 };
357 if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter,
358 t->i2c->addr, &cfg))
359 goto attach_failed;
Michael Krufky5bea1cd2007-10-22 09:56:38 -0300360 break;
361 }
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700362 case TUNER_TEA5767:
Michael Krufkya07c8772008-04-29 03:54:19 -0300363 if (!dvb_attach(tea5767_attach, &t->fe,
364 t->i2c->adapter, t->i2c->addr))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300365 goto attach_failed;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700366 t->mode_mask = T_RADIO;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700367 break;
Mauro Carvalho Chehab8573a9e2007-04-08 01:09:11 -0300368 case TUNER_TEA5761:
Michael Krufkya07c8772008-04-29 03:54:19 -0300369 if (!dvb_attach(tea5761_attach, &t->fe,
370 t->i2c->adapter, t->i2c->addr))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300371 goto attach_failed;
Mauro Carvalho Chehab8573a9e2007-04-08 01:09:11 -0300372 t->mode_mask = T_RADIO;
373 break;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700374 case TUNER_PHILIPS_FMD1216ME_MK3:
375 buffer[0] = 0x0b;
376 buffer[1] = 0xdc;
377 buffer[2] = 0x9c;
378 buffer[3] = 0x60;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700379 i2c_master_send(c, buffer, 4);
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700380 mdelay(1);
381 buffer[2] = 0x86;
382 buffer[3] = 0x54;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700383 i2c_master_send(c, buffer, 4);
Michael Krufkya07c8772008-04-29 03:54:19 -0300384 if (!dvb_attach(simple_tuner_attach, &t->fe,
385 t->i2c->adapter, t->i2c->addr, t->type))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300386 goto attach_failed;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700387 break;
Hartmut Hackmann93df3412005-11-08 21:36:31 -0800388 case TUNER_PHILIPS_TD1316:
389 buffer[0] = 0x0b;
390 buffer[1] = 0xdc;
391 buffer[2] = 0x86;
392 buffer[3] = 0xa4;
Michael Krufkya07c8772008-04-29 03:54:19 -0300393 i2c_master_send(c, buffer, 4);
394 if (!dvb_attach(simple_tuner_attach, &t->fe,
395 t->i2c->adapter, t->i2c->addr, t->type))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300396 goto attach_failed;
Markus Rechbergerac272ed2006-01-23 17:11:09 -0200397 break;
Mauro Carvalho Chehab690c5442007-10-29 11:33:18 -0300398 case TUNER_XC2028:
399 {
Michel Ludwiga37b4c92007-11-16 07:46:14 -0300400 struct xc2028_config cfg = {
401 .i2c_adap = t->i2c->adapter,
402 .i2c_addr = t->i2c->addr,
Michel Ludwiga37b4c92007-11-16 07:46:14 -0300403 };
Michael Krufkya07c8772008-04-29 03:54:19 -0300404 if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300405 goto attach_failed;
Michael Krufkyd6eef492009-10-24 16:42:16 -0300406 tune_now = 0;
Mauro Carvalho Chehab690c5442007-10-29 11:33:18 -0300407 break;
408 }
Mauro Carvalho Chehab15396232006-06-23 16:13:56 -0300409 case TUNER_TDA9887:
Mauro Carvalho Chehab09fee5f2008-04-30 15:29:57 -0300410 if (!dvb_attach(tda9887_attach,
411 &t->fe, t->i2c->adapter, t->i2c->addr))
412 goto attach_failed;
Mauro Carvalho Chehab15396232006-06-23 16:13:56 -0300413 break;
Steven Toth27c685a2008-01-05 16:50:14 -0300414 case TUNER_XC5000:
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300415 {
Steven Toth27c685a2008-01-05 16:50:14 -0300416 xc5000_cfg.i2c_address = t->i2c->addr;
Devin Heitmuellerea227862009-03-11 02:58:53 -0300417 /* if_khz will be set when the digital dvb_attach() occurs */
418 xc5000_cfg.if_khz = 0;
Michael Krufkya07c8772008-04-29 03:54:19 -0300419 if (!dvb_attach(xc5000_attach,
Michael Krufky30650962008-09-06 14:56:58 -0300420 &t->fe, t->i2c->adapter, &xc5000_cfg))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300421 goto attach_failed;
Michael Krufkyd6eef492009-10-24 16:42:16 -0300422 tune_now = 0;
Steven Toth27c685a2008-01-05 16:50:14 -0300423 break;
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300424 }
Michael Krufky93463892009-09-15 23:04:18 -0300425 case TUNER_NXP_TDA18271:
426 {
427 struct tda18271_config cfg = {
428 .config = t->config,
Mauro Carvalho Chehabe350d442010-09-26 22:58:28 -0300429 .small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
Michael Krufky93463892009-09-15 23:04:18 -0300430 };
431
432 if (!dvb_attach(tda18271_attach, &t->fe, t->i2c->addr,
433 t->i2c->adapter, &cfg))
434 goto attach_failed;
Michael Krufkyd6eef492009-10-24 16:42:16 -0300435 tune_now = 0;
Michael Krufky93463892009-09-15 23:04:18 -0300436 break;
437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 default:
Michael Krufkya07c8772008-04-29 03:54:19 -0300439 if (!dvb_attach(simple_tuner_attach, &t->fe,
440 t->i2c->adapter, t->i2c->addr, t->type))
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300441 goto attach_failed;
442
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 break;
444 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700445
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300446 if ((NULL == analog_ops->set_params) &&
Michael Krufky1dde7a42007-10-21 13:40:56 -0300447 (fe_tuner_ops->set_analog_params)) {
Michael Krufkya07c8772008-04-29 03:54:19 -0300448
Michael Krufky7271e602008-05-26 16:08:40 +0200449 t->name = fe_tuner_ops->info.name;
Michael Krufkye18f9442007-08-21 01:25:48 -0300450
Michael Krufky4e9154b2007-10-21 19:39:50 -0300451 t->fe.analog_demod_priv = t;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300452 memcpy(analog_ops, &tuner_analog_ops,
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300453 sizeof(struct analog_demod_ops));
Michael Krufkya07c8772008-04-29 03:54:19 -0300454
Michael Krufkya55db8c2007-12-09 13:52:51 -0300455 } else {
Michael Krufky7271e602008-05-26 16:08:40 +0200456 t->name = analog_ops->info.name;
Michael Krufkye18f9442007-08-21 01:25:48 -0300457 }
458
Michael Krufky7271e602008-05-26 16:08:40 +0200459 tuner_dbg("type set to %s\n", t->name);
Michael Krufkye18f9442007-08-21 01:25:48 -0300460
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700461 if (t->mode_mask == T_UNINITIALIZED)
462 t->mode_mask = new_mode_mask;
463
Michael Krufkyd6eef492009-10-24 16:42:16 -0300464 /* Some tuners require more initialization setup before use,
465 such as firmware download or device calibration.
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300466 trying to set a frequency here will just fail
467 FIXME: better to move set_freq to the tuner code. This is needed
468 on analog tuners for PLL to properly work
469 */
Michael Krufkyd6eef492009-10-24 16:42:16 -0300470 if (tune_now)
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300471 set_freq(c, (V4L2_TUNER_RADIO == t->mode) ?
472 t->radio_freq : t->tv_freq);
473
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700474 tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
Laurent Riffard604f28e2005-11-26 20:43:39 +0100475 c->adapter->name, c->driver->driver.name, c->addr << 1, type,
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700476 t->mode_mask);
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300477 return;
478
479attach_failed:
480 tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
481 t->type = TUNER_ABSENT;
482 t->mode_mask = T_UNINITIALIZED;
483
484 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485}
486
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700487/*
488 * This function apply tuner config to tuner specified
489 * by tun_setup structure. I addr is unset, then admin status
490 * and tun addr status is more precise then current status,
491 * it's applied. Otherwise status and type are applied only to
492 * tuner with exactly the same addr.
493*/
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700494
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700495static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700496{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300497 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700498
Hartmut Hackmannde956c12007-04-27 12:31:12 -0300499 if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
500 (t->mode_mask & tun_setup->mode_mask))) ||
501 (tun_setup->addr == c->addr)) {
502 set_type(c, tun_setup->type, tun_setup->mode_mask,
Hartmut Hackmanncfeb8832007-04-27 12:31:17 -0300503 tun_setup->config, tun_setup->tuner_callback);
Mauro Carvalho Chehabb9ef6bb2008-04-26 11:29:34 -0300504 } else
505 tuner_dbg("set addr discarded for type %i, mask %x. "
506 "Asked to change tuner at addr 0x%02x, with mask %x\n",
507 t->type, t->mode_mask,
508 tun_setup->addr, tun_setup->mode_mask);
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700509}
510
511static inline int check_mode(struct tuner *t, char *cmd)
512{
Mauro Carvalho Chehab793cf9e2005-09-09 13:03:37 -0700513 if ((1 << t->mode & t->mode_mask) == 0) {
Marcin Slusarz4d3437d2008-05-26 14:03:02 -0300514 return -EINVAL;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700515 }
Mauro Carvalho Chehab793cf9e2005-09-09 13:03:37 -0700516
517 switch (t->mode) {
518 case V4L2_TUNER_RADIO:
519 tuner_dbg("Cmd %s accepted for radio\n", cmd);
520 break;
521 case V4L2_TUNER_ANALOG_TV:
522 tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
523 break;
524 case V4L2_TUNER_DIGITAL_TV:
525 tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
526 break;
527 }
528 return 0;
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700529}
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700530
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700531/* get more precise norm info from insmod option */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532static int tuner_fixup_std(struct tuner *t)
533{
534 if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 switch (pal[0]) {
Hans Verkuile71ced12006-12-11 15:51:43 -0300536 case '6':
537 tuner_dbg ("insmod fixup: PAL => PAL-60\n");
538 t->std = V4L2_STD_PAL_60;
539 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 case 'b':
541 case 'B':
542 case 'g':
543 case 'G':
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700544 tuner_dbg ("insmod fixup: PAL => PAL-BG\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 t->std = V4L2_STD_PAL_BG;
546 break;
547 case 'i':
548 case 'I':
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700549 tuner_dbg ("insmod fixup: PAL => PAL-I\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 t->std = V4L2_STD_PAL_I;
551 break;
552 case 'd':
553 case 'D':
554 case 'k':
555 case 'K':
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700556 tuner_dbg ("insmod fixup: PAL => PAL-DK\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 t->std = V4L2_STD_PAL_DK;
558 break;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700559 case 'M':
560 case 'm':
561 tuner_dbg ("insmod fixup: PAL => PAL-M\n");
562 t->std = V4L2_STD_PAL_M;
563 break;
564 case 'N':
565 case 'n':
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200566 if (pal[1] == 'c' || pal[1] == 'C') {
567 tuner_dbg("insmod fixup: PAL => PAL-Nc\n");
568 t->std = V4L2_STD_PAL_Nc;
569 } else {
570 tuner_dbg ("insmod fixup: PAL => PAL-N\n");
571 t->std = V4L2_STD_PAL_N;
572 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700573 break;
Mauro Carvalho Chehab21d4df32005-09-09 13:03:59 -0700574 case '-':
575 /* default parameter, do nothing */
576 break;
577 default:
578 tuner_warn ("pal= argument not recognised\n");
579 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 }
581 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700582 if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
583 switch (secam[0]) {
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200584 case 'b':
585 case 'B':
586 case 'g':
587 case 'G':
588 case 'h':
589 case 'H':
590 tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n");
591 t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
592 break;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700593 case 'd':
594 case 'D':
595 case 'k':
596 case 'K':
597 tuner_dbg ("insmod fixup: SECAM => SECAM-DK\n");
598 t->std = V4L2_STD_SECAM_DK;
599 break;
600 case 'l':
601 case 'L':
Mauro Carvalho Chehab800d3c62005-11-13 16:07:48 -0800602 if ((secam[1]=='C')||(secam[1]=='c')) {
603 tuner_dbg ("insmod fixup: SECAM => SECAM-L'\n");
604 t->std = V4L2_STD_SECAM_LC;
605 } else {
606 tuner_dbg ("insmod fixup: SECAM => SECAM-L\n");
607 t->std = V4L2_STD_SECAM_L;
608 }
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700609 break;
Mauro Carvalho Chehab21d4df32005-09-09 13:03:59 -0700610 case '-':
611 /* default parameter, do nothing */
612 break;
613 default:
614 tuner_warn ("secam= argument not recognised\n");
615 break;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700616 }
617 }
618
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200619 if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
620 switch (ntsc[0]) {
621 case 'm':
622 case 'M':
623 tuner_dbg("insmod fixup: NTSC => NTSC-M\n");
624 t->std = V4L2_STD_NTSC_M;
625 break;
626 case 'j':
627 case 'J':
628 tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
629 t->std = V4L2_STD_NTSC_M_JP;
630 break;
Hans Verkuild97a11e2006-02-07 06:48:40 -0200631 case 'k':
632 case 'K':
633 tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
634 t->std = V4L2_STD_NTSC_M_KR;
635 break;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200636 case '-':
637 /* default parameter, do nothing */
638 break;
639 default:
640 tuner_info("ntsc= argument not recognised\n");
641 break;
642 }
643 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 return 0;
645}
646
Michael Krufky4e9154b2007-10-21 19:39:50 -0300647static void tuner_status(struct dvb_frontend *fe)
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200648{
Michael Krufky4e9154b2007-10-21 19:39:50 -0300649 struct tuner *t = fe->analog_demod_priv;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200650 unsigned long freq, freq_fraction;
Michael Krufkya07c8772008-04-29 03:54:19 -0300651 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
652 struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200653 const char *p;
654
655 switch (t->mode) {
656 case V4L2_TUNER_RADIO: p = "radio"; break;
657 case V4L2_TUNER_ANALOG_TV: p = "analog TV"; break;
658 case V4L2_TUNER_DIGITAL_TV: p = "digital TV"; break;
659 default: p = "undefined"; break;
660 }
661 if (t->mode == V4L2_TUNER_RADIO) {
Hans Verkuil27487d42006-01-15 15:04:52 -0200662 freq = t->radio_freq / 16000;
663 freq_fraction = (t->radio_freq % 16000) * 100 / 16000;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200664 } else {
Hans Verkuil27487d42006-01-15 15:04:52 -0200665 freq = t->tv_freq / 16;
666 freq_fraction = (t->tv_freq % 16) * 100 / 16;
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200667 }
668 tuner_info("Tuner mode: %s\n", p);
669 tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
Mauro Carvalho Chehab4ae5c2e2006-03-25 15:53:38 -0300670 tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std);
Hans Verkuil8a4b2752006-01-23 17:11:09 -0200671 if (t->mode != V4L2_TUNER_RADIO)
672 return;
Michael Krufkye18f9442007-08-21 01:25:48 -0300673 if (fe_tuner_ops->get_status) {
674 u32 tuner_status;
675
676 fe_tuner_ops->get_status(&t->fe, &tuner_status);
677 if (tuner_status & TUNER_STATUS_LOCKED)
678 tuner_info("Tuner is locked.\n");
679 if (tuner_status & TUNER_STATUS_STEREO)
680 tuner_info("Stereo: yes\n");
681 }
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300682 if (analog_ops->has_signal)
683 tuner_info("Signal strength: %d\n",
684 analog_ops->has_signal(fe));
Mauro Carvalho Chehab7e578192006-01-09 15:25:27 -0200685}
Hans Verkuil8a4b2752006-01-23 17:11:09 -0200686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687/* ---------------------------------------------------------------------- */
688
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700689/*
690 * Switch tuner to other mode. If tuner support both tv and radio,
691 * set another frequency to some value (This is needed for some pal
692 * tuners to avoid locking). Otherwise, just put second tuner in
693 * standby mode.
694 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700696static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd)
697{
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300698 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Michael Krufky1dde7a42007-10-21 13:40:56 -0300699
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800700 if (mode == t->mode)
701 return 0;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700702
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800703 t->mode = mode;
Mauro Carvalho Chehab793cf9e2005-09-09 13:03:37 -0700704
Marcin Slusarz4d3437d2008-05-26 14:03:02 -0300705 if (check_mode(t, cmd) == -EINVAL) {
Mauro Carvalho Chehab16a5e532008-12-20 07:17:10 -0300706 tuner_dbg("Tuner doesn't support this mode. "
707 "Putting tuner to sleep\n");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800708 t->mode = T_STANDBY;
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300709 if (analog_ops->standby)
710 analog_ops->standby(&t->fe);
Marcin Slusarz4d3437d2008-05-26 14:03:02 -0300711 return -EINVAL;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800712 }
713 return 0;
Mauro Carvalho Chehabf7ce3cc2005-07-12 13:58:55 -0700714}
715
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300716static int tuner_s_type_addr(struct v4l2_subdev *sd, struct tuner_setup *type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300718 struct tuner *t = to_tuner(sd);
719 struct i2c_client *client = v4l2_get_subdevdata(sd);
720
721 tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=0x%02x\n",
722 type->type,
723 type->addr,
724 type->mode_mask,
725 type->config);
726
727 set_addr(client, type);
728 return 0;
729}
730
731static int tuner_s_radio(struct v4l2_subdev *sd)
732{
733 struct tuner *t = to_tuner(sd);
734 struct i2c_client *client = v4l2_get_subdevdata(sd);
735
Hans Verkuilbccfa442009-03-30 06:55:27 -0300736 if (set_mode(client, t, V4L2_TUNER_RADIO, "s_radio") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300737 return 0;
738 if (t->radio_freq)
739 set_freq(client, t->radio_freq);
740 return 0;
741}
742
Laurent Pinchart622b8282009-10-05 10:48:17 -0300743static int tuner_s_power(struct v4l2_subdev *sd, int on)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300744{
745 struct tuner *t = to_tuner(sd);
Michael Krufkybc3e5c72007-12-21 11:18:32 -0300746 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Laurent Pinchart622b8282009-10-05 10:48:17 -0300748 if (on)
749 return 0;
750
Mauro Carvalho Chehab16a5e532008-12-20 07:17:10 -0300751 tuner_dbg("Putting tuner to sleep\n");
752
Laurent Pinchart622b8282009-10-05 10:48:17 -0300753 if (check_mode(t, "s_power") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300754 return 0;
755 t->mode = T_STANDBY;
756 if (analog_ops->standby)
757 analog_ops->standby(&t->fe);
758 return 0;
759}
760
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300761static int tuner_s_config(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *cfg)
762{
763 struct tuner *t = to_tuner(sd);
764 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
Mauro Carvalho Chehab7f171122007-10-18 19:56:47 -0300765
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300766 if (t->type != cfg->tuner)
767 return 0;
Mauro Carvalho Chehab7f171122007-10-18 19:56:47 -0300768
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300769 if (analog_ops->set_config) {
770 analog_ops->set_config(&t->fe, cfg->priv);
771 return 0;
Mauro Carvalho Chehab7f171122007-10-18 19:56:47 -0300772 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300774 tuner_dbg("Tuner frontend module has no way to set config\n");
775 return 0;
776}
Mauro Carvalho Chehab56fc08c2005-06-23 22:05:07 -0700777
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300778/* --- v4l ioctls --- */
779/* take care: bttv does userspace copying, we'll get a
780 kernel pointer here... */
781static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
782{
783 struct tuner *t = to_tuner(sd);
784 struct i2c_client *client = v4l2_get_subdevdata(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
Hans Verkuilbccfa442009-03-30 06:55:27 -0300786 if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "s_std") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300787 return 0;
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700788
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300789 t->std = std;
790 tuner_fixup_std(t);
791 if (t->tv_freq)
792 set_freq(client, t->tv_freq);
793 return 0;
794}
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700795
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300796static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
797{
798 struct tuner *t = to_tuner(sd);
799 struct i2c_client *client = v4l2_get_subdevdata(sd);
Michael Krufkye18f9442007-08-21 01:25:48 -0300800
Hans Verkuilbccfa442009-03-30 06:55:27 -0300801 if (set_mode(client, t, f->type, "s_frequency") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300802 return 0;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300803 set_freq(client, f->frequency);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
805 return 0;
806}
807
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300808static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
809{
810 struct tuner *t = to_tuner(sd);
811 struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
812
Hans Verkuilbccfa442009-03-30 06:55:27 -0300813 if (check_mode(t, "g_frequency") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300814 return 0;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300815 f->type = t->mode;
816 if (fe_tuner_ops->get_frequency) {
817 u32 abs_freq;
818
819 fe_tuner_ops->get_frequency(&t->fe, &abs_freq);
820 f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
Julia Lawall75b697f2009-08-01 16:48:41 -0300821 DIV_ROUND_CLOSEST(abs_freq * 2, 125) :
822 DIV_ROUND_CLOSEST(abs_freq, 62500);
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300823 return 0;
824 }
825 f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
826 t->radio_freq : t->tv_freq;
827 return 0;
828}
829
830static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
831{
832 struct tuner *t = to_tuner(sd);
833 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
834 struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
835
Hans Verkuilbccfa442009-03-30 06:55:27 -0300836 if (check_mode(t, "g_tuner") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300837 return 0;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300838
839 vt->type = t->mode;
840 if (analog_ops->get_afc)
841 vt->afc = analog_ops->get_afc(&t->fe);
842 if (t->mode == V4L2_TUNER_ANALOG_TV)
843 vt->capability |= V4L2_TUNER_CAP_NORM;
844 if (t->mode != V4L2_TUNER_RADIO) {
845 vt->rangelow = tv_range[0] * 16;
846 vt->rangehigh = tv_range[1] * 16;
847 return 0;
848 }
849
850 /* radio mode */
851 vt->rxsubchans =
852 V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
853 if (fe_tuner_ops->get_status) {
854 u32 tuner_status;
855
856 fe_tuner_ops->get_status(&t->fe, &tuner_status);
857 vt->rxsubchans =
858 (tuner_status & TUNER_STATUS_STEREO) ?
859 V4L2_TUNER_SUB_STEREO :
860 V4L2_TUNER_SUB_MONO;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300861 }
862 if (analog_ops->has_signal)
863 vt->signal = analog_ops->has_signal(&t->fe);
864 vt->capability |=
865 V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
866 vt->audmode = t->audmode;
867 vt->rangelow = radio_range[0] * 16000;
868 vt->rangehigh = radio_range[1] * 16000;
869 return 0;
870}
871
872static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
873{
874 struct tuner *t = to_tuner(sd);
875 struct i2c_client *client = v4l2_get_subdevdata(sd);
876
Hans Verkuilbccfa442009-03-30 06:55:27 -0300877 if (check_mode(t, "s_tuner") == -EINVAL)
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300878 return 0;
879
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300880 /* do nothing unless we're a radio tuner */
881 if (t->mode != V4L2_TUNER_RADIO)
882 return 0;
883 t->audmode = vt->audmode;
884 set_radio_freq(client, t->radio_freq);
885 return 0;
886}
887
888static int tuner_log_status(struct v4l2_subdev *sd)
889{
890 struct tuner *t = to_tuner(sd);
891 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
892
893 if (analog_ops->tuner_status)
894 analog_ops->tuner_status(&t->fe);
895 return 0;
896}
897
Jean Delvare21b48a72007-03-12 19:20:15 -0300898static int tuner_suspend(struct i2c_client *c, pm_message_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300900 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
Hans Verkuil9dd659d2007-11-04 11:03:36 -0300902 tuner_dbg("suspend\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 /* FIXME: power down ??? */
904 return 0;
905}
906
Jean Delvare21b48a72007-03-12 19:20:15 -0300907static int tuner_resume(struct i2c_client *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300909 struct tuner *t = to_tuner(i2c_get_clientdata(c));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910
Hans Verkuil9dd659d2007-11-04 11:03:36 -0300911 tuner_dbg("resume\n");
Hans Verkuil27487d42006-01-15 15:04:52 -0200912 if (V4L2_TUNER_RADIO == t->mode) {
913 if (t->radio_freq)
914 set_freq(c, t->radio_freq);
915 } else {
916 if (t->tv_freq)
917 set_freq(c, t->tv_freq);
918 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 return 0;
920}
921
Hans Verkuil75b4c262009-04-01 03:32:22 -0300922static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg)
923{
924 struct v4l2_subdev *sd = i2c_get_clientdata(client);
925
926 /* TUNER_SET_CONFIG is still called by tuner-simple.c, so we have
927 to handle it here.
928 There must be a better way of doing this... */
929 switch (cmd) {
930 case TUNER_SET_CONFIG:
931 return tuner_s_config(sd, arg);
932 }
933 return -ENOIOCTLCMD;
934}
935
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300936/* ----------------------------------------------------------------------- */
937
938static const struct v4l2_subdev_core_ops tuner_core_ops = {
939 .log_status = tuner_log_status,
Hans Verkuilf41737e2009-04-01 03:52:39 -0300940 .s_std = tuner_s_std,
Laurent Pinchart622b8282009-10-05 10:48:17 -0300941 .s_power = tuner_s_power,
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300942};
943
944static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = {
Hans Verkuile8a4a9e2008-11-24 18:21:40 -0300945 .s_radio = tuner_s_radio,
946 .g_tuner = tuner_g_tuner,
947 .s_tuner = tuner_s_tuner,
948 .s_frequency = tuner_s_frequency,
949 .g_frequency = tuner_g_frequency,
950 .s_type_addr = tuner_s_type_addr,
951 .s_config = tuner_s_config,
952};
953
954static const struct v4l2_subdev_ops tuner_ops = {
955 .core = &tuner_core_ops,
956 .tuner = &tuner_tuner_ops,
957};
958
Hans Verkuil92de1f12007-11-04 10:53:09 -0300959/* ---------------------------------------------------------------------- */
960
Adrian Bunkc52c4d02008-01-28 22:11:15 -0300961static LIST_HEAD(tuner_list);
Hans Verkuil92de1f12007-11-04 10:53:09 -0300962
963/* Search for existing radio and/or TV tuners on the given I2C adapter.
Hans Verkuil9dd659d2007-11-04 11:03:36 -0300964 Note that when this function is called from tuner_probe you can be
Hans Verkuil92de1f12007-11-04 10:53:09 -0300965 certain no other devices will be added/deleted at the same time, I2C
966 core protects against that. */
967static void tuner_lookup(struct i2c_adapter *adap,
968 struct tuner **radio, struct tuner **tv)
969{
970 struct tuner *pos;
971
972 *radio = NULL;
973 *tv = NULL;
974
975 list_for_each_entry(pos, &tuner_list, list) {
976 int mode_mask;
977
978 if (pos->i2c->adapter != adap ||
Hans Verkuil0c846742009-03-29 19:40:01 -0300979 strcmp(pos->i2c->driver->driver.name, "tuner"))
Hans Verkuil92de1f12007-11-04 10:53:09 -0300980 continue;
981
982 mode_mask = pos->mode_mask & ~T_STANDBY;
983 if (*radio == NULL && mode_mask == T_RADIO)
984 *radio = pos;
985 /* Note: currently TDA9887 is the only demod-only
986 device. If other devices appear then we need to
987 make this test more general. */
988 else if (*tv == NULL && pos->type != TUNER_TDA9887 &&
989 (pos->mode_mask & (T_ANALOG_TV | T_DIGITAL_TV)))
990 *tv = pos;
991 }
992}
993
994/* During client attach, set_type is called by adapter's attach_inform callback.
Hans Verkuil9dd659d2007-11-04 11:03:36 -0300995 set_type must then be completed by tuner_probe.
Hans Verkuil92de1f12007-11-04 10:53:09 -0300996 */
Jean Delvared2653e92008-04-29 23:11:39 +0200997static int tuner_probe(struct i2c_client *client,
998 const struct i2c_device_id *id)
Hans Verkuil92de1f12007-11-04 10:53:09 -0300999{
Hans Verkuil92de1f12007-11-04 10:53:09 -03001000 struct tuner *t;
1001 struct tuner *radio;
1002 struct tuner *tv;
1003
Hans Verkuil92de1f12007-11-04 10:53:09 -03001004 t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
Hans Verkuil9dd659d2007-11-04 11:03:36 -03001005 if (NULL == t)
Hans Verkuil92de1f12007-11-04 10:53:09 -03001006 return -ENOMEM;
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001007 v4l2_i2c_subdev_init(&t->sd, client, &tuner_ops);
Hans Verkuil92de1f12007-11-04 10:53:09 -03001008 t->i2c = client;
Michael Krufky7271e602008-05-26 16:08:40 +02001009 t->name = "(tuner unset)";
Hans Verkuil92de1f12007-11-04 10:53:09 -03001010 t->type = UNSET;
1011 t->audmode = V4L2_TUNER_MODE_STEREO;
1012 t->mode_mask = T_UNINITIALIZED;
1013
1014 if (show_i2c) {
1015 unsigned char buffer[16];
1016 int i, rc;
1017
1018 memset(buffer, 0, sizeof(buffer));
1019 rc = i2c_master_recv(client, buffer, sizeof(buffer));
1020 tuner_info("I2C RECV = ");
1021 for (i = 0; i < rc; i++)
1022 printk(KERN_CONT "%02x ", buffer[i]);
1023 printk("\n");
1024 }
Hans Verkuil92de1f12007-11-04 10:53:09 -03001025
1026 /* autodetection code based on the i2c addr */
1027 if (!no_autodetect) {
Hans Verkuil9dd659d2007-11-04 11:03:36 -03001028 switch (client->addr) {
Hans Verkuil92de1f12007-11-04 10:53:09 -03001029 case 0x10:
Michael Krufkya07c8772008-04-29 03:54:19 -03001030 if (tuner_symbol_probe(tea5761_autodetection,
1031 t->i2c->adapter,
1032 t->i2c->addr) >= 0) {
Hans Verkuil92de1f12007-11-04 10:53:09 -03001033 t->type = TUNER_TEA5761;
1034 t->mode_mask = T_RADIO;
1035 t->mode = T_STANDBY;
1036 /* Sets freq to FM range */
1037 t->radio_freq = 87.5 * 16000;
1038 tuner_lookup(t->i2c->adapter, &radio, &tv);
1039 if (tv)
1040 tv->mode_mask &= ~T_RADIO;
1041
1042 goto register_client;
1043 }
Jiri Slabya570fb62010-01-06 13:45:28 -03001044 kfree(t);
Mauro Carvalho Chehab867e8352008-04-23 17:27:27 -03001045 return -ENODEV;
Hans Verkuil92de1f12007-11-04 10:53:09 -03001046 case 0x42:
1047 case 0x43:
1048 case 0x4a:
1049 case 0x4b:
1050 /* If chip is not tda8290, don't register.
1051 since it can be tda9887*/
Michael Krufkya07c8772008-04-29 03:54:19 -03001052 if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
Mauro Carvalho Chehabb538d282008-04-30 15:45:00 -03001053 t->i2c->addr) >= 0) {
Hans Verkuil92de1f12007-11-04 10:53:09 -03001054 tuner_dbg("tda829x detected\n");
1055 } else {
1056 /* Default is being tda9887 */
1057 t->type = TUNER_TDA9887;
1058 t->mode_mask = T_RADIO | T_ANALOG_TV |
1059 T_DIGITAL_TV;
1060 t->mode = T_STANDBY;
1061 goto register_client;
1062 }
1063 break;
1064 case 0x60:
Michael Krufkya07c8772008-04-29 03:54:19 -03001065 if (tuner_symbol_probe(tea5767_autodetection,
1066 t->i2c->adapter, t->i2c->addr)
Mauro Carvalho Chehabb538d282008-04-30 15:45:00 -03001067 >= 0) {
Hans Verkuil92de1f12007-11-04 10:53:09 -03001068 t->type = TUNER_TEA5767;
1069 t->mode_mask = T_RADIO;
1070 t->mode = T_STANDBY;
1071 /* Sets freq to FM range */
1072 t->radio_freq = 87.5 * 16000;
1073 tuner_lookup(t->i2c->adapter, &radio, &tv);
1074 if (tv)
1075 tv->mode_mask &= ~T_RADIO;
1076
1077 goto register_client;
1078 }
1079 break;
1080 }
1081 }
1082
1083 /* Initializes only the first TV tuner on this adapter. Why only the
1084 first? Because there are some devices (notably the ones with TI
1085 tuners) that have more than one i2c address for the *same* device.
1086 Experience shows that, except for just one case, the first
1087 address is the right one. The exception is a Russian tuner
1088 (ACORP_Y878F). So, the desired behavior is just to enable the
1089 first found TV tuner. */
1090 tuner_lookup(t->i2c->adapter, &radio, &tv);
1091 if (tv == NULL) {
1092 t->mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
1093 if (radio == NULL)
1094 t->mode_mask |= T_RADIO;
1095 tuner_dbg("Setting mode_mask to 0x%02x\n", t->mode_mask);
1096 t->tv_freq = 400 * 16; /* Sets freq to VHF High */
1097 t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
1098 }
1099
1100 /* Should be just before return */
1101register_client:
Hans Verkuil9dd659d2007-11-04 11:03:36 -03001102 tuner_info("chip found @ 0x%x (%s)\n", client->addr << 1,
1103 client->adapter->name);
Hans Verkuil92de1f12007-11-04 10:53:09 -03001104
1105 /* Sets a default mode */
1106 if (t->mode_mask & T_ANALOG_TV) {
Michael Krufky864a6b82007-12-09 17:21:54 -03001107 t->mode = V4L2_TUNER_ANALOG_TV;
Hans Verkuil92de1f12007-11-04 10:53:09 -03001108 } else if (t->mode_mask & T_RADIO) {
Michael Krufky864a6b82007-12-09 17:21:54 -03001109 t->mode = V4L2_TUNER_RADIO;
Hans Verkuil92de1f12007-11-04 10:53:09 -03001110 } else {
Michael Krufky864a6b82007-12-09 17:21:54 -03001111 t->mode = V4L2_TUNER_DIGITAL_TV;
Hans Verkuil92de1f12007-11-04 10:53:09 -03001112 }
Michael Krufkyd7cba042008-09-12 13:31:45 -03001113 set_type(client, t->type, t->mode_mask, t->config, t->fe.callback);
Hans Verkuil9dd659d2007-11-04 11:03:36 -03001114 list_add_tail(&t->list, &tuner_list);
Hans Verkuil92de1f12007-11-04 10:53:09 -03001115 return 0;
1116}
1117
Hans Verkuil9dd659d2007-11-04 11:03:36 -03001118static int tuner_remove(struct i2c_client *client)
Hans Verkuil92de1f12007-11-04 10:53:09 -03001119{
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001120 struct tuner *t = to_tuner(i2c_get_clientdata(client));
Hans Verkuil92de1f12007-11-04 10:53:09 -03001121
Hans Verkuile8a4a9e2008-11-24 18:21:40 -03001122 v4l2_device_unregister_subdev(&t->sd);
Michael Krufkya07c8772008-04-29 03:54:19 -03001123 tuner_detach(&t->fe);
1124 t->fe.analog_demod_priv = NULL;
Hans Verkuil92de1f12007-11-04 10:53:09 -03001125
1126 list_del(&t->list);
1127 kfree(t);
Hans Verkuil92de1f12007-11-04 10:53:09 -03001128 return 0;
1129}
1130
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131/* ----------------------------------------------------------------------- */
1132
Jean Delvareaf294862008-05-18 20:49:40 +02001133/* This driver supports many devices and the idea is to let the driver
1134 detect which device is present. So rather than listing all supported
1135 devices here, we pretend to support a single, fake device type. */
1136static const struct i2c_device_id tuner_id[] = {
1137 { "tuner", }, /* autodetect */
1138 { }
1139};
1140MODULE_DEVICE_TABLE(i2c, tuner_id);
1141
Hans Verkuil02a20982010-09-15 15:36:23 -03001142static struct i2c_driver tuner_driver = {
1143 .driver = {
1144 .owner = THIS_MODULE,
1145 .name = "tuner",
1146 },
1147 .probe = tuner_probe,
1148 .remove = tuner_remove,
1149 .command = tuner_command,
1150 .suspend = tuner_suspend,
1151 .resume = tuner_resume,
1152 .id_table = tuner_id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153};
1154
Hans Verkuil02a20982010-09-15 15:36:23 -03001155static __init int init_tuner(void)
1156{
1157 return i2c_add_driver(&tuner_driver);
1158}
1159
1160static __exit void exit_tuner(void)
1161{
1162 i2c_del_driver(&tuner_driver);
1163}
1164
1165module_init(init_tuner);
1166module_exit(exit_tuner);
1167
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168/*
1169 * Overrides for Emacs so that we follow Linus's tabbing style.
1170 * ---------------------------------------------------------------------------
1171 * Local variables:
1172 * c-basic-offset: 8
1173 * End:
1174 */