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>
27 #define DRIVER_NAME "tea5761"
29 #define TEA5761_VERSION KERNEL_VERSION(0, 0, 1)
31 #define TEA5761_I2C_ADDR 0x10
33 #define TEA5761_MANID 0x002b
34 #define TEA5761_CHIPID 0x5761
36 #define TEA5761_INTREG_BLMSK 0x0001
37 #define TEA5761_INTREG_FRRMSK 0x0002
38 #define TEA5761_INTREG_LEVMSK 0x0008
39 #define TEA5761_INTREG_IFMSK 0x0010
40 #define TEA5761_INTREG_BLMFLAG 0x0100
41 #define TEA5761_INTREG_FRRFLAG 0x0200
42 #define TEA5761_INTREG_LEVFLAG 0x0800
43 #define TEA5761_INTREG_IFFLAG 0x1000
45 #define TEA5761_FRQSET_SUD 0x8000
46 #define TEA5761_FRQSET_SM 0x4000
48 #define TEA5761_TNCTRL_PUPD0 0x4000
49 #define TEA5761_TNCTRL_BLIM 0x2000
50 #define TEA5761_TNCTRL_SWPM 0x1000
51 #define TEA5761_TNCTRL_IFCTC 0x0800
52 #define TEA5761_TNCTRL_AFM 0x0400
53 #define TEA5761_TNCTRL_SMUTE 0x0200
54 #define TEA5761_TNCTRL_SNC 0x0100
55 #define TEA5761_TNCTRL_MU 0x0080
56 #define TEA5761_TNCTRL_SSL1 0x0040
57 #define TEA5761_TNCTRL_SSL0 0x0020
58 #define TEA5761_TNCTRL_HLSI 0x0010
59 #define TEA5761_TNCTRL_MST 0x0008
60 #define TEA5761_TNCTRL_SWP 0x0004
61 #define TEA5761_TNCTRL_DTC 0x0002
62 #define TEA5761_TNCTRL_AHLSI 0x0001
64 #define TEA5761_TUNCHK_LEVEL(x) (((x) & 0x00F0) >> 4)
65 #define TEA5761_TUNCHK_IFCNT(x) (((x) & 0xFE00) >> 9)
66 #define TEA5761_TUNCHK_TUNTO 0x0100
67 #define TEA5761_TUNCHK_LD 0x0008
68 #define TEA5761_TUNCHK_STEREO 0x0004
70 #define TEA5761_TESTREG_TRIGFR 0x0800
72 #define TEA5761_FREQ_LOW 87500
73 #define TEA5761_FREQ_HIGH 108000
84 } __attribute__ ((packed
));
86 struct tea5761_write_regs
{
91 } __attribute__ ((packed
));
93 struct tea5761_device
{
94 struct video_device
*video_dev
;
95 struct i2c_client
*i2c_dev
;
96 struct tea5761_regs regs
;
101 static struct tea5761_device tea5761
;
103 static struct i2c_driver tea5761_driver
;
104 static int radio_nr
= -1;
106 static int tea5761_read_regs(struct tea5761_device
*tea
)
109 u16
*p
= (u16
*) &tea
->regs
;
110 struct i2c_client
*client
= tea
->i2c_dev
;
112 rc
= i2c_master_recv(client
, (void*) &tea
->regs
, sizeof(tea
->regs
));
113 for (i
= 0; i
< 8; i
++) {
114 p
[i
] = __be16_to_cpu(p
[i
]);
117 dev_dbg(&client
->dev
,
118 "chip state: %04x %04x %04x %04x %04x %04x %04x %04x\n",
119 p
[0], p
[1], p
[2], p
[3], p
[4], p
[5], p
[6], p
[7]);
122 dev_err(&client
->dev
, "read\n");
127 static void tea5761_write_regs(struct tea5761_device
*tea
)
129 struct tea5761_write_regs wr
;
130 struct tea5761_regs
*r
= &tea
->regs
;
131 struct i2c_client
*client
= tea
->i2c_dev
;
134 wr
.intreg
= r
->intreg
& 0xff;
135 wr
.frqset
= __cpu_to_be16(r
->frqset
);
136 wr
.tnctrl
= __cpu_to_be16(r
->tnctrl
);
137 wr
.testreg
= __cpu_to_be16(r
->testreg
);
139 dev_dbg(&client
->dev
,
140 "writing state: %02x %02x %02x %02x %02x %02x %02x\n",
141 p
[0], p
[1], p
[2], p
[3], p
[4], p
[5], p
[6]);
142 if (i2c_master_send(client
, (void *) &wr
, sizeof(wr
)) < 0)
143 dev_err(&client
->dev
, "write\n");
146 static void tea5761_power_up(struct tea5761_device
*tea
)
148 struct tea5761_regs
*r
= &tea
->regs
;
150 if (!(r
->tnctrl
& TEA5761_TNCTRL_PUPD0
)) {
151 r
->tnctrl
&= ~(TEA5761_TNCTRL_AFM
| TEA5761_TNCTRL_MU
|
152 TEA5761_TNCTRL_HLSI
);
153 r
->testreg
|= TEA5761_TESTREG_TRIGFR
;
154 r
->tnctrl
|= TEA5761_TNCTRL_PUPD0
;
155 return tea5761_write_regs(tea
);
159 static void tea5761_power_down(struct tea5761_device
*tea
)
161 struct tea5761_regs
*r
= &tea
->regs
;
163 if (r
->tnctrl
& TEA5761_TNCTRL_PUPD0
) {
164 r
->tnctrl
&= ~TEA5761_TNCTRL_PUPD0
;
165 return tea5761_write_regs(tea
);
169 static void tea5761_set_freq(struct tea5761_device
*tea
, int freq
)
171 struct tea5761_regs
*r
= &tea
->regs
;
173 if (r
->tnctrl
& TEA5761_TNCTRL_HLSI
)
174 r
->frqset
= (freq
+ 225000) / 8192;
176 r
->frqset
= (freq
- 225000) / 8192;
179 static int tea5761_get_freq(struct tea5761_device
*tea
)
181 struct tea5761_regs
*r
= &tea
->regs
;
183 if (r
->tnctrl
& TEA5761_TNCTRL_HLSI
)
184 return (r
->frqchk
* 8192) - 225000;
186 return (r
->frqchk
* 8192) + 225000;
189 static void tea5761_tune(struct tea5761_device
*tea
, int freq
)
191 tea5761_set_freq(tea
, freq
);
192 tea5761_write_regs(tea
);
195 static void tea5761_set_audout_mode(struct tea5761_device
*tea
, int audmode
)
197 struct tea5761_regs
*r
= &tea
->regs
;
198 int tnctrl
= r
->tnctrl
;
200 if (audmode
== V4L2_TUNER_MODE_MONO
)
201 r
->tnctrl
|= TEA5761_TNCTRL_MST
;
203 r
->tnctrl
&= ~TEA5761_TNCTRL_MST
;
204 if (tnctrl
!= r
->tnctrl
)
205 tea5761_write_regs(tea
);
208 static int tea5761_get_audout_mode(struct tea5761_device
*tea
)
210 struct tea5761_regs
*r
= &tea
->regs
;
212 if (r
->tnctrl
& TEA5761_TNCTRL_MST
)
213 return V4L2_TUNER_MODE_MONO
;
215 return V4L2_TUNER_MODE_STEREO
;
218 static void tea5761_mute(struct tea5761_device
*tea
, int on
)
220 struct tea5761_regs
*r
= &tea
->regs
;
221 int tnctrl
= r
->tnctrl
;
224 r
->tnctrl
|= TEA5761_TNCTRL_MU
;
226 r
->tnctrl
&= ~TEA5761_TNCTRL_MU
;
227 if (tnctrl
!= r
->tnctrl
)
228 tea5761_write_regs(tea
);
231 static int tea5761_is_muted(struct tea5761_device
*tea
)
233 return tea
->regs
.tnctrl
& TEA5761_TNCTRL_MU
;
236 static int tea5761_do_ioctl(struct inode
*inode
, struct file
*file
,
237 unsigned int cmd
, void *arg
)
239 struct tea5761_device
*tea
= file
->private_data
;
240 struct video_device
*dev
= tea
->video_dev
;
241 struct i2c_client
*client
= tea
->i2c_dev
;
242 struct tea5761_regs
*r
= &tea
->regs
;
245 struct v4l2_capability c
;
247 struct v4l2_frequency f
;
248 struct v4l2_queryctrl qc
;
249 struct v4l2_control ct
;
252 tea5761_read_regs(tea
);
255 case VIDIOC_QUERYCAP
:
256 dev_dbg(&client
->dev
, "VIDIOC_QUERYCAP\n");
257 memset(&u
->c
, 0, sizeof(u
->c
));
258 strlcpy(u
->c
.driver
, dev
->dev
->driver
->name
,
259 sizeof(u
->c
.driver
));
260 strlcpy(u
->c
.card
, dev
->name
, sizeof(u
->c
.card
));
261 snprintf(u
->c
.bus_info
, sizeof(u
->c
.bus_info
), "I2C:%s",
263 u
->c
.version
= TEA5761_VERSION
;
264 u
->c
.capabilities
= V4L2_CAP_TUNER
| V4L2_CAP_RADIO
;
268 /* Only one tuner chip */
269 dev_dbg(&client
->dev
, "VIDIOC_G_TUNER\n");
273 memset(&u
->t
, 0, sizeof(u
->t
));
274 u
->t
.type
= V4L2_TUNER_RADIO
;
275 strlcpy(u
->t
.name
, "FM", sizeof(u
->t
.name
));
276 /* Freq in 62.5Hz units */
277 u
->t
.rangelow
= TEA5761_FREQ_LOW
* 16;
278 u
->t
.rangehigh
= TEA5761_FREQ_HIGH
* 16;
279 u
->t
.capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_STEREO
;
280 if (r
->tunchk
& TEA5761_TUNCHK_STEREO
)
281 u
->t
.rxsubchans
= V4L2_TUNER_SUB_STEREO
;
282 u
->t
.audmode
= tea5761_get_audout_mode(tea
);
283 u
->t
.signal
= TEA5761_TUNCHK_LEVEL(r
->tunchk
) * 0xffff / 0xf;
284 u
->t
.afc
= TEA5761_TUNCHK_IFCNT(r
->tunchk
);
288 /* Only tuner nro 0 can be selected. */
289 dev_dbg(&client
->dev
, "VIDIOC_S_TUNER\n");
292 tea5761_set_audout_mode(tea
, u
->t
.audmode
);
295 case VIDIOC_G_FREQUENCY
:
296 dev_dbg(&client
->dev
, "VIDIOC_G_FREQUENCY\n");
297 memset(&u
->f
, 0, sizeof(u
->f
));
298 u
->f
.type
= V4L2_TUNER_RADIO
;
299 if (r
->tnctrl
& TEA5761_TNCTRL_PUPD0
)
300 u
->f
.frequency
= (tea5761_get_freq(tea
) * 2) / 125;
305 case VIDIOC_S_FREQUENCY
:
306 dev_dbg(&client
->dev
, "VIDIOC_S_FREQUENCY %u\n",
310 if (u
->f
.frequency
== 0) {
311 /* We special case this as a power down
313 tea5761_power_down(tea
);
316 if (u
->f
.frequency
< 16 * TEA5761_FREQ_LOW
)
318 if (u
->f
.frequency
> 16 * TEA5761_FREQ_HIGH
)
321 tea5761_power_up(tea
);
322 tea5761_tune(tea
, (u
->f
.frequency
* 125) / 2);
325 case VIDIOC_QUERYCTRL
:
326 dev_dbg(&client
->dev
, "VIDIOC_QUERYCTRL %d\n", u
->qc
.id
);
327 if (u
->qc
.id
!= V4L2_CID_AUDIO_MUTE
)
329 strlcpy(u
->qc
.name
, "Mute", sizeof(u
->qc
.name
));
333 u
->qc
.default_value
= 0;
334 u
->qc
.type
= V4L2_CTRL_TYPE_BOOLEAN
;
338 dev_dbg(&client
->dev
, "VIDIOC_G_CTRL %d\n", u
->ct
.id
);
339 if (u
->ct
.id
!= V4L2_CID_AUDIO_MUTE
)
341 if (r
->tnctrl
& TEA5761_TNCTRL_PUPD0
)
342 u
->ct
.value
= tea5761_is_muted(tea
) ? 1 : 0;
348 dev_dbg(&client
->dev
, "VIDIOC_S_CTRL %d\n", u
->ct
.id
);
349 if (u
->ct
.id
!= V4L2_CID_AUDIO_MUTE
)
351 tea5761_mute(tea
, u
->ct
.value
);
361 static int tea5761_ioctl(struct inode
*inode
, struct file
*file
,
362 unsigned int cmd
, unsigned long arg
)
364 return video_usercopy(inode
, file
, cmd
, arg
, tea5761_do_ioctl
);
367 static int tea5761_open(struct inode
*inode
, struct file
*file
)
369 int minor
= iminor(file
->f_dentry
->d_inode
);
370 /* Currently we support only one device */
371 struct tea5761_device
*tea
= &tea5761
;
373 if (tea
->video_dev
->minor
!= minor
)
376 mutex_lock(&tea
->mutex
);
377 /* Only exclusive access */
379 mutex_unlock(&tea
->mutex
);
383 mutex_unlock(&tea
->mutex
);
385 file
->private_data
= tea
;
389 static int tea5761_release(struct inode
*inode
, struct file
*file
)
391 struct tea5761_device
*tea
= file
->private_data
;
393 mutex_lock(&tea
->mutex
);
395 mutex_unlock(&tea
->mutex
);
400 static struct file_operations tea5761_fops
= {
401 .owner
= THIS_MODULE
,
402 .open
= tea5761_open
,
403 .release
= tea5761_release
,
404 .ioctl
= tea5761_ioctl
,
408 static struct video_device tea5761_video_device
= {
409 .owner
= THIS_MODULE
,
410 .name
= "TEA5761 FM-Radio",
411 .type
= VID_TYPE_TUNER
,
412 .fops
= &tea5761_fops
,
413 .release
= video_device_release
416 static int tea5761_i2c_driver_probe(struct i2c_client
*client
,
417 const struct i2c_device_id
*id
)
419 struct video_device
*video_dev
;
421 struct tea5761_device
*tea
= &tea5761
;
423 mutex_init(&tea
->mutex
);
425 tea
->i2c_dev
= client
;
427 /* V4L initialization */
428 video_dev
= video_device_alloc();
429 if (video_dev
== NULL
) {
430 dev_err(&client
->dev
, "couldn't allocate memory\n");
434 tea
->video_dev
= video_dev
;
436 *video_dev
= tea5761_video_device
;
437 video_dev
->dev
= &client
->dev
;
438 i2c_set_clientdata(client
, video_dev
);
440 /* initialize and power off the chip */
441 tea5761_read_regs(tea
);
442 tea5761_set_audout_mode(tea
, V4L2_TUNER_MODE_STEREO
);
443 tea5761_mute(tea
, 0);
444 tea5761_power_down(tea
);
446 tea5761
.video_dev
= video_dev
;
447 tea5761
.i2c_dev
= client
;
449 err
= video_register_device(video_dev
, VFL_TYPE_RADIO
, radio_nr
);
451 dev_err(&client
->dev
, "couldn't register video device\n");
452 goto err_video_alloc
;
455 dev_info(&client
->dev
, "tea5761 (version %d) detected\n",
456 (tea
->regs
.manid
>> 12) & 0xf);
461 video_device_release(video_dev
);
467 static int tea5761_i2c_driver_remove(struct i2c_client
*client
)
469 struct video_device
*vd
= i2c_get_clientdata(client
);
471 video_unregister_device(vd
);
476 static const struct i2c_device_id tea5761_id
[] = {
480 MODULE_DEVICE_TABLE(i2c
, tea5761_id
);
482 static struct i2c_driver tea5761_driver
= {
486 .probe
= tea5761_i2c_driver_probe
,
487 .remove
= __devexit_p(tea5761_i2c_driver_remove
),
488 .id_table
= tea5761_id
,
491 static int __init
tea5761_init(void)
495 if ((res
= i2c_add_driver(&tea5761_driver
))) {
496 printk(KERN_ERR DRIVER_NAME
": driver registration failed\n");
503 static void __exit
tea5761_exit(void)
505 i2c_del_driver(&tea5761_driver
);
508 MODULE_AUTHOR("Timo Teräs");
509 MODULE_DESCRIPTION("I2C interface for TEA5761.");
510 MODULE_LICENSE("GPL");
512 module_param(radio_nr
, int, 0);
513 MODULE_PARM_DESC(nr_radio
, "video4linux device number to use");
515 module_init(tea5761_init
)
516 module_exit(tea5761_exit
)