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