summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-07-10 17:05:19 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-07-10 17:05:19 -0300
commit87e2075bfc4af8e6e5cad365ab37698a791d201c (patch)
treef5849eab0d2864bd53859c25f8bf4bc3f2ce5adb
parent784f927dcf2cc497d4a2c44fb4f1321d9cf0c45b (diff)
parent760844137434b0401b2cd25b2d3ee9b9443facb8 (diff)
downloadmediapointer-dvb-s2-87e2075bfc4af8e6e5cad365ab37698a791d201c.tar.gz
mediapointer-dvb-s2-87e2075bfc4af8e6e5cad365ab37698a791d201c.tar.bz2
merge: http://www.linuxtv.org/hg/~hverkuil/v4l-dvb-rds
From: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--linux/drivers/media/radio/radio-cadet.c6
-rw-r--r--linux/drivers/media/radio/radio-si470x.c9
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-driver.c2
-rw-r--r--linux/drivers/media/video/saa6588.c60
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-core.c4
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-video.c2
-rw-r--r--linux/drivers/media/video/saa7134/saa7134.h1
-rw-r--r--linux/include/linux/videodev2.h23
-rw-r--r--v4l2-apps/util/v4l2-ctl.cpp4
-rw-r--r--v4l2-spec/biblio.sgml65
-rw-r--r--v4l2-spec/compat.sgml14
-rw-r--r--v4l2-spec/dev-rds.sgml174
-rw-r--r--v4l2-spec/v4l2.sgml7
-rw-r--r--v4l2-spec/vidioc-g-tuner.sgml17
-rw-r--r--v4l2-spec/vidioc-querycap.sgml2
15 files changed, 288 insertions, 102 deletions
diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c
index 2fd4aae2e..99551d836 100644
--- a/linux/drivers/media/radio/radio-cadet.c
+++ b/linux/drivers/media/radio/radio-cadet.c
@@ -386,7 +386,8 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(v->card, "ADS Cadet", sizeof(v->card));
strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
v->version = CADET_VERSION;
- v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE;
+ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO |
+ V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE;
return 0;
}
@@ -399,7 +400,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
switch (v->index) {
case 0:
strlcpy(v->name, "FM", sizeof(v->name));
- v->capability = V4L2_TUNER_CAP_STEREO;
+ v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS;
v->rangelow = 1400; /* 87.5 MHz */
v->rangehigh = 1728; /* 108.0 MHz */
v->rxsubchans = cadet_getstereo(dev);
@@ -413,6 +414,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
default:
break;
}
+ v->rxsubchans |= V4L2_TUNER_SUB_RDS;
break;
case 1:
strlcpy(v->name, "AM", sizeof(v->name));
diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c
index 20aa447cc..3efd397d1 100644
--- a/linux/drivers/media/radio/radio-si470x.c
+++ b/linux/drivers/media/radio/radio-si470x.c
@@ -1254,7 +1254,7 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info));
capability->version = DRIVER_KERNEL_VERSION;
capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
- V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
return 0;
}
@@ -1413,7 +1413,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
/* driver constants */
strcpy(tuner->name, "FM");
tuner->type = V4L2_TUNER_RADIO;
- tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+ tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
+ V4L2_TUNER_CAP_RDS;
/* range limits */
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
@@ -1439,6 +1440,10 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
else
tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+ /* If there is a reliable method of detecting an RDS channel,
+ then this code should check for that before setting this
+ RDS subchannel. */
+ tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
/* mono/stereo selector */
if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c
index bd5dde3f8..9c25efe06 100644
--- a/linux/drivers/media/video/bt8xx/bttv-driver.c
+++ b/linux/drivers/media/video/bt8xx/bttv-driver.c
@@ -2679,6 +2679,8 @@ static int bttv_querycap(struct file *file, void *priv,
V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
+ if (btv->has_saa6588)
+ cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
if (no_overlay <= 0)
cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c
index 58aff8305..dcc83511e 100644
--- a/linux/drivers/media/video/saa6588.c
+++ b/linux/drivers/media/video/saa6588.c
@@ -51,7 +51,7 @@ I2C_CLIENT_INSMOD;
/* insmod options */
static unsigned int debug;
static unsigned int xtal;
-static unsigned int rbds;
+static unsigned int mmbs;
static unsigned int plvl;
static unsigned int bufblocks = 100;
@@ -59,8 +59,8 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages");
module_param(xtal, int, 0);
MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");
-module_param(rbds, int, 0);
-MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0");
+module_param(mmbs, int, 0);
+MODULE_PARM_DESC(mmbs, "enable MMBS mode: 0=off (default), 1=on");
module_param(plvl, int, 0);
MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");
module_param(bufblocks, int, 0);
@@ -89,6 +89,7 @@ struct saa6588 {
unsigned char last_blocknum;
wait_queue_head_t read_queue;
int data_available_for_read;
+ u8 sync;
};
static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd)
@@ -272,13 +273,16 @@ static void saa6588_i2c_poll(struct saa6588 *s)
unsigned char tmp;
/* Although we only need 3 bytes, we have to read at least 6.
- SAA6588 returns garbage otherwise */
+ SAA6588 returns garbage otherwise. */
if (6 != i2c_master_recv(client, &tmpbuf[0], 6)) {
if (debug > 1)
dprintk(PREFIX "read error!\n");
return;
}
+ s->sync = tmpbuf[0] & 0x10;
+ if (!s->sync)
+ return;
blocknum = tmpbuf[0] >> 5;
if (blocknum == s->last_blocknum) {
if (debug > 3)
@@ -297,9 +301,8 @@ static void saa6588_i2c_poll(struct saa6588 *s)
occurred during reception of this block.
Bit 6: Corrected bit. Indicates that an error was
corrected for this data block.
- Bits 5-3: Received Offset. Indicates the offset received
- by the sync system.
- Bits 2-0: Offset Name. Indicates the offset applied to this data.
+ Bits 5-3: Same as bits 0-2.
+ Bits 2-0: Block number.
SAA6588 byte order is Status-MSB-LSB, so we have to swap the
first and the last of the 3 bytes block.
@@ -309,12 +312,21 @@ static void saa6588_i2c_poll(struct saa6588 *s)
tmpbuf[2] = tmpbuf[0];
tmpbuf[0] = tmp;
+ /* Map 'Invalid block E' to 'Invalid Block' */
+ if (blocknum == 6)
+ blocknum = V4L2_RDS_BLOCK_INVALID;
+ /* And if are not in mmbs mode, then 'Block E' is also mapped
+ to 'Invalid Block'. As far as I can tell MMBS is discontinued,
+ and if there is ever a need to support E blocks, then please
+ contact the linux-media mailinglist. */
+ else if (!mmbs && blocknum == 5)
+ blocknum = V4L2_RDS_BLOCK_INVALID;
tmp = blocknum;
tmp |= blocknum << 3; /* Received offset == Offset Name (OK ?) */
if ((tmpbuf[2] & 0x03) == 0x03)
- tmp |= 0x80; /* uncorrectable error */
+ tmp |= V4L2_RDS_BLOCK_ERROR; /* uncorrectable error */
else if ((tmpbuf[2] & 0x03) != 0x00)
- tmp |= 0x40; /* corrected error */
+ tmp |= V4L2_RDS_BLOCK_CORRECTED; /* corrected error */
tmpbuf[2] = tmp; /* Is this enough ? Should we also check other bits ? */
spin_lock_irqsave(&s->lock, flags);
@@ -340,14 +352,14 @@ static void saa6588_work(struct work_struct *work)
schedule_delayed_work(&s->work, msecs_to_jiffies(20));
}
-static int saa6588_configure(struct saa6588 *s)
+static void saa6588_configure(struct saa6588 *s)
{
struct i2c_client *client = v4l2_get_subdevdata(&s->sd);
unsigned char buf[3];
int rc;
buf[0] = cSyncRestart;
- if (rbds)
+ if (mmbs)
buf[0] |= cProcessingModeRBDS;
buf[1] = cFlywheelDefault;
@@ -393,8 +405,6 @@ static int saa6588_configure(struct saa6588 *s)
rc = i2c_master_send(client, buf, 3);
if (rc != 3)
printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc);
-
- return 0;
}
/* ---------------------------------------------------------------------- */
@@ -435,6 +445,24 @@ static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
return 0;
}
+static int saa6588_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+ struct saa6588 *s = to_saa6588(sd);
+
+ vt->capability |= V4L2_TUNER_CAP_RDS;
+ if (s->sync)
+ vt->rxsubchans |= V4L2_TUNER_SUB_RDS;
+ return 0;
+}
+
+static int saa6588_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+ struct saa6588 *s = to_saa6588(sd);
+
+ saa6588_configure(s);
+ return 0;
+}
+
static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -449,8 +477,14 @@ static const struct v4l2_subdev_core_ops saa6588_core_ops = {
.ioctl = saa6588_ioctl,
};
+static const struct v4l2_subdev_tuner_ops saa6588_tuner_ops = {
+ .g_tuner = saa6588_g_tuner,
+ .s_tuner = saa6588_s_tuner,
+};
+
static const struct v4l2_subdev_ops saa6588_ops = {
.core = &saa6588_core_ops,
+ .tuner = &saa6588_tuner_ops,
};
/* ---------------------------------------------------------------------- */
diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c
index da73430ad..e466afd18 100644
--- a/linux/drivers/media/video/saa7134/saa7134-core.c
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c
@@ -1073,8 +1073,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
sd = v4l2_i2c_new_probed_subdev_addr(&dev->v4l2_dev,
&dev->i2c_adap, "saa6588", "saa6588",
saa7134_boards[dev->board].rds_addr);
- if (sd)
+ if (sd) {
printk(KERN_INFO "%s: found RDS decoder\n", dev->name);
+ dev->has_rds = 1;
+ }
}
request_submodules(dev);
diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c
index e7f78fcb8..5be072c57 100644
--- a/linux/drivers/media/video/saa7134/saa7134-video.c
+++ b/linux/drivers/media/video/saa7134/saa7134-video.c
@@ -1826,6 +1826,8 @@ static int saa7134_querycap(struct file *file, void *priv,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_TUNER;
+ if (dev->has_rds)
+ cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
if (saa7134_no_overlay <= 0)
cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h
index 454802e73..be5abf059 100644
--- a/linux/drivers/media/video/saa7134/saa7134.h
+++ b/linux/drivers/media/video/saa7134/saa7134.h
@@ -544,6 +544,7 @@ struct saa7134_dev {
struct i2c_adapter i2c_adap;
struct i2c_client i2c_client;
unsigned char eedata[256];
+ int has_rds;
/* video overlay */
struct v4l2_framebuffer ovbuf;
diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h
index ee6458f74..b5c4f7295 100644
--- a/linux/include/linux/videodev2.h
+++ b/linux/include/linux/videodev2.h
@@ -1185,6 +1185,7 @@ struct v4l2_modulator {
#define V4L2_TUNER_CAP_LANG2 0x0020
#define V4L2_TUNER_CAP_SAP 0x0020
#define V4L2_TUNER_CAP_LANG1 0x0040
+#define V4L2_TUNER_CAP_RDS 0x0080
/* Flags for the 'rxsubchans' field */
#define V4L2_TUNER_SUB_MONO 0x0001
@@ -1192,6 +1193,7 @@ struct v4l2_modulator {
#define V4L2_TUNER_SUB_LANG2 0x0004
#define V4L2_TUNER_SUB_SAP 0x0004
#define V4L2_TUNER_SUB_LANG1 0x0008
+#define V4L2_TUNER_SUB_RDS 0x0010
/* Values for the 'audmode' field */
#define V4L2_TUNER_MODE_MONO 0x0000
@@ -1217,6 +1219,27 @@ struct v4l2_hw_freq_seek {
};
/*
+ * R D S
+ */
+
+struct v4l2_rds_data {
+ __u8 lsb;
+ __u8 msb;
+ __u8 block;
+} __attribute__ ((packed));
+
+#define V4L2_RDS_BLOCK_MSK 0x7
+#define V4L2_RDS_BLOCK_A 0
+#define V4L2_RDS_BLOCK_B 1
+#define V4L2_RDS_BLOCK_C 2
+#define V4L2_RDS_BLOCK_D 3
+#define V4L2_RDS_BLOCK_C_ALT 4
+#define V4L2_RDS_BLOCK_INVALID 7
+
+#define V4L2_RDS_BLOCK_CORRECTED 0x40
+#define V4L2_RDS_BLOCK_ERROR 0x80
+
+/*
* A U D I O
*/
struct v4l2_audio {
diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp
index 309e14312..6f6b5e2f8 100644
--- a/v4l2-apps/util/v4l2-ctl.cpp
+++ b/v4l2-apps/util/v4l2-ctl.cpp
@@ -956,6 +956,8 @@ static std::string rxsubchans2s(int rxsubchans)
s += "lang1 ";
if (rxsubchans & V4L2_TUNER_SUB_LANG2)
s += "lang2 ";
+ if (rxsubchans & V4L2_TUNER_SUB_RDS)
+ s += "rds ";
return s;
}
@@ -990,6 +992,8 @@ static std::string tcap2s(unsigned cap)
s += "lang1 ";
if (cap & V4L2_TUNER_CAP_LANG2)
s += "lang2 ";
+ if (cap & V4L2_TUNER_CAP_RDS)
+ s += "rds ";
return s;
}
diff --git a/v4l2-spec/biblio.sgml b/v4l2-spec/biblio.sgml
index b013ece1d..afc8a0dd2 100644
--- a/v4l2-spec/biblio.sgml
+++ b/v4l2-spec/biblio.sgml
@@ -158,54 +158,23 @@ Signal - NTSC for Studio Applications"</title>
1125-Line High-Definition Production"</title>
</biblioentry>
- <biblioentry id="v4l">
- <abbrev>V4L</abbrev>
- <authorgroup>
- <author>
- <firstname>Alan</firstname>
- <surname>Cox</surname>
- <affiliation>
- <orgname>Red Hat, Inc.</orgname>
- <address>
- <email>alan@redhat.com</email>
- </address>
- </affiliation>
- </author>
- </authorgroup>
- <title>Video4Linux API Specification</title>
- <abstract>
- <para>This file is part of the Linux kernel sources under
-<filename>Documentation/video4linux</filename>.</para>
- </abstract>
- </biblioentry>
-
- <biblioentry id="v4lprog">
- <abbrev>V4LPROG</abbrev>
- <authorgroup>
- <author>
- <firstname>Alan</firstname>
- <surname>Cox</surname>
- <affiliation>
- <orgname>Red Hat, Inc.</orgname>
- <address>
- <email>alan@redhat.com</email>
- </address>
- </affiliation>
- </author>
- </authorgroup>
- <title>Video4Linux Programming (a.k.a. The Video4Linux
-Book)</title>
- <abstract>
- <para>About V4L <emphasis>driver</emphasis> programming. This
-book is part of the Linux kernel DocBook documentation, for example at
-<ulink url="http://kernelnewbies.org/documents/">
-http://kernelnewbies.org/documents/</ulink>. SGML sources are included
-in the kernel sources.</para>
- </abstract>
- <copyright>
- <year>2000</year>
- <holder>Alan Cox</holder>
- </copyright>
+ <biblioentry id="en50067">
+ <abbrev>EN&nbsp;50067</abbrev>
+ <authorgroup>
+ <corpauthor>European Committee for Electrotechnical Standardization
+(<ulink url="http://www.cenelec.eu">http://www.cenelec.eu</ulink>)</corpauthor>
+ </authorgroup>
+ <title>Specification of the radio data system (RDS) for VHF/FM sound broadcasting
+in the frequency range from 87,5 to 108,0 MHz</title>
+ </biblioentry>
+
+ <biblioentry id="nrsc4">
+ <abbrev>NRSC-4</abbrev>
+ <authorgroup>
+ <corpauthor>National Radio Systems Committee
+(<ulink url="http://www.nrscstandards.org">http://www.nrscstandards.org</ulink>)</corpauthor>
+ </authorgroup>
+ <title>NTSC-4: United States RBDS Standard</title>
</biblioentry>
</bibliography>
diff --git a/v4l2-spec/compat.sgml b/v4l2-spec/compat.sgml
index 94713023d..c1c725f35 100644
--- a/v4l2-spec/compat.sgml
+++ b/v4l2-spec/compat.sgml
@@ -1273,9 +1273,8 @@ also the size of the structure changed, which is encoded in the ioctl
request code, thus older V4L2 devices will respond with an &EINVAL; to
the new &VIDIOC-QUERYCAP; ioctl.</para>
- <para>There are new fields to identify the driver, a new (as
-of yet unspecified) device function
-<constant>V4L2_CAP_RDS_CAPTURE</constant>, the
+ <para>There are new fields to identify the driver, a new RDS
+device function <constant>V4L2_CAP_RDS_CAPTURE</constant>, the
<constant>V4L2_CAP_AUDIO</constant> flag indicates if the device has
any audio connectors, another I/O capability
<constant>V4L2_CAP_ASYNCIO</constant> can be flagged. In response to
@@ -2294,6 +2293,15 @@ was renamed to <structname id=v4l2-chip-ident-old>v4l2_chip_ident_old</structnam
</listitem>
</orderedlist>
</section>
+ <section>
+ <title>V4L2 in Linux 2.6.32</title>
+ <orderedlist>
+ <listitem>
+ <para>Finalized the RDS capture API. See <xref linkend="rds"> for
+more information.</para>
+ </listitem>
+ </orderedlist>
+ </section>
</section>
<section id="other">
diff --git a/v4l2-spec/dev-rds.sgml b/v4l2-spec/dev-rds.sgml
index 07bfd4c65..8f357d9f0 100644
--- a/v4l2-spec/dev-rds.sgml
+++ b/v4l2-spec/dev-rds.sgml
@@ -2,38 +2,154 @@
<para>The Radio Data System transmits supplementary
information in binary format, for example the station name or travel
-information, on a inaudible audio subcarrier of a radio program. This
-interface aims at devices capable of receiving and decoding RDS
+information, on an inaudible audio subcarrier of a radio program. This
+interface is aimed at devices capable of receiving and decoding RDS
information.</para>
- <para>The V4L API defines its RDS API as follows.</para>
-
- <para>From radio devices supporting it, RDS data can be read
-with the &func-read; function. The data is packed in groups of three,
-as follows:<orderedlist>
- <listitem>
- <para>First Octet Least Significant Byte of RDS Block</para>
- </listitem>
- <listitem>
- <para>Second Octet Most Significant Byte of RDS Block</para>
- </listitem>
- <listitem>
- <para>Third Octet Bit 7: Error bit. Indicates that an
-uncorrectable error occurred during reception of this block. Bit 6:
-Corrected bit. Indicates that an error was corrected for this data
-block. Bits 5-3: Received Offset. Indicates the offset received by the
-sync system. Bits 2-0: Offset Name. Indicates the offset applied to
-this data.</para>
- </listitem>
- </orderedlist></para>
-
- <para>It was argued <!-- video4linux-list@redhat.com
-on 12 Nov 2002, subject "RDS/RBDS" --> the RDS API should be
-extended before integration into V4L2, no new API has been devised yet.
-Please write to the linux-media mailing list for discussion: &v4l-ml;.
-Meanwhile no V4L2 driver should set the
-<constant>V4L2_CAP_RDS_CAPTURE</constant> capability flag.</para>
+ <para>For more information see the core RDS standard <xref linkend="en50067">
+and the RBDS standard <xref linkend="nrsc4">.</para>
+ <para>Note that the RBDS standard as is used in the USA is almost identical
+to the RDS standard. Any RDS decoder can also handle RBDS. Only some of the fields
+have slightly different meanings. See the RBDS standard for more information.</para>
+
+ <para>The RBDS standard also specifies support for MMBS (Modified Mobile Search).
+This is a proprietary format which seems to be discontinued. The RDS interface does not
+support this format. Should support for MMBS (or the so-called 'E blocks' in general)
+be needed, then please contact the linux-media mailing list: &v4l-ml;.</para>
+
+ <section>
+ <title>Querying Capabilities</title>
+
+ <para>Devices supporting the RDS capturing API
+set the <constant>V4L2_CAP_RDS_CAPTURE</constant> flag in
+the <structfield>capabilities</structfield> field of &v4l2-capability;
+returned by the &VIDIOC-QUERYCAP; ioctl.</para>
+
+ <para>Any tuner that supports RDS will set the
+<constant>V4L2_TUNER_CAP_RDS</constant> flag in the <structfield>capability</structfield>
+field of &v4l2-tuner;.</para>
+
+ <para>Whether an RDS signal is present can be detected by looking at
+the <structfield>rxsubchans</structfield> field of &v4l2-tuner;: the
+<constant>V4L2_TUNER_SUB_RDS</constant> will be set if RDS data was detected.</para>
+
+ </section>
+
+ <section>
+ <title>Reading RDS data</title>
+
+ <para>RDS data can be read from the radio device
+with the &func-read; function. The data is packed in groups of three bytes,
+as follows:</para>
+ <table frame="none" pgwide="1" id="v4l2-rds-data">
+ <title>struct
+<structname>v4l2_rds_data</structname></title>
+ <tgroup cols="3">
+ <colspec colname="c1" colwidth="1*">
+ <colspec colname="c2" colwidth="1*">
+ <colspec colname="c3" colwidth="5*">
+ <tbody valign="top">
+ <row>
+ <entry>__u8</entry>
+ <entry><structfield>lsb</structfield></entry>
+ <entry>Least Significant Byte of RDS Block</entry>
+ </row>
+ <row>
+ <entry>__u8</entry>
+ <entry><structfield>msb</structfield></entry>
+ <entry>Most Significant Byte of RDS Block</entry>
+ </row>
+ <row>
+ <entry>__u8</entry>
+ <entry><structfield>block</structfield></entry>
+ <entry>Block description</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table frame="none" pgwide="1" id="v4l2-rds-block">
+ <title>Block description</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*">
+ <colspec colname="c2" colwidth="5*">
+ <tbody valign="top">
+ <row>
+ <entry>Bits 0-2</entry>
+ <entry>Block (aka offset) of the received data.</entry>
+ </row>
+ <row>
+ <entry>Bits 3-5</entry>
+ <entry>Deprecated. Currently identical to bits 0-2. Do not use these bits.</entry>
+ </row>
+ <row>
+ <entry>Bit 6</entry>
+ <entry>Corrected bit. Indicates that an error was corrected for this data block.</entry>
+ </row>
+ <row>
+ <entry>Bit 7</entry>
+ <entry>Error bit. Indicates that an uncorrectable error occurred during reception of this block.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="none" pgwide="1" id="v4l2-rds-block-codes">
+ <title>Block defines</title>
+ <tgroup cols="3">
+ <colspec colname="c1" colwidth="1*">
+ <colspec colname="c2" colwidth="1*">
+ <colspec colname="c3" colwidth="5*">
+ <tbody valign="top">
+ <row>
+ <entry>V4L2_RDS_BLOCK_MSK</entry>
+ <entry>7</entry>
+ <entry>Mask for bits 0-2 to get the block ID.</entry>
+ </row>
+ <row>
+ <entry>V4L2_RDS_BLOCK_A</entry>
+ <entry>0</entry>
+ <entry>Block A.</entry>
+ </row>
+ <row>
+ <entry>V4L2_RDS_BLOCK_B</entry>
+ <entry>1</entry>
+ <entry>Block B.</entry>
+ </row>
+ <row>
+ <entry>V4L2_RDS_BLOCK_C</entry>
+ <entry>2</entry>
+ <entry>Block C.</entry>
+ </row>
+ <row>
+ <entry>V4L2_RDS_BLOCK_D</entry>
+ <entry>3</entry>
+ <entry>Block D.</entry>
+ </row>
+ <row>
+ <entry>V4L2_RDS_BLOCK_C_ALT</entry>
+ <entry>4</entry>
+ <entry>Block C'.</entry>
+ </row>
+ <row>
+ <entry>V4L2_RDS_BLOCK_INVALID</entry>
+ <entry>7</entry>
+ <entry>An invalid block.</entry>
+ </row>
+ <row>
+ <entry>V4L2_RDS_BLOCK_CORRECTED</entry>
+ <entry>0x40</entry>
+ <entry>A bit error was detected but corrected.</entry>
+ </row>
+ <row>
+ <entry>V4L2_RDS_BLOCK_ERROR</entry>
+ <entry>0x80</entry>
+ <entry>An incorrectable error occurred.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
<!--
Local Variables:
diff --git a/v4l2-spec/v4l2.sgml b/v4l2-spec/v4l2.sgml
index 470793d29..815e96ab5 100644
--- a/v4l2-spec/v4l2.sgml
+++ b/v4l2-spec/v4l2.sgml
@@ -131,6 +131,13 @@ structs, ioctls) must be noted in more detail in the history chapter
applications. -->
<revision>
+ <revnumber>0.26</revnumber>
+ <date>2009-06-15</date>
+ <authorinitials>hv</authorinitials>
+ <revremark>Finalized the RDS capture API.</revremark>
+ </revision>
+
+ <revision>
<revnumber>0.25</revnumber>
<date>2009-01-18</date>
<authorinitials>hv</authorinitials>
diff --git a/v4l2-spec/vidioc-g-tuner.sgml b/v4l2-spec/vidioc-g-tuner.sgml
index d5d379838..eb0b89e9a 100644
--- a/v4l2-spec/vidioc-g-tuner.sgml
+++ b/v4l2-spec/vidioc-g-tuner.sgml
@@ -120,9 +120,9 @@ field is not quite clear.--></para></entry>
to decode audio subprograms. They will <emphasis>not</emphasis>
change, for example with the current video standard.</para><para>When
the structure refers to a radio tuner only the
-<constant>V4L2_TUNER_CAP_LOW</constant> and
-<constant>V4L2_TUNER_CAP_STEREO</constant> flags can be
-set.</para></entry>
+<constant>V4L2_TUNER_CAP_LOW</constant>,
+<constant>V4L2_TUNER_CAP_STEREO</constant> and
+<constant>V4L2_TUNER_CAP_RDS</constant> flags can be set.</para></entry>
</row>
<row>
<entry>__u32</entry>
@@ -312,6 +312,12 @@ carrier for a monaural secondary language. Only
supports the <constant>V4L2_STD_NTSC_M</constant> video
standard.</para><!-- FIXME what if PAL+NTSC and Bi but not SAP? --></entry>
</row>
+ <row>
+ <entry><constant>V4L2_TUNER_CAP_RDS</constant></entry>
+ <entry>0x0080</entry>
+ <entry>RDS capture is supported. This capability is only valid for
+radio tuners.</entry>
+ </row>
</tbody>
</tgroup>
</table>
@@ -353,6 +359,11 @@ bilingual audio signal (or a second audio program).</entry>
<constant>V4L2_TUNER_SUB_SAP</constant> flag applies when the
current video standard is <constant>V4L2_STD_NTSC_M</constant>.</entry>
</row>
+ <row>
+ <entry><constant>V4L2_TUNER_SUB_RDS</constant></entry>
+ <entry>0x0010</entry>
+ <entry>The tuner receives an RDS channel.</entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/v4l2-spec/vidioc-querycap.sgml b/v4l2-spec/vidioc-querycap.sgml
index 2715289d8..4a741f5e9 100644
--- a/v4l2-spec/vidioc-querycap.sgml
+++ b/v4l2-spec/vidioc-querycap.sgml
@@ -184,7 +184,7 @@ data.</entry>
<row>
<entry><constant>V4L2_CAP_RDS_CAPTURE</constant></entry>
<entry>0x00000100</entry>
- <entry>[to be defined]</entry>
+ <entry>The device supports the <link linkend="rds">RDS</link> interface.</entry>
</row>
<row>
<entry><constant>V4L2_CAP_VIDEO_OUTPUT_OVERLAY</constant></entry>