2 * drivers/media/radio/radio-tea5761.c
4 * Copyright (C) 2005 Nokia Corporation
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <linux/module.h>
21 #include <linux/version.h>
22 #include <linux/init.h>
23 #include <linux/i2c.h>
24 #include <linux/delay.h>
25 #include <media/v4l2-common.h>
26 #include <asm/arch/gpio.h>
27 #include <asm/arch/board.h>
29 #define DRIVER_NAME "tea5761"
31 #define TEA5761_VERSION KERNEL_VERSION(0, 0, 1)
33 #define TEA5761_I2C_ADDR 0x10
35 #define TEA5761_MANID 0x002b
36 #define TEA5761_CHIPID 0x5761
38 #define TEA5761_INTREG_BLMSK 0x0001
39 #define TEA5761_INTREG_FRRMSK 0x0002
40 #define TEA5761_INTREG_LEVMSK 0x0008
41 #define TEA5761_INTREG_IFMSK 0x0010
42 #define TEA5761_INTREG_BLMFLAG 0x0100
43 #define TEA5761_INTREG_FRRFLAG 0x0200
44 #define TEA5761_INTREG_LEVFLAG 0x0800
45 #define TEA5761_INTREG_IFFLAG 0x1000
47 #define TEA5761_FRQSET_SUD 0x8000
48 #define TEA5761_FRQSET_SM 0x4000
50 #define TEA5761_TNCTRL_PUPD0 0x4000
51 #define TEA5761_TNCTRL_BLIM 0x2000
52 #define TEA5761_TNCTRL_SWPM 0x1000
53 #define TEA5761_TNCTRL_IFCTC 0x0800
54 #define TEA5761_TNCTRL_AFM 0x0400
55 #define TEA5761_TNCTRL_SMUTE 0x0200
56 #define TEA5761_TNCTRL_SNC 0x0100
57 #define TEA5761_TNCTRL_MU 0x0080
58 #define TEA5761_TNCTRL_SSL1 0x0040
59 #define TEA5761_TNCTRL_SSL0 0x0020
60 #define TEA5761_TNCTRL_HLSI 0x0010
61 #define TEA5761_TNCTRL_MST 0x0008
62 #define TEA5761_TNCTRL_SWP 0x0004
63 #define TEA5761_TNCTRL_DTC 0x0002
64 #define TEA5761_TNCTRL_AHLSI 0x0001
66 #define TEA5761_TUNCHK_LEVEL(x) (((x) & 0x00F0) >> 4)
67 #define TEA5761_TUNCHK_IFCNT(x) (((x) & 0xFE00) >> 9)
68 #define TEA5761_TUNCHK_TUNTO 0x0100
69 #define TEA5761_TUNCHK_LD 0x0008
70 #define TEA5761_TUNCHK_STEREO 0x0004
72 #define TEA5761_TESTREG_TRIGFR 0x0800
74 #define TEA5761_FREQ_LOW 87500
75 #define TEA5761_FREQ_HIGH 108000
77 /* Probe for TEA5761 twice since the version N4B seems to be
78 * broken and needs two probes to be found */
79 static unsigned short normal_i2c[] = {
80 TEA5761_I2C_ADDR, TEA5761_I2C_ADDR, I2C_CLIENT_END
94 } __attribute__ ((packed));
96 struct tea5761_write_regs {
101 } __attribute__ ((packed));
103 struct tea5761_device {
104 struct video_device *video_dev;
105 struct i2c_client *i2c_dev;
106 struct tea5761_regs regs;
111 static struct tea5761_device tea5761;
113 static struct i2c_driver tea5761_driver;
114 static int radio_nr = -1;
116 static int tea5761_read_regs(struct tea5761_device *tea)
119 u16 *p = (u16 *) &tea->regs;
120 struct i2c_client *client = tea->i2c_dev;
122 rc = i2c_master_recv(client, (void*) &tea->regs, sizeof(tea->regs));
123 for (i = 0; i < 8; i++) {
124 p[i] = __be16_to_cpu(p[i]);
127 dev_dbg(&client->dev,
128 "chip state: %04x %04x %04x %04x %04x %04x %04x %04x\n",
129 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
132 dev_err(&client->dev, "read\n");
137 static void tea5761_write_regs(struct tea5761_device *tea)
139 struct tea5761_write_regs wr;
140 struct tea5761_regs *r = &tea->regs;
141 struct i2c_client *client = tea->i2c_dev;
146 wr.intreg = r->intreg & 0xff;
147 wr.frqset = __cpu_to_be16(r->frqset);
148 wr.tnctrl = __cpu_to_be16(r->tnctrl);
149 wr.testreg = __cpu_to_be16(r->testreg);
151 dev_dbg(&client->dev,
152 "writing state: %02x %02x %02x %02x %02x %02x %02x\n",
153 p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
154 if (i2c_master_send(client, (void *) &wr, sizeof(wr)) < 0)
155 dev_err(&client->dev, "write\n");
158 static void tea5761_power_up(struct tea5761_device *tea)
160 struct tea5761_regs *r = &tea->regs;
162 if (!(r->tnctrl & TEA5761_TNCTRL_PUPD0)) {
163 r->tnctrl &= ~(TEA5761_TNCTRL_AFM | TEA5761_TNCTRL_MU |
164 TEA5761_TNCTRL_HLSI);
165 r->testreg |= TEA5761_TESTREG_TRIGFR;
166 r->tnctrl |= TEA5761_TNCTRL_PUPD0;
167 return tea5761_write_regs(tea);
171 static void tea5761_power_down(struct tea5761_device *tea)
173 struct tea5761_regs *r = &tea->regs;
175 if (r->tnctrl & TEA5761_TNCTRL_PUPD0) {
176 r->tnctrl &= ~TEA5761_TNCTRL_PUPD0;
177 return tea5761_write_regs(tea);
181 static void tea5761_set_freq(struct tea5761_device *tea, int freq)
183 struct tea5761_regs *r = &tea->regs;
185 if (r->tnctrl & TEA5761_TNCTRL_HLSI)
186 r->frqset = (freq + 225000) / 8192;
188 r->frqset = (freq - 225000) / 8192;
191 static int tea5761_get_freq(struct tea5761_device *tea)
193 struct tea5761_regs *r = &tea->regs;
195 if (r->tnctrl & TEA5761_TNCTRL_HLSI)
196 return (r->frqchk * 8192) - 225000;
198 return (r->frqchk * 8192) + 225000;
201 static void tea5761_tune(struct tea5761_device *tea, int freq)
203 tea5761_set_freq(tea, freq);
204 tea5761_write_regs(tea);
207 static void tea5761_set_audout_mode(struct tea5761_device *tea, int audmode)
209 struct tea5761_regs *r = &tea->regs;
210 int tnctrl = r->tnctrl;
212 if (audmode == V4L2_TUNER_MODE_MONO)
213 r->tnctrl |= TEA5761_TNCTRL_MST;
215 r->tnctrl &= ~TEA5761_TNCTRL_MST;
216 if (tnctrl != r->tnctrl)
217 tea5761_write_regs(tea);
220 static int tea5761_get_audout_mode(struct tea5761_device *tea)
222 struct tea5761_regs *r = &tea->regs;
224 if (r->tnctrl & TEA5761_TNCTRL_MST)
225 return V4L2_TUNER_MODE_MONO;
227 return V4L2_TUNER_MODE_STEREO;
230 static void tea5761_mute(struct tea5761_device *tea, int on)
232 struct tea5761_regs *r = &tea->regs;
233 int tnctrl = r->tnctrl;
236 r->tnctrl |= TEA5761_TNCTRL_MU;
238 r->tnctrl &= ~TEA5761_TNCTRL_MU;
239 if (tnctrl != r->tnctrl)
240 tea5761_write_regs(tea);
243 static int tea5761_is_muted(struct tea5761_device *tea)
245 return tea->regs.tnctrl & TEA5761_TNCTRL_MU;
248 static int tea5761_do_ioctl(struct inode *inode, struct file *file,
249 unsigned int cmd, void *arg)
251 struct tea5761_device *tea = file->private_data;
252 struct video_device *dev = tea->video_dev;
253 struct i2c_client *client = tea->i2c_dev;
254 struct tea5761_regs *r = &tea->regs;
257 struct v4l2_capability c;
259 struct v4l2_frequency f;
260 struct v4l2_queryctrl qc;
261 struct v4l2_control ct;
264 tea5761_read_regs(tea);
267 case VIDIOC_QUERYCAP:
268 dev_dbg(&client->dev, "VIDIOC_QUERYCAP\n");
269 memset(&u->c, 0, sizeof(u->c));
270 strlcpy(u->c.driver, dev->dev->driver->name,
271 sizeof(u->c.driver));
272 strlcpy(u->c.card, dev->name, sizeof(u->c.card));
273 snprintf(u->c.bus_info, sizeof(u->c.bus_info), "I2C:%s",
275 u->c.version = TEA5761_VERSION;
276 u->c.capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
280 /* Only one tuner chip */
281 dev_dbg(&client->dev, "VIDIOC_G_TUNER\n");
285 memset(&u->t, 0, sizeof(u->t));
286 u->t.type = V4L2_TUNER_RADIO;
287 strlcpy(u->t.name, "FM", sizeof(u->t.name));
288 /* Freq in 62.5Hz units */
289 u->t.rangelow = TEA5761_FREQ_LOW * 16;
290 u->t.rangehigh = TEA5761_FREQ_HIGH * 16;
291 u->t.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
292 if (r->tunchk & TEA5761_TUNCHK_STEREO)
293 u->t.rxsubchans = V4L2_TUNER_SUB_STEREO;
294 u->t.audmode = tea5761_get_audout_mode(tea);
295 u->t.signal = TEA5761_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf;
296 u->t.afc = TEA5761_TUNCHK_IFCNT(r->tunchk);
300 /* Only tuner nro 0 can be selected. */
301 dev_dbg(&client->dev, "VIDIOC_S_TUNER\n");
304 tea5761_set_audout_mode(tea, u->t.audmode);
307 case VIDIOC_G_FREQUENCY:
308 dev_dbg(&client->dev, "VIDIOC_G_FREQUENCY\n");
309 memset(&u->f, 0, sizeof(u->f));
310 u->f.type = V4L2_TUNER_RADIO;
311 if (r->tnctrl & TEA5761_TNCTRL_PUPD0)
312 u->f.frequency = (tea5761_get_freq(tea) * 2) / 125;
317 case VIDIOC_S_FREQUENCY:
318 dev_dbg(&client->dev, "VIDIOC_S_FREQUENCY %u\n",
322 if (u->f.frequency == 0) {
323 /* We special case this as a power down
325 tea5761_power_down(tea);
328 if (u->f.frequency < 16 * TEA5761_FREQ_LOW)
330 if (u->f.frequency > 16 * TEA5761_FREQ_HIGH)
333 tea5761_power_up(tea);
334 tea5761_tune(tea, (u->f.frequency * 125) / 2);
337 case VIDIOC_QUERYCTRL:
338 dev_dbg(&client->dev, "VIDIOC_QUERYCTRL %d\n", u->qc.id);
339 if (u->qc.id != V4L2_CID_AUDIO_MUTE)
341 strlcpy(u->qc.name, "Mute", sizeof(u->qc.name));
345 u->qc.default_value = 0;
346 u->qc.type = V4L2_CTRL_TYPE_BOOLEAN;
350 dev_dbg(&client->dev, "VIDIOC_G_CTRL %d\n", u->ct.id);
351 if (u->ct.id != V4L2_CID_AUDIO_MUTE)
353 if (r->tnctrl & TEA5761_TNCTRL_PUPD0)
354 u->ct.value = tea5761_is_muted(tea) ? 1 : 0;
360 dev_dbg(&client->dev, "VIDIOC_S_CTRL %d\n", u->ct.id);
361 if (u->ct.id != V4L2_CID_AUDIO_MUTE)
363 tea5761_mute(tea, u->ct.value);
373 static int tea5761_ioctl(struct inode *inode, struct file *file,
374 unsigned int cmd, unsigned long arg)
376 return video_usercopy(inode, file, cmd, arg, tea5761_do_ioctl);
379 static int tea5761_open(struct inode *inode, struct file *file)
381 int minor = iminor(file->f_dentry->d_inode);
382 /* Currently we support only one device */
383 struct tea5761_device *tea = &tea5761;
385 if (tea->video_dev->minor != minor)
388 mutex_lock(&tea->mutex);
389 /* Only exclusive access */
391 mutex_unlock(&tea->mutex);
395 mutex_unlock(&tea->mutex);
397 file->private_data = tea;
401 static int tea5761_release(struct inode *inode, struct file *file)
403 struct tea5761_device *tea = file->private_data;
405 mutex_lock(&tea->mutex);
407 mutex_unlock(&tea->mutex);
412 static struct file_operations tea5761_fops = {
413 .owner = THIS_MODULE,
414 .open = tea5761_open,
415 .release = tea5761_release,
416 .ioctl = tea5761_ioctl,
420 static struct video_device tea5761_video_device = {
421 .owner = THIS_MODULE,
422 .name = "TEA5761 FM-Radio",
423 .type = VID_TYPE_TUNER,
424 .hardware = 40 /* VID_HARDWARE_TEA5761UK */,
425 .fops = &tea5761_fops,
426 .release = video_device_release
429 static int tea5761_probe(struct i2c_adapter *adapter, int address,
432 struct i2c_client *client;
433 struct video_device *video_dev;
435 static const char *client_name = "TEA5761 FM-Radio";
436 struct tea5761_device *tea = &tea5761;
437 struct tea5761_regs *r = &tea->regs;
439 mutex_init(&tea->mutex);
440 /* I2C detection and initialization */
441 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
442 if (client == NULL) {
443 dev_err(&adapter->dev, DRIVER_NAME
444 ": couldn't allocate memory\n");
447 tea->i2c_dev = client;
449 client->addr = address;
450 client->adapter = adapter;
451 client->driver = &tea5761_driver;
452 client->dev.driver = &tea5761_driver.driver;
454 strlcpy(client->name, client_name, I2C_NAME_SIZE);
457 if (tea5761_read_regs(tea) < 0) {
458 dev_info(&client->dev,
459 "chip read failed for %d-%04x\n",
460 adapter->nr, address);
463 if (r->chipid != TEA5761_CHIPID) {
464 dev_info(&client->dev,
465 "bad chipid (0x%04x) at %d-%04x\n",
466 r->chipid, adapter->nr, address);
469 if ((r->manid & 0x0fff) != TEA5761_MANID) {
470 dev_info(&client->dev,
471 "bad manid (0x%04x) at %d-%04x\n",
472 r->manid, adapter->nr, address);
477 err = i2c_attach_client(client);
479 dev_err(&client->dev, "couldn't attach to address %d-%04x\n",
480 adapter->nr, address);
484 /* V4L initialization */
485 video_dev = video_device_alloc();
486 if (video_dev == NULL) {
487 dev_err(&client->dev, "couldn't allocate memory\n");
491 tea->video_dev = video_dev;
493 *video_dev = tea5761_video_device;
494 video_dev->dev = &client->dev;
495 i2c_set_clientdata(client, video_dev);
497 /* initialize and power off the chip */
498 tea5761_read_regs(tea);
499 tea5761_set_audout_mode(tea, V4L2_TUNER_MODE_STEREO);
500 tea5761_mute(tea, 0);
501 tea5761_power_down(tea);
503 tea5761.video_dev = video_dev;
504 tea5761.i2c_dev = client;
506 err = video_register_device(video_dev, VFL_TYPE_RADIO, radio_nr);
508 dev_err(&client->dev, "couldn't register video device\n");
509 goto err_video_alloc;
512 dev_info(&client->dev, "tea5761 (version %d) detected at %d-%04x\n",
513 (tea->regs.manid >> 12) & 0xf, adapter->nr, address);
518 video_device_release(video_dev);
520 i2c_detach_client(client);
526 static int tea5761_attach_adapter(struct i2c_adapter *adapter)
528 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
531 return i2c_probe(adapter, &addr_data, tea5761_probe);
534 static int tea5761_detach_client(struct i2c_client *client)
536 struct video_device *vd = i2c_get_clientdata(client);
538 i2c_detach_client(client);
539 video_unregister_device(vd);
545 static struct i2c_driver tea5761_driver = {
546 .id = I2C_DRIVERID_TUNER,
550 .attach_adapter = tea5761_attach_adapter,
551 .detach_client = tea5761_detach_client,
555 /* No way to pass platform device data. Enable here all the TEA5761
556 * devices, since I2C address scanning will need them to respond.
558 static int enable_gpio;
560 static int __init tea5761_dev_init(void)
562 const struct omap_tea5761_config *info;
564 info = omap_get_config(OMAP_TAG_TEA5761, struct omap_tea5761_config);
566 enable_gpio = info->enable_gpio;
570 pr_debug(DRIVER_NAME ": enabling tea5761 at GPIO %d\n",
573 if (omap_request_gpio(enable_gpio) < 0) {
574 printk(KERN_ERR DRIVER_NAME ": can't request GPIO %d\n",
579 omap_set_gpio_direction(enable_gpio, 0);
581 omap_set_gpio_dataout(enable_gpio, 1);
587 static void __exit tea5761_dev_exit(void)
590 omap_set_gpio_dataout(enable_gpio, 0);
591 omap_free_gpio(enable_gpio);
595 static int __init tea5761_dev_init(void)
599 static void __exit tea5761_dev_exit(void)
604 static int __init tea5761_init(void)
608 if ((res = tea5761_dev_init()) < 0)
611 if ((res = i2c_add_driver(&tea5761_driver))) {
612 printk(KERN_ERR DRIVER_NAME ": driver registration failed\n");
619 static void __exit tea5761_exit(void)
623 if ((res = i2c_del_driver(&tea5761_driver)))
624 printk(KERN_ERR DRIVER_NAME ": i2c driver removal failed\n");
628 MODULE_AUTHOR("Timo Teräs");
629 MODULE_DESCRIPTION("I2C interface for TEA5761.");
630 MODULE_LICENSE("GPL");
632 module_param(radio_nr, int, 0);
633 MODULE_PARM_DESC(nr_radio, "video4linux device number to use");
635 module_init(tea5761_init)
636 module_exit(tea5761_exit)