aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-06-20 05:09:14 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-12 11:17:31 -0400
commit3c86cf7a7d323019a7942df8bacf47c9fd2c31fa (patch)
tree8ed9ecc206eef28319d633d38432aab310e98219 /drivers
parent6a052c84342dd047226ecad0e1aa4e4b37d45a6c (diff)
V4L/DVB (12215): saa6588: conform to the final RDS spec.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/saa6588.c60
1 files changed, 47 insertions, 13 deletions
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index c25e81af5ce0..c3e96f070973 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -40,7 +40,7 @@
40/* insmod options */ 40/* insmod options */
41static unsigned int debug; 41static unsigned int debug;
42static unsigned int xtal; 42static unsigned int xtal;
43static unsigned int rbds; 43static unsigned int mmbs;
44static unsigned int plvl; 44static unsigned int plvl;
45static unsigned int bufblocks = 100; 45static unsigned int bufblocks = 100;
46 46
@@ -48,8 +48,8 @@ module_param(debug, int, 0644);
48MODULE_PARM_DESC(debug, "enable debug messages"); 48MODULE_PARM_DESC(debug, "enable debug messages");
49module_param(xtal, int, 0); 49module_param(xtal, int, 0);
50MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0"); 50MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");
51module_param(rbds, int, 0); 51module_param(mmbs, int, 0);
52MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0"); 52MODULE_PARM_DESC(mmbs, "enable MMBS mode: 0=off (default), 1=on");
53module_param(plvl, int, 0); 53module_param(plvl, int, 0);
54MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0"); 54MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");
55module_param(bufblocks, int, 0); 55module_param(bufblocks, int, 0);
@@ -78,6 +78,7 @@ struct saa6588 {
78 unsigned char last_blocknum; 78 unsigned char last_blocknum;
79 wait_queue_head_t read_queue; 79 wait_queue_head_t read_queue;
80 int data_available_for_read; 80 int data_available_for_read;
81 u8 sync;
81}; 82};
82 83
83static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd) 84static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd)
@@ -261,13 +262,16 @@ static void saa6588_i2c_poll(struct saa6588 *s)
261 unsigned char tmp; 262 unsigned char tmp;
262 263
263 /* Although we only need 3 bytes, we have to read at least 6. 264 /* Although we only need 3 bytes, we have to read at least 6.
264 SAA6588 returns garbage otherwise */ 265 SAA6588 returns garbage otherwise. */
265 if (6 != i2c_master_recv(client, &tmpbuf[0], 6)) { 266 if (6 != i2c_master_recv(client, &tmpbuf[0], 6)) {
266 if (debug > 1) 267 if (debug > 1)
267 dprintk(PREFIX "read error!\n"); 268 dprintk(PREFIX "read error!\n");
268 return; 269 return;
269 } 270 }
270 271
272 s->sync = tmpbuf[0] & 0x10;
273 if (!s->sync)
274 return;
271 blocknum = tmpbuf[0] >> 5; 275 blocknum = tmpbuf[0] >> 5;
272 if (blocknum == s->last_blocknum) { 276 if (blocknum == s->last_blocknum) {
273 if (debug > 3) 277 if (debug > 3)
@@ -286,9 +290,8 @@ static void saa6588_i2c_poll(struct saa6588 *s)
286 occurred during reception of this block. 290 occurred during reception of this block.
287 Bit 6: Corrected bit. Indicates that an error was 291 Bit 6: Corrected bit. Indicates that an error was
288 corrected for this data block. 292 corrected for this data block.
289 Bits 5-3: Received Offset. Indicates the offset received 293 Bits 5-3: Same as bits 0-2.
290 by the sync system. 294 Bits 2-0: Block number.
291 Bits 2-0: Offset Name. Indicates the offset applied to this data.
292 295
293 SAA6588 byte order is Status-MSB-LSB, so we have to swap the 296 SAA6588 byte order is Status-MSB-LSB, so we have to swap the
294 first and the last of the 3 bytes block. 297 first and the last of the 3 bytes block.
@@ -298,12 +301,21 @@ static void saa6588_i2c_poll(struct saa6588 *s)
298 tmpbuf[2] = tmpbuf[0]; 301 tmpbuf[2] = tmpbuf[0];
299 tmpbuf[0] = tmp; 302 tmpbuf[0] = tmp;
300 303
304 /* Map 'Invalid block E' to 'Invalid Block' */
305 if (blocknum == 6)
306 blocknum = V4L2_RDS_BLOCK_INVALID;
307 /* And if are not in mmbs mode, then 'Block E' is also mapped
308 to 'Invalid Block'. As far as I can tell MMBS is discontinued,
309 and if there is ever a need to support E blocks, then please
310 contact the linux-media mailinglist. */
311 else if (!mmbs && blocknum == 5)
312 blocknum = V4L2_RDS_BLOCK_INVALID;
301 tmp = blocknum; 313 tmp = blocknum;
302 tmp |= blocknum << 3; /* Received offset == Offset Name (OK ?) */ 314 tmp |= blocknum << 3; /* Received offset == Offset Name (OK ?) */
303 if ((tmpbuf[2] & 0x03) == 0x03) 315 if ((tmpbuf[2] & 0x03) == 0x03)
304 tmp |= 0x80; /* uncorrectable error */ 316 tmp |= V4L2_RDS_BLOCK_ERROR; /* uncorrectable error */
305 else if ((tmpbuf[2] & 0x03) != 0x00) 317 else if ((tmpbuf[2] & 0x03) != 0x00)
306 tmp |= 0x40; /* corrected error */ 318 tmp |= V4L2_RDS_BLOCK_CORRECTED; /* corrected error */
307 tmpbuf[2] = tmp; /* Is this enough ? Should we also check other bits ? */ 319 tmpbuf[2] = tmp; /* Is this enough ? Should we also check other bits ? */
308 320
309 spin_lock_irqsave(&s->lock, flags); 321 spin_lock_irqsave(&s->lock, flags);
@@ -321,14 +333,14 @@ static void saa6588_work(struct work_struct *work)
321 schedule_delayed_work(&s->work, msecs_to_jiffies(20)); 333 schedule_delayed_work(&s->work, msecs_to_jiffies(20));
322} 334}
323 335
324static int saa6588_configure(struct saa6588 *s) 336static void saa6588_configure(struct saa6588 *s)
325{ 337{
326 struct i2c_client *client = v4l2_get_subdevdata(&s->sd); 338 struct i2c_client *client = v4l2_get_subdevdata(&s->sd);
327 unsigned char buf[3]; 339 unsigned char buf[3];
328 int rc; 340 int rc;
329 341
330 buf[0] = cSyncRestart; 342 buf[0] = cSyncRestart;
331 if (rbds) 343 if (mmbs)
332 buf[0] |= cProcessingModeRBDS; 344 buf[0] |= cProcessingModeRBDS;
333 345
334 buf[1] = cFlywheelDefault; 346 buf[1] = cFlywheelDefault;
@@ -374,8 +386,6 @@ static int saa6588_configure(struct saa6588 *s)
374 rc = i2c_master_send(client, buf, 3); 386 rc = i2c_master_send(client, buf, 3);
375 if (rc != 3) 387 if (rc != 3)
376 printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc); 388 printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc);
377
378 return 0;
379} 389}
380 390
381/* ---------------------------------------------------------------------- */ 391/* ---------------------------------------------------------------------- */
@@ -416,6 +426,24 @@ static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
416 return 0; 426 return 0;
417} 427}
418 428
429static int saa6588_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
430{
431 struct saa6588 *s = to_saa6588(sd);
432
433 vt->capability |= V4L2_TUNER_CAP_RDS;
434 if (s->sync)
435 vt->rxsubchans |= V4L2_TUNER_SUB_RDS;
436 return 0;
437}
438
439static int saa6588_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
440{
441 struct saa6588 *s = to_saa6588(sd);
442
443 saa6588_configure(s);
444 return 0;
445}
446
419static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) 447static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
420{ 448{
421 struct i2c_client *client = v4l2_get_subdevdata(sd); 449 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -430,8 +458,14 @@ static const struct v4l2_subdev_core_ops saa6588_core_ops = {
430 .ioctl = saa6588_ioctl, 458 .ioctl = saa6588_ioctl,
431}; 459};
432 460
461static const struct v4l2_subdev_tuner_ops saa6588_tuner_ops = {
462 .g_tuner = saa6588_g_tuner,
463 .s_tuner = saa6588_s_tuner,
464};
465
433static const struct v4l2_subdev_ops saa6588_ops = { 466static const struct v4l2_subdev_ops saa6588_ops = {
434 .core = &saa6588_core_ops, 467 .core = &saa6588_core_ops,
468 .tuner = &saa6588_tuner_ops,
435}; 469};
436 470
437/* ---------------------------------------------------------------------- */ 471/* ---------------------------------------------------------------------- */