linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFCv3 00/10] Add SDR at V4L2 API
@ 2013-04-21 19:00 Mauro Carvalho Chehab
  2013-04-21 19:00 ` [PATCH RFCv3 01/10] [media] Add initial SDR support " Mauro Carvalho Chehab
                   ` (10 more replies)
  0 siblings, 11 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

This is a version 3 of the V4L2 API bits to support Software Digital
Radio (SDR).

Changes from version 2:

	- Patches got better described and named;
	- Merged all SDR analog TV into just one field;
	- Documented what parts of the [RFC v2013-04-11] SDR API
	  REQUIREMENT SPECIFICATION are being addressed on the
	  patches that touch on the V4L2 external API.

With regards to the [RFC v2013-04-11] SDR requirements spec[1], v3
implements:

	- operation mode inquire (Rx/Tx)
		- implemented via VIDIOC_QUERYCAP;
		- get/set doesn't make sense, as different devnodes
		  are used for RX and TX;
	- sampling resolution
		- implemented via VIDIOC_ENUM_FMT/VIDIOC_G_FMT/VIDIOC_S_FMT.
	- sampling rate
		- get/set - implemented via VIDIOC_G_TUNER/VIDIOC_S_TUNER.
		- inquire HW - TODO (planning is to also use the same
		  ioctl's for it);
		- It may make sense to move it out of TUNER ioctl, as
		  this is actually ADC/DAC settings. For the initial
		  tests, I'll likely use as is, but IMO, the beter is to
		  split it out of VIDIOC_G_TUNER/VIDIOC_S_TUNER.
	- inversion
		- TODO. If needed, probably will use VIDIOC_G_TUNER.
	- RF frequency
		- implemented using VIDIOC_S_FREQUENCY/VIDIOC_G_FREQUENCY
		- scale: 62.5 Hz.
		- TODO: add a lower scale, for very low freqs.
	- IF frequency
		- implemented via VIDIOC_G_TUNER/VIDIOC_S_TUNER.
	- tuner lock (frequency synthesizer / PLL)
		- TODO. May eventually use tuner->strength
	- tuner gains
		- TODO (V4L2 controls).
	- enable/disable auto gain
		- TODO (V4L2 controls).
	- tuner filters
		- TODO (V4L2 controls).
	- pass RF standard to tuner?
		- Partially implemented. It doesn't pass V4L2 analog TV
		  types yet.
		- TODO: add VIDIOC_S_STD support for SDR radio
	- antenna switch
		- implemented via VIDIOC_G_TUNER/VIDIOC_S_TUNER.
	- external LNA
		- TODO (maybe there's already a V4L2 control for it)
	- device locking between multiple APIs
		- TODO (well, there are resource locking already between
		 	DVB and V4L at driver level)

[1] http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/63323

TODO:
	- check if VB2 require changes (might require trivial ones, due
	  to the new buffer type);

	- add a SDR driver testing the new features - likely a cx88 driver,
but as cx88 doesn't use VB2, I might use some other driver. The advantage
of using cx88 is that it has 2 ADC, one baseband and another IF that can
be used at the same time, 8-bits or 10-bits and up to ~35 MHz of
sampling rate.

Mauro Carvalho Chehab (10):
  [media] Add initial SDR support at V4L2 API
  [media] videodev2.h: Remove the unused old V4L1 buffer types
  [media] V4L2 api: Add a buffer capture type for SDR
  [media] V4L2 sdr API: Add fields for VIDIOC_[G|S]_TUNER
  [media] v4l2-ioctl: Add tuner ioctl support for SDR radio type
  [media] tuner-core: consider SDR as radio
  [media] tuner-core: add SDR support for g_tuner
  [media] tuner-core: store tuner ranges at tuner struct
  [media] tuner-core: add support to get the tuner frequency range
  [media] tuner-core: add support for SDR set_tuner

 Documentation/DocBook/media/v4l/common.xml         |  35 +++
 Documentation/DocBook/media/v4l/dev-capture.xml    |  26 +-
 Documentation/DocBook/media/v4l/io.xml             |   6 +
 Documentation/DocBook/media/v4l/pixfmt.xml         |  41 +++
 Documentation/DocBook/media/v4l/v4l2.xml           |   1 +
 Documentation/DocBook/media/v4l/vidioc-g-tuner.xml |  30 ++-
 .../DocBook/media/v4l/vidioc-querycap.xml          |   7 +
 drivers/media/dvb-core/dvb_frontend.h              |   2 +
 drivers/media/tuners/tuner-xc2028.c                |   2 +
 drivers/media/v4l2-core/tuner-core.c               | 297 ++++++++++++++-------
 drivers/media/v4l2-core/v4l2-dev.c                 |   3 +
 drivers/media/v4l2-core/v4l2-ioctl.c               | 121 +++++++--
 include/media/v4l2-dev.h                           |   3 +-
 include/media/v4l2-ioctl.h                         |   8 +
 include/uapi/linux/videodev2.h                     |  79 ++++--
 15 files changed, 503 insertions(+), 158 deletions(-)

-- 
1.8.1.4


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 01/10] [media] Add initial SDR support at V4L2 API
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-22  6:56   ` Hans Verkuil
  2013-04-21 19:00 ` [PATCH RFCv3 02/10] [media] videodev2.h: Remove the unused old V4L1 buffer types Mauro Carvalho Chehab
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Adds the basic API bits for Software Digital Radio (SDR) at
the V4L2 API.

A normal radio device is actually radio and hardware demod. As the demod
is in hardware, several things that are required for the demodulate the
signal (IF, bandwidth, sample rate, RF/IF filters, etc) are internal to
the device and aren't part of the API.

SDR radio, on the other hand, requires that every control needed by the
tuner to be exposed on userspace, as userspace needs to adjust the
software decoder to match it.

As proposed at:
	http://comments.gmane.org/gmane.linux.drivers.video-input-infrastructure/63123

Add a new device node for SDR devices, and a VIDIOC_QUERYCAP
capability (V4L2_CAP_SDR) to indicate that a devnode is SDR.

The stream output format also needs to be different, as it should
output sample data, instead of video streams. As we need to document
SDR, add one initial format there that will be later be used.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 Documentation/DocBook/media/v4l/common.xml         | 35 ++++++++++++++++++
 Documentation/DocBook/media/v4l/pixfmt.xml         | 41 ++++++++++++++++++++++
 Documentation/DocBook/media/v4l/v4l2.xml           |  1 +
 .../DocBook/media/v4l/vidioc-querycap.xml          |  7 ++++
 drivers/media/v4l2-core/v4l2-dev.c                 |  3 ++
 include/media/v4l2-dev.h                           |  3 +-
 include/uapi/linux/videodev2.h                     | 11 ++++++
 7 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/Documentation/DocBook/media/v4l/common.xml b/Documentation/DocBook/media/v4l/common.xml
index 1ddf354..f59c67d 100644
--- a/Documentation/DocBook/media/v4l/common.xml
+++ b/Documentation/DocBook/media/v4l/common.xml
@@ -513,6 +513,41 @@ the &v4l2-capability; returned by the &VIDIOC-QUERYCAP; ioctl when the
 device has one or more modulators.</para>
     </section>
 
+  <section id="sdr_tuner">
+    <title>Software Digital Radio (SDR) Tuners and Modulators</title>
+
+    <para>Those devices are special types of Radio devices that don't
+have any analog demodulator. Instead, it samples the radio IF or baseband
+and sends the samples for userspace to demodulate.</para>
+    <section>
+      <title>Tuners</title>
+
+      <para>SDR receivers can have one or more tuners sampling RF signals.
+Each tuner is associated with one or more inputs, depending on the number
+of RF connectors on the tuner. The <structfield>type</structfield> field of
+the respective &v4l2-input; returned by the &VIDIOC-ENUMINPUT; ioctl is set to
+<constant>V4L2_INPUT_TYPE_TUNER</constant> and its
+<structfield>tuner</structfield> field contains the index number of
+the tuner input.</para>
+
+<para>To query and change tuner properties applications use the
+&VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctl, respectively. The
+&v4l2-tuner; returned by <constant>VIDIOC_G_TUNER</constant> also
+contains signal status information applicable when the tuner of the
+current SDR input is queried. In order to change the SDR input,
+<constant>VIDIOC_S_TUNER</constant> with a new SDR index should be called.
+Drivers must support both ioctls and set the
+<constant>V4L2_CAP_SDR</constant> and <constant>V4L2_CAP_TUNER</constant>
+flags in the &v4l2-capability; returned by the &VIDIOC-QUERYCAP; ioctl.</para>
+    </section>
+
+    <section>
+      <title>Modulators</title>
+      <para>To be defined.</para>
+    </section>
+  </section>
+
+
     <section>
       <title>Radio Frequency</title>
 
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index 99b8d2a..e30075e 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -203,6 +203,47 @@ codes can be used.</entry>
   </table>
 </section>
 
+<section>
+  <title>SDR format struture</title>
+  <table pgwide="1" frame="none" id="v4l2-sdr-format">
+    <title>struct <structname>v4l2_sdr_format</structname></title>
+    <tgroup cols="3">
+      &cs-str;
+      <tbody valign="top">
+	<row>
+	  <entry>__u32</entry>
+	  <entry><structfield>sampleformat</structfield></entry>
+	  <entry>The format of the samples used by the SDR device.
+		 This is a little endian
+		 <link linkend="v4l2-sdr-fourcc">
+		 four character code</link>.</entry>
+	</row>
+      </tbody>
+    </tgroup>
+  </table>
+  <table pgwide="1" frame="none" id="v4l2-sdr-fourcc">
+    <title>SDR formats</title>
+    <tgroup cols="2">
+      &cs-str;
+      <tbody valign="top">
+	<row>
+	  <entry><constant>V4L2_SDR_FMT_I8Q8</constant></entry>
+	  <entry>Samples are given by a sequence of 8 bits in-phase(I) and
+		  8 bits quadrature (Q) samples taken from a
+		  <emphasis>signal(t)</emphasis> represented by the following
+		 expression:
+		 <informalequation>
+		 <alt>signal(t) = I cos(2&pi; f t) - Q sin(2&pi; f t)</alt>
+		 <mathphrase><emphasis>signal(t) = I * cos(2&pi; f<subscript>c</subscript> t) - Q * sin(2&pi; f<subscript>c</subscript> t)</emphasis></mathphrase>
+		 </informalequation>
+	  </entry>
+	</row>
+      </tbody>
+    </tgroup>
+  </table>
+
+</section>
+
   <section>
     <title>Standard Image Formats</title>
 
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index bfc93cd..b53a5cf 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -521,6 +521,7 @@ and discussions on the V4L mailing list.</revremark>
     <section id="ttx"> &sub-dev-teletext; </section>
     <section id="radio"> &sub-dev-radio; </section>
     <section id="rds"> &sub-dev-rds; </section>
+    <section id="sdr"> &sub-dev-sdr; </section>
     <section id="event"> &sub-dev-event; </section>
     <section id="subdev"> &sub-dev-subdev; </section>
   </chapter>
diff --git a/Documentation/DocBook/media/v4l/vidioc-querycap.xml b/Documentation/DocBook/media/v4l/vidioc-querycap.xml
index d5a3c97..97bb25a 100644
--- a/Documentation/DocBook/media/v4l/vidioc-querycap.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-querycap.xml
@@ -296,6 +296,13 @@ modulator programming see
 <xref linkend="tuner" />.</entry>
 	  </row>
 	  <row>
+	    <entry><constant>V4L2_CAP_SDR</constant></entry>
+	    <entry>0x00100000</entry>
+	    <entry>The device is a Software Digital Radio.
+		    For more information about SDR programming see
+<xref linkend="sdr_tuner" />.</entry>
+	  </row>
+	  <row>
 	    <entry><constant>V4L2_CAP_READWRITE</constant></entry>
 	    <entry>0x01000000</entry>
 	    <entry>The device supports the <link
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 5923c5d..a48e070 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -796,6 +796,9 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
 	case VFL_TYPE_SUBDEV:
 		name_base = "v4l-subdev";
 		break;
+	case VFL_TYPE_SDR:
+		name_base = "sdr";
+		break;
 	default:
 		printk(KERN_ERR "%s called with unknown type: %d\n",
 		       __func__, type);
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 95d1c91..95863bb 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -24,7 +24,8 @@
 #define VFL_TYPE_VBI		1
 #define VFL_TYPE_RADIO		2
 #define VFL_TYPE_SUBDEV		3
-#define VFL_TYPE_MAX		4
+#define VFL_TYPE_SDR		4
+#define VFL_TYPE_MAX		5
 
 /* Is this a receiver, transmitter or mem-to-mem? */
 /* Ignored for VFL_TYPE_SUBDEV. */
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 97fb392..4aa24c3 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -284,6 +284,7 @@ struct v4l2_capability {
 #define V4L2_CAP_AUDIO			0x00020000  /* has audio support */
 #define V4L2_CAP_RADIO			0x00040000  /* is a radio device */
 #define V4L2_CAP_MODULATOR		0x00080000  /* has a modulator */
+#define V4L2_CAP_SDR			0x00100000  /* is a SDR device */
 
 #define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
 #define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
@@ -1700,6 +1701,15 @@ struct v4l2_pix_format_mplane {
 	__u8				reserved[11];
 } __attribute__ ((packed));
 
+
+struct v4l2_sdr_format {
+	__u32				sampleformat;
+};
+
+/*      Sample format						Description  */
+
+#define V4L2_SDR_FMT_I8Q8	v4l2_fourcc('I', '8', 'Q', '8') /* I 8bits, Q 8bits  */
+
 /**
  * struct v4l2_format - stream data format
  * @type:	enum v4l2_buf_type; type of the data stream
@@ -1718,6 +1728,7 @@ struct v4l2_format {
 		struct v4l2_window		win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
 		struct v4l2_vbi_format		vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
 		struct v4l2_sliced_vbi_format	sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
+		struct v4l2_sdr_format		fmt;	 /* V4L2_BUF_TYPE_SDR_CAPTURE */
 		__u8	raw_data[200];                   /* user-defined */
 	} fmt;
 };
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 02/10] [media] videodev2.h: Remove the unused old V4L1 buffer types
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
  2013-04-21 19:00 ` [PATCH RFCv3 01/10] [media] Add initial SDR support " Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-22  6:56   ` Hans Verkuil
  2013-04-21 19:00 ` [PATCH RFCv3 03/10] [media] V4L2 api: Add a buffer capture type for SDR Mauro Carvalho Chehab
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Those aren't used anywhere for a long time. Drop it.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 include/uapi/linux/videodev2.h | 21 ---------------------
 1 file changed, 21 deletions(-)

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 4aa24c3..5d8ee92 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -72,27 +72,6 @@
 #define VIDEO_MAX_FRAME               32
 #define VIDEO_MAX_PLANES               8
 
-#ifndef __KERNEL__
-
-/* These defines are V4L1 specific and should not be used with the V4L2 API!
-   They will be removed from this header in the future. */
-
-#define VID_TYPE_CAPTURE	1	/* Can capture */
-#define VID_TYPE_TUNER		2	/* Can tune */
-#define VID_TYPE_TELETEXT	4	/* Does teletext */
-#define VID_TYPE_OVERLAY	8	/* Overlay onto frame buffer */
-#define VID_TYPE_CHROMAKEY	16	/* Overlay by chromakey */
-#define VID_TYPE_CLIPPING	32	/* Can clip */
-#define VID_TYPE_FRAMERAM	64	/* Uses the frame buffer memory */
-#define VID_TYPE_SCALES		128	/* Scalable */
-#define VID_TYPE_MONOCHROME	256	/* Monochrome only */
-#define VID_TYPE_SUBCAPTURE	512	/* Can capture subareas of the image */
-#define VID_TYPE_MPEG_DECODER	1024	/* Can decode MPEG streams */
-#define VID_TYPE_MPEG_ENCODER	2048	/* Can encode MPEG streams */
-#define VID_TYPE_MJPEG_DECODER	4096	/* Can decode MJPEG streams */
-#define VID_TYPE_MJPEG_ENCODER	8192	/* Can encode MJPEG streams */
-#endif
-
 /*
  *	M I S C E L L A N E O U S
  */
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 03/10] [media] V4L2 api: Add a buffer capture type for SDR
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
  2013-04-21 19:00 ` [PATCH RFCv3 01/10] [media] Add initial SDR support " Mauro Carvalho Chehab
  2013-04-21 19:00 ` [PATCH RFCv3 02/10] [media] videodev2.h: Remove the unused old V4L1 buffer types Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-22  7:00   ` Hans Verkuil
  2013-04-21 19:00 ` [PATCH RFCv3 04/10] [media] V4L2 sdr API: Add fields for VIDIOC_[G|S]_TUNER Mauro Carvalho Chehab
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

As SDR devices are not video, VBI or RDS devices, it needs
its own buffer type for capture.

Also, as discussed at:
	http://comments.gmane.org/gmane.linux.drivers.video-input-infrastructure/63123

It should be a way to enumerate and select the formats that the
hardware supports, as one hardware may accept more than one format
(cx88, for example, can likely support several different formats,
as it will depend on how the RISC code for it will be written).

So, add a a new stream type (V4L2_BUF_TYPE_SDR_CAPTURE) at the
V4L2 API, and the corresponding buffer function handlers.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 Documentation/DocBook/media/v4l/dev-capture.xml | 26 ++++++++++++--------
 Documentation/DocBook/media/v4l/io.xml          |  6 +++++
 drivers/media/v4l2-core/v4l2-ioctl.c            | 32 +++++++++++++++++++++++++
 include/media/v4l2-ioctl.h                      |  8 +++++++
 include/uapi/linux/videodev2.h                  |  3 ++-
 5 files changed, 64 insertions(+), 11 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/dev-capture.xml b/Documentation/DocBook/media/v4l/dev-capture.xml
index e1c5f94..7797d2d 100644
--- a/Documentation/DocBook/media/v4l/dev-capture.xml
+++ b/Documentation/DocBook/media/v4l/dev-capture.xml
@@ -44,7 +44,7 @@ all video capture devices.</para>
   </section>
 
   <section>
-    <title>Image Format Negotiation</title>
+    <title>Streaming Format Negotiation</title>
 
     <para>The result of a capture operation is determined by
 cropping and image format parameters. The former select an area of the
@@ -65,13 +65,18 @@ linkend="crop" />.</para>
 
     <para>To query the current image format applications set the
 <structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> or
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> and call the
-&VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill
-the &v4l2-pix-format; <structfield>pix</structfield> or the
-&v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member of the
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> or
+<constant>V4L2_BUF_TYPE_VIDEO_SDR_CAPTURE</constant> or
+and call the &VIDIOC-G-FMT; ioctl with a pointer to this structure.</para>
+
+<para>Video drivers fill the &v4l2-pix-format; <structfield>pix</structfield>
+or the &v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member of the
 <structfield>fmt</structfield> union.</para>
 
+<para>SDR drivers fill the &v4l2-sdr-format; <structfield>sdr</structfield>
+member of the <structfield>fmt</structfield> union.</para>
+
     <para>To request different parameters applications set the
 <structfield>type</structfield> field of a &v4l2-format; as above and
 initialize all fields of the &v4l2-pix-format;
@@ -87,8 +92,9 @@ adjust the parameters and finally return the actual parameters as
 without disabling I/O or possibly time consuming hardware
 preparations.</para>
 
-    <para>The contents of &v4l2-pix-format; and &v4l2-pix-format-mplane;
-are discussed in <xref linkend="pixfmt" />. See also the specification of the
+    <para>The contents of &v4l2-pix-format;, &v4l2-pix-format-mplane; and
+&v4l2-sdr-format; are discussed in <xref linkend="pixfmt" />.
+See also the specification of the
 <constant>VIDIOC_G_FMT</constant>, <constant>VIDIOC_S_FMT</constant>
 and <constant>VIDIOC_TRY_FMT</constant> ioctls for details. Video
 capture devices must implement both the
@@ -100,9 +106,9 @@ returns default parameters as <constant>VIDIOC_G_FMT</constant> does.
   </section>
 
   <section>
-    <title>Reading Images</title>
+    <title>Reading streams</title>
 
-    <para>A video capture device may support the <link
+    <para>A video capture device or an SDR device may support the <link
 linkend="rw">read() function</link> and/or streaming (<link
 linkend="mmap">memory mapping</link> or <link
 linkend="userp">user pointer</link>) I/O. See <xref
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index 2c4c068..0e69d31 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -1005,6 +1005,12 @@ should set this to 0.</entry>
 	    <entry>Buffer for video output overlay (OSD), see <xref
 		linkend="osd" />.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant></entry>
+	    <entry>8</entry>
+	    <entry>Buffer for Software Digital Radio (SDR) receivers, see <xref
+		linkend="sdr" />.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index f81bda1..fd853da 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -150,6 +150,7 @@ const char *v4l2_type_names[] = {
 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
 	[V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
+	[V4L2_BUF_TYPE_SDR_CAPTURE] = "sdr-cap",
 };
 EXPORT_SYMBOL(v4l2_type_names);
 
@@ -242,6 +243,7 @@ static void v4l_print_format(const void *arg, bool write_only)
 	const struct v4l2_pix_format_mplane *mp;
 	const struct v4l2_vbi_format *vbi;
 	const struct v4l2_sliced_vbi_format *sliced;
+	const struct v4l2_sdr_format *sdr;
 	const struct v4l2_window *win;
 	const struct v4l2_clip *clip;
 	unsigned i;
@@ -323,6 +325,14 @@ static void v4l_print_format(const void *arg, bool write_only)
 				sliced->service_lines[0][i],
 				sliced->service_lines[1][i]);
 		break;
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		sdr = &p->fmt.sdr;
+		pr_cont("format=%c%c%c%c\n",
+			(sdr->sampleformat & 0xff),
+			(sdr->sampleformat >>  8) & 0xff,
+			(sdr->sampleformat >> 16) & 0xff,
+			(sdr->sampleformat >> 24) & 0xff);
+		break;
 	}
 }
 
@@ -898,6 +908,7 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
 	bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI;
+	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
@@ -947,6 +958,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
 		if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out)
 			return 0;
 		break;
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap)
+			return 0;
+		break;
 	default:
 		break;
 	}
@@ -1066,6 +1081,10 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
 		if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane))
 			break;
 		return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_sdr_cap))
+			break;
+		return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1120,6 +1139,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
 		if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out))
 			break;
 		return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg);
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (unlikely(!is_rx || !ops->vidioc_g_fmt_sdr_cap))
+			break;
+		return ops->vidioc_g_fmt_sdr_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1184,6 +1207,10 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.sliced);
 		return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg);
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (unlikely(!is_rx || !ops->vidioc_s_fmt_sdr_cap))
+			break;
+		return ops->vidioc_s_fmt_sdr_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
@@ -1194,6 +1221,7 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
 	struct v4l2_format *p = arg;
 	struct video_device *vfd = video_devdata(file);
 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
@@ -1248,6 +1276,10 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
 			break;
 		CLEAR_AFTER_FIELD(p, fmt.sliced);
 		return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg);
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_try_fmt_sdr_cap))
+			break;
+		return ops->vidioc_try_fmt_sdr_cap(file, fh, arg);
 	}
 	return -EINVAL;
 }
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 931652f..731120a 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -40,6 +40,8 @@ struct v4l2_ioctl_ops {
 					      struct v4l2_fmtdesc *f);
 	int (*vidioc_enum_fmt_vid_out_mplane)(struct file *file, void *fh,
 					      struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_sdr_cap)(struct file *file, void *fh,
+				       struct v4l2_fmtdesc *f);
 
 	/* VIDIOC_G_FMT handlers */
 	int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
@@ -62,6 +64,8 @@ struct v4l2_ioctl_ops {
 					   struct v4l2_format *f);
 	int (*vidioc_g_fmt_vid_out_mplane)(struct file *file, void *fh,
 					   struct v4l2_format *f);
+	int (*vidioc_g_fmt_sdr_cap)(struct file *file, void *fh,
+				    struct v4l2_fmtdesc *f);
 
 	/* VIDIOC_S_FMT handlers */
 	int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
@@ -84,6 +88,8 @@ struct v4l2_ioctl_ops {
 					   struct v4l2_format *f);
 	int (*vidioc_s_fmt_vid_out_mplane)(struct file *file, void *fh,
 					   struct v4l2_format *f);
+	int (*vidioc_s_fmt_sdr_cap)(struct file *file, void *fh,
+				    struct v4l2_fmtdesc *f);
 
 	/* VIDIOC_TRY_FMT handlers */
 	int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
@@ -106,6 +112,8 @@ struct v4l2_ioctl_ops {
 					     struct v4l2_format *f);
 	int (*vidioc_try_fmt_vid_out_mplane)(struct file *file, void *fh,
 					     struct v4l2_format *f);
+	int (*vidioc_try_fmt_sdr_cap)(struct file *file, void *fh,
+				      struct v4l2_fmtdesc *f);
 
 	/* Buffer handlers */
 	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 5d8ee92..974c49d 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -139,6 +139,7 @@ enum v4l2_buf_type {
 #endif
 	V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
 	V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
+	V4L2_BUF_TYPE_SDR_CAPTURE          = 11,
 	/* Deprecated, do not use */
 	V4L2_BUF_TYPE_PRIVATE              = 0x80,
 };
@@ -1707,7 +1708,7 @@ struct v4l2_format {
 		struct v4l2_window		win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
 		struct v4l2_vbi_format		vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
 		struct v4l2_sliced_vbi_format	sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
-		struct v4l2_sdr_format		fmt;	 /* V4L2_BUF_TYPE_SDR_CAPTURE */
+		struct v4l2_sdr_format		sdr;	 /* V4L2_BUF_TYPE_SDR_CAPTURE */
 		__u8	raw_data[200];                   /* user-defined */
 	} fmt;
 };
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 04/10] [media] V4L2 sdr API: Add fields for VIDIOC_[G|S]_TUNER
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
                   ` (2 preceding siblings ...)
  2013-04-21 19:00 ` [PATCH RFCv3 03/10] [media] V4L2 api: Add a buffer capture type for SDR Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-22  7:11   ` Hans Verkuil
  2013-04-21 19:00 ` [PATCH RFCv3 05/10] [media] v4l2-ioctl: Add tuner ioctl support for SDR radio type Mauro Carvalho Chehab
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

As discussed at:
	http://comments.gmane.org/gmane.linux.drivers.video-input-infrastructure/63123

SDR radio require some other things at to set. VIDIOC_[G|S]_TUNER
is currently not enough.

I proposed there to create an extra ioctl for it, but the thing
is that VIDIOC_[G|S]_TUNER is meant to set what's needed to configure
the tuner. So, add there the missing bits to:
	- set/get the tuner sampling rate;
	- set/get the tuner low pass bandwidth filter;
	- get the tuner IF.

VIDIOC_[G|S]_TUNER already provides:
	- tuner input switch;
	- tuner input name;
	- tuner capability flags;
	- tuner range;
	- signal strength;
	- afc.

There are still 3 u32 reserved fields there that may be used for
SDR in the future, and may be neded at the final version.

For example, it may make sense to add a SDR flag with:
	- bandwidth inversion flag;
	- tuner PLL lock flag (or reuse signal strength for that).

It also makes sense to add sample_rate range there.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 Documentation/DocBook/media/v4l/vidioc-g-tuner.xml | 30 ++++++++++++++---
 drivers/media/tuners/tuner-xc2028.c                |  2 ++
 include/uapi/linux/videodev2.h                     | 38 ++++++++++++++++++++--
 3 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
index 6cc8201..b8a3bcf 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
@@ -200,9 +200,10 @@ audio</entry>
 <constant>_SAP</constant> flag is cleared in the
 <structfield>capability</structfield> field, the corresponding
 <constant>V4L2_TUNER_SUB_</constant> flag must not be set
-here.</para><para>This field is valid only if this is the tuner of the
+here.</para>
+<para>This field is valid only for if this is the tuner of the
 current video input, or when the structure refers to a radio
-tuner.</para></entry>
+tuner. This field is not used by SDR tuners.</para></entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -216,7 +217,7 @@ unless the requested mode is invalid or unsupported. See <xref
 the selected and received audio programs do not
 match.</para><para>Currently this is the only field of struct
 <structname>v4l2_tuner</structname> applications can
-change.</para></entry>
+change. This field is not used by SDR tuners.</para></entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -234,7 +235,28 @@ settles at zero, &ie; range is what? --></entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[4]</entry>
+	    <entry><structfield>sample_rate</structfield></entry>
+	    <entry spanname="hspan">Sampling rate used by a SDR tuner, in Hz.
+		    This value is valid only for SDR tuners.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>bandwidth</structfield></entry>
+	    <entry spanname="hspan">Bandwidth allowed by the SDR tuner
+		    low-pass saw filter, in Hz. This value is valid only for
+		    SDR tuners.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>int_freq</structfield></entry>
+	    <entry spanname="hspan">Intermediate Frequency (IF) used by
+	    the tuner, in Hz. This value is valid only for
+	    <constant>VIDIOC_G_TUNER</constant>, and it is valid only
+	    on SDR tuners.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[3]</entry>
 	    <entry spanname="hspan">Reserved for future extensions. Drivers and
 applications must set the array to zero.</entry>
 	  </row>
diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c
index 878d2c4..c61163f 100644
--- a/drivers/media/tuners/tuner-xc2028.c
+++ b/drivers/media/tuners/tuner-xc2028.c
@@ -1020,6 +1020,8 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
 	 * Maybe this might also be needed for DTV.
 	 */
 	switch (new_type) {
+	default:			/* SDR currently not supported */
+		goto ret;
 	case V4L2_TUNER_ANALOG_TV:
 		rc = send_seq(priv, {0x00, 0x00});
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 974c49d..c002030 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -160,6 +160,22 @@ enum v4l2_tuner_type {
 	V4L2_TUNER_RADIO	     = 1,
 	V4L2_TUNER_ANALOG_TV	     = 2,
 	V4L2_TUNER_DIGITAL_TV	     = 3,
+/*
+ * Even not decoding the signal, SDR tuners may require to adjust IF,
+ * low pass filters, center frequency, etc based on the signal envelope,
+ * and its bandwidth. While we might be using here the V4L2_STD_*
+ * types, plus DVB delsys, that doesn't seem to be the better thing to
+ * do, as:
+ *	1) it would require 64 bits for V4L2 std + 32 bits for DVB std;
+ *	2) non-TV types of envelopes won't work.
+ *
+ * So, add a separate enum to describe the possible types of SDR envelopes.
+ */
+	V4L2_TUNER_SDR_RADIO = 10,	/* Generic non-optimized Radio range */
+	V4L2_TUNER_SDR_ATV,		/* Optimize for Analog TV */
+	V4L2_TUNER_SDR_DTV_ATSC,	/* Optimize for Digital TV, ATSC */
+	V4L2_TUNER_SDR_DTV_DVBT,	/* Optimize for Digital TV, DVB-T */
+	V4L2_TUNER_SDR_DTV_ISDBT,	/* Optimize for Digital TV, ISDB-T */
 };
 
 enum v4l2_memory {
@@ -1291,6 +1307,7 @@ struct v4l2_querymenu {
 /*
  *	T U N I N G
  */
+
 struct v4l2_tuner {
 	__u32                   index;
 	__u8			name[32];
@@ -1298,11 +1315,26 @@ struct v4l2_tuner {
 	__u32			capability;
 	__u32			rangelow;
 	__u32			rangehigh;
-	__u32			rxsubchans;
-	__u32			audmode;
+
+	union {
+		/* non-SDR tuners */
+		struct {
+			__u32	rxsubchans;
+			__u32	audmode;
+		};
+		/* SDR tuners - audio demod data makes no sense here */
+		struct {
+			__u32	sample_rate;	/* Sample rate, in Hz */
+			__u32	bandwidth;	/* Bandwidth, in Hz */
+		};
+	};
+
 	__s32			signal;
 	__s32			afc;
-	__u32			reserved[4];
+
+		__u32	int_freq;	/* Read Only - IF used, in Hz */
+	/* non-SDR tuners */
+	__u32		reserved[3];
 };
 
 struct v4l2_modulator {
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 05/10] [media] v4l2-ioctl: Add tuner ioctl support for SDR radio type
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
                   ` (3 preceding siblings ...)
  2013-04-21 19:00 ` [PATCH RFCv3 04/10] [media] V4L2 sdr API: Add fields for VIDIOC_[G|S]_TUNER Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-21 19:00 ` [PATCH RFCv3 06/10] [media] tuner-core: consider SDR as radio Mauro Carvalho Chehab
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

The tuner ioctl's are optimized to handle internally the
differences between TV and normal AM/FM radio.

SDR is different than both, so it needs its own way of doing things.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 89 ++++++++++++++++++++++++++----------
 include/uapi/linux/videodev2.h       |  5 ++
 2 files changed, 70 insertions(+), 24 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index fd853da..f8bb171 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1296,6 +1296,19 @@ static int v4l_streamoff(const struct v4l2_ioctl_ops *ops,
 	return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg);
 }
 
+static u32 v4l_device_type(struct video_device *vfd)
+{
+	switch (vfd->vfl_type) {
+	case VFL_TYPE_RADIO:
+		return V4L2_TUNER_RADIO;
+	case VFL_TYPE_SDR:
+		/* May be overriden by the driver */
+		return V4L2_TUNER_SDR_RADIO;
+	default:
+		return V4L2_TUNER_ANALOG_TV;
+	}
+}
+
 static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
@@ -1303,8 +1316,7 @@ static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops,
 	struct v4l2_tuner *p = arg;
 	int err;
 
-	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
-			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+	p->type = v4l_device_type(vfd);
 	err = ops->vidioc_g_tuner(file, fh, p);
 	if (!err)
 		p->capability |= V4L2_TUNER_CAP_FREQ_BANDS;
@@ -1316,9 +1328,18 @@ static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,
 {
 	struct video_device *vfd = video_devdata(file);
 	struct v4l2_tuner *p = arg;
+	u32 type;
+
+	/*
+	 * For non-SDR devices, the type is defined by the dev type;
+	 * For SDR devices, if the type is not an SDR type return error
+	 */
+	type = v4l_device_type(vfd);
+	if (type != VFL_TYPE_SDR)
+		p->type = type;
+	else if (!V4L2_TUNER_IS_SDR(p->type))
+		return -EINVAL;
 
-	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
-			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	return ops->vidioc_s_tuner(file, fh, p);
 }
 
@@ -1340,8 +1361,7 @@ static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
 	struct video_device *vfd = video_devdata(file);
 	struct v4l2_frequency *p = arg;
 
-	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
-			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+	p->type = v4l_device_type(vfd);
 	return ops->vidioc_g_frequency(file, fh, p);
 }
 
@@ -1352,10 +1372,13 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
 	const struct v4l2_frequency *p = arg;
 	enum v4l2_tuner_type type;
 
-	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
-			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-	if (p->type != type)
+	type = v4l_device_type(vfd);
+	if (type != VFL_TYPE_SDR) {
+		if (p->type != type)
+			return -EINVAL;
+	} else if (!V4L2_TUNER_IS_SDR(p->type))
 		return -EINVAL;
+
 	return ops->vidioc_s_frequency(file, fh, p);
 }
 
@@ -1457,10 +1480,13 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
 	struct v4l2_hw_freq_seek *p = arg;
 	enum v4l2_tuner_type type;
 
-	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
-		V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-	if (p->type != type)
+	type = v4l_device_type(vfd);
+	if (type != VFL_TYPE_SDR) {
+		if (p->type != type)
+			return -EINVAL;
+	} else if (!V4L2_TUNER_IS_SDR(p->type))
 		return -EINVAL;
+
 	return ops->vidioc_s_hw_freq_seek(file, fh, p);
 }
 
@@ -1974,12 +2000,19 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
 	struct v4l2_frequency_band *p = arg;
 	enum v4l2_tuner_type type;
 	int err;
+	bool is_sdr;
 
-	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
-			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+	type = v4l_device_type(vfd);
+	if (type != VFL_TYPE_SDR) {
+		if (p->type != type)
+			return -EINVAL;
+		is_sdr = false;
+	} else {
+		if (!V4L2_TUNER_IS_SDR(type))
+			return -EINVAL;
+		is_sdr = true;
+	}
 
-	if (type != p->type)
-		return -EINVAL;
 	if (ops->vidioc_enum_freq_bands)
 		return ops->vidioc_enum_freq_bands(file, fh, p);
 	if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
@@ -1988,7 +2021,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
 			.type = type,
 		};
 
-		if (p->index)
+		if (p->index && !is_sdr)
 			return -EINVAL;
 		err = ops->vidioc_g_tuner(file, fh, &t);
 		if (err)
@@ -1996,16 +2029,15 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
 		p->capability = t.capability | V4L2_TUNER_CAP_FREQ_BANDS;
 		p->rangelow = t.rangelow;
 		p->rangehigh = t.rangehigh;
-		p->modulation = (type == V4L2_TUNER_RADIO) ?
-			V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
-		return 0;
+
+		goto ret;
 	}
 	if (is_valid_ioctl(vfd, VIDIOC_G_MODULATOR)) {
 		struct v4l2_modulator m = {
 			.index = p->tuner,
 		};
 
-		if (type != V4L2_TUNER_RADIO)
+		if (type == V4L2_TUNER_ANALOG_TV)
 			return -EINVAL;
 		if (p->index)
 			return -EINVAL;
@@ -2015,11 +2047,20 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
 		p->capability = m.capability | V4L2_TUNER_CAP_FREQ_BANDS;
 		p->rangelow = m.rangelow;
 		p->rangehigh = m.rangehigh;
-		p->modulation = (type == V4L2_TUNER_RADIO) ?
-			V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
-		return 0;
+		goto ret;
 	}
 	return -ENOTTY;
+ret:
+	if (is_sdr) {
+		/* With SDR, modulation type can be anything */
+		p->modulation = V4L2_BAND_MODULATION_ANY;
+		return 0;
+	}
+
+	p->modulation = (type == V4L2_TUNER_RADIO) ?
+		V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
+	return 0;
+
 }
 
 struct v4l2_ioctl_info {
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index c002030..e2cc369 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -176,8 +176,12 @@ enum v4l2_tuner_type {
 	V4L2_TUNER_SDR_DTV_ATSC,	/* Optimize for Digital TV, ATSC */
 	V4L2_TUNER_SDR_DTV_DVBT,	/* Optimize for Digital TV, DVB-T */
 	V4L2_TUNER_SDR_DTV_ISDBT,	/* Optimize for Digital TV, ISDB-T */
+	V4L2_TUNER_SDR_MAX
 };
 
+#define V4L2_TUNER_IS_SDR(type)					\
+	(((type) >= V4L2_TUNER_SDR_RADIO) || ((type) < V4L2_TUNER_SDR_MAX))
+
 enum v4l2_memory {
 	V4L2_MEMORY_MMAP             = 1,
 	V4L2_MEMORY_USERPTR          = 2,
@@ -1388,6 +1392,7 @@ struct v4l2_frequency {
 #define V4L2_BAND_MODULATION_VSB	(1 << 1)
 #define V4L2_BAND_MODULATION_FM		(1 << 2)
 #define V4L2_BAND_MODULATION_AM		(1 << 3)
+#define V4L2_BAND_MODULATION_ANY	(1 << 4)
 
 struct v4l2_frequency_band {
 	__u32	tuner;
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 06/10] [media] tuner-core: consider SDR as radio
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
                   ` (4 preceding siblings ...)
  2013-04-21 19:00 ` [PATCH RFCv3 05/10] [media] v4l2-ioctl: Add tuner ioctl support for SDR radio type Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-21 19:00 ` [PATCH RFCv3 07/10] [media] tuner-core: add SDR support for g_tuner Mauro Carvalho Chehab
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

There are several tests at tuner-core for radio. Extend it to
also cover SDR radio.

Some of the changes here may need to be reviewed, SDR support will
actually be implemented there.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/v4l2-core/tuner-core.c | 22 ++++++++++++----------
 include/uapi/linux/videodev2.h       |  3 +++
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index ddc9379..b97ec63 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -445,7 +445,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
 	   on analog tuners for PLL to properly work
 	 */
 	if (tune_now) {
-		if (V4L2_TUNER_RADIO == t->mode)
+		if (V4L2_TUNER_IS_RADIO(t->mode))
 			set_radio_freq(c, t->radio_freq);
 		else
 			set_tv_freq(c, t->tv_freq);
@@ -743,7 +743,7 @@ static int tuner_remove(struct i2c_client *client)
 static inline int check_mode(struct tuner *t, enum v4l2_tuner_type mode)
 {
 	int t_mode;
-	if (mode == V4L2_TUNER_RADIO)
+	if (V4L2_TUNER_IS_RADIO(mode))
 		t_mode = T_RADIO;
 	else
 		t_mode = T_ANALOG_TV;
@@ -791,7 +791,7 @@ static void set_freq(struct tuner *t, unsigned int freq)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
 
-	if (t->mode == V4L2_TUNER_RADIO) {
+	if (V4L2_TUNER_IS_RADIO(t->mode)) {
 		if (!freq)
 			freq = t->radio_freq;
 		set_radio_freq(client, freq);
@@ -1024,11 +1024,13 @@ static void tuner_status(struct dvb_frontend *fe)
 		p = "digital TV";
 		break;
 	case V4L2_TUNER_ANALOG_TV:
-	default:
 		p = "analog TV";
 		break;
+	default:
+		p = "SDR";
+		break;
 	}
-	if (t->mode == V4L2_TUNER_RADIO) {
+	if (V4L2_TUNER_IS_RADIO(t->mode)) {
 		freq = t->radio_freq / 16000;
 		freq_fraction = (t->radio_freq % 16000) * 100 / 16000;
 	} else {
@@ -1039,7 +1041,7 @@ static void tuner_status(struct dvb_frontend *fe)
 		   t->standby ? " on standby mode" : "");
 	tuner_info("Frequency:       %lu.%02lu MHz\n", freq, freq_fraction);
 	tuner_info("Standard:        0x%08lx\n", (unsigned long)t->std);
-	if (t->mode != V4L2_TUNER_RADIO)
+	if (!V4L2_TUNER_IS_RADIO(t->mode))
 		return;
 	if (fe_tuner_ops->get_status) {
 		u32 tuner_status;
@@ -1144,11 +1146,11 @@ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
 		u32 abs_freq;
 
 		fe_tuner_ops->get_frequency(&t->fe, &abs_freq);
-		f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
+		f->frequency = (V4L2_TUNER_IS_RADIO(t->mode)) ?
 			DIV_ROUND_CLOSEST(abs_freq * 2, 125) :
 			DIV_ROUND_CLOSEST(abs_freq, 62500);
 	} else {
-		f->frequency = (V4L2_TUNER_RADIO == f->type) ?
+		f->frequency = (V4L2_TUNER_IS_RADIO(f->type)) ?
 			t->radio_freq : t->tv_freq;
 	}
 	return 0;
@@ -1180,7 +1182,7 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 		if (!analog_ops->has_signal(&t->fe, &signal))
 			vt->signal = signal;
 	}
-	if (vt->type != V4L2_TUNER_RADIO) {
+	if (!V4L2_TUNER_IS_RADIO(vt->type)) {
 		vt->capability |= V4L2_TUNER_CAP_NORM;
 		vt->rangelow = tv_range[0] * 16;
 		vt->rangehigh = tv_range[1] * 16;
@@ -1224,7 +1226,7 @@ static int tuner_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 	if (set_mode(t, vt->type))
 		return 0;
 
-	if (t->mode == V4L2_TUNER_RADIO) {
+	if (V4L2_TUNER_IS_RADIO(t->mode)) {
 		t->audmode = vt->audmode;
 		/*
 		 * For radio audmode can only be mono or stereo. Map any
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index e2cc369..9d18af7 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -182,6 +182,9 @@ enum v4l2_tuner_type {
 #define V4L2_TUNER_IS_SDR(type)					\
 	(((type) >= V4L2_TUNER_SDR_RADIO) || ((type) < V4L2_TUNER_SDR_MAX))
 
+#define V4L2_TUNER_IS_RADIO(type)					\
+	(((type) == V4L2_TUNER_RADIO) || V4L2_TUNER_IS_SDR(type))
+
 enum v4l2_memory {
 	V4L2_MEMORY_MMAP             = 1,
 	V4L2_MEMORY_USERPTR          = 2,
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 07/10] [media] tuner-core: add SDR support for g_tuner
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
                   ` (5 preceding siblings ...)
  2013-04-21 19:00 ` [PATCH RFCv3 06/10] [media] tuner-core: consider SDR as radio Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-22  7:18   ` Hans Verkuil
  2013-04-21 19:00 ` [PATCH RFCv3 08/10] [media] tuner-core: store tuner ranges at tuner struct Mauro Carvalho Chehab
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Properly initialize the fields for VIDIOC_G_TUNER, if the
device is in SDR mode.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/v4l2-core/tuner-core.c | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index b97ec63..e54b5ae 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -1190,7 +1190,31 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	}
 
 	/* radio mode */
-	if (vt->type == t->mode) {
+	vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+
+	if (V4L2_TUNER_IS_SDR(vt->type)) {
+		vt->rangelow  = tv_range[0] * 16000;
+		vt->rangehigh = tv_range[1] * 16000;
+	else {
+		vt->rangelow = radio_range[0] * 16000;
+		vt->rangehigh = radio_range[1] * 16000;
+	}
+	/* Check if the radio device is active */
+	if (vt->type != t->mode)
+		return 0;
+
+	if (V4L2_TUNER_IS_SDR(vt->type)) {
+		if (fe_tuner_ops->get_bandwidth)
+			fe_tuner_ops->get_bandwidth(&t->fe,
+							&vt->bandwidth);
+		if (fe_tuner_ops->get_if_frequency)
+			fe_tuner_ops->get_if_frequency(&t->fe,
+							&vt->int_freq);
+		/*
+			* Sampe rate is not a tuner props - it is up to the
+			* bridge driver to fill it.
+			*/
+	} else {
 		vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
 		if (fe_tuner_ops->get_status) {
 			u32 tuner_status;
@@ -1203,9 +1227,6 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 		}
 		vt->audmode = t->audmode;
 	}
-	vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
-	vt->rangelow = radio_range[0] * 16000;
-	vt->rangehigh = radio_range[1] * 16000;
 
 	return 0;
 }
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 08/10] [media] tuner-core: store tuner ranges at tuner struct
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
                   ` (6 preceding siblings ...)
  2013-04-21 19:00 ` [PATCH RFCv3 07/10] [media] tuner-core: add SDR support for g_tuner Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-22  7:22   ` Hans Verkuil
  2013-04-21 19:00 ` [PATCH RFCv3 09/10] [media] tuner-core: add support to get the tuner frequency range Mauro Carvalho Chehab
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Instead of using global values for tuner ranges, store them
internally. That fixes the need of using a different range
for SDR radio, and will help to latter add a tuner ops to
retrieve the tuner range for SDR mode.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/v4l2-core/tuner-core.c | 59 ++++++++++++++++++++++--------------
 1 file changed, 37 insertions(+), 22 deletions(-)

diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index e54b5ae..abdcda4 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -67,8 +67,8 @@ static char secam[] = "--";
 static char ntsc[] = "-";
 
 module_param_named(debug, tuner_debug, int, 0644);
-module_param_array(tv_range, int, NULL, 0644);
-module_param_array(radio_range, int, NULL, 0644);
+module_param_array(tv_range, int, NULL, 0444);
+module_param_array(radio_range, int, NULL, 0444);
 module_param_string(pal, pal, sizeof(pal), 0644);
 module_param_string(secam, secam, sizeof(secam), 0644);
 module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
@@ -134,6 +134,8 @@ struct tuner {
 	unsigned int        type; /* chip type id */
 	void                *config;
 	const char          *name;
+
+	u32                 radio_range[2], tv_range[2], sdr_range[2];
 };
 
 /*
@@ -266,7 +268,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
 	struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
 	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 	unsigned char buffer[4];
-	int tune_now = 1;
+	int i, tune_now = 1;
 
 	if (type == UNSET || type == TUNER_ABSENT) {
 		tuner_dbg("tuner 0x%02x: Tuner type absent\n", c->addr);
@@ -451,6 +453,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
 			set_tv_freq(c, t->tv_freq);
 	}
 
+	/* Initializes the tuner ranges from modprobe parameters */
+	for (i = 0; i < 2; i++) {
+		t->radio_range[i] = radio_range[i] * 16000;
+		t->sdr_range[i] = tv_range[i] * 16000;
+		t->tv_range[i] = tv_range[i] * 16;
+	}
+
 	tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
 		  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
 		  t->mode_mask);
@@ -831,16 +840,16 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
 		tuner_warn("Tuner has no way to set tv freq\n");
 		return;
 	}
-	if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
+	if (freq < t->tv_range[0] || freq > t->tv_range[1]) {
 		tuner_dbg("TV freq (%d.%02d) out of range (%d-%d)\n",
-			   freq / 16, freq % 16 * 100 / 16, tv_range[0],
-			   tv_range[1]);
+			   freq / 16, freq % 16 * 100 / 16, t->tv_range[0] / 16,
+			   t->tv_range[1] / 16);
 		/* V4L2 spec: if the freq is not possible then the closest
 		   possible value should be selected */
-		if (freq < tv_range[0] * 16)
-			freq = tv_range[0] * 16;
+		if (freq < t->tv_range[0])
+			freq = t->tv_range[0];
 		else
-			freq = tv_range[1] * 16;
+			freq = t->tv_range[1];
 	}
 	params.frequency = freq;
 	tuner_dbg("tv freq set to %d.%02d\n",
@@ -957,7 +966,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
 {
 	struct tuner *t = to_tuner(i2c_get_clientdata(c));
 	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
-
+	u32 *range;
 	struct analog_parameters params = {
 		.mode      = t->mode,
 		.audmode   = t->audmode,
@@ -972,16 +981,22 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
 		tuner_warn("tuner has no way to set radio frequency\n");
 		return;
 	}
-	if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
+
+	if (V4L2_TUNER_IS_SDR(t->mode))
+		range = t->sdr_range;
+	else
+		range = t->radio_range;
+
+	if (freq < range[0] || freq > range[1]) {
 		tuner_dbg("radio freq (%d.%02d) out of range (%d-%d)\n",
 			   freq / 16000, freq % 16000 * 100 / 16000,
-			   radio_range[0], radio_range[1]);
+			   range[0] / 16000, range[1] / 16000);
 		/* V4L2 spec: if the freq is not possible then the closest
 		   possible value should be selected */
-		if (freq < radio_range[0] * 16000)
-			freq = radio_range[0] * 16000;
+		if (freq < range[0])
+			freq = range[0];
 		else
-			freq = radio_range[1] * 16000;
+			freq = range[1];
 	}
 	params.frequency = freq;
 	tuner_dbg("radio freq set to %d.%02d\n",
@@ -1184,8 +1199,8 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	}
 	if (!V4L2_TUNER_IS_RADIO(vt->type)) {
 		vt->capability |= V4L2_TUNER_CAP_NORM;
-		vt->rangelow = tv_range[0] * 16;
-		vt->rangehigh = tv_range[1] * 16;
+		vt->rangelow = t->tv_range[0];
+		vt->rangehigh = t->tv_range[1];
 		return 0;
 	}
 
@@ -1193,11 +1208,11 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
 
 	if (V4L2_TUNER_IS_SDR(vt->type)) {
-		vt->rangelow  = tv_range[0] * 16000;
-		vt->rangehigh = tv_range[1] * 16000;
-	else {
-		vt->rangelow = radio_range[0] * 16000;
-		vt->rangehigh = radio_range[1] * 16000;
+		vt->rangelow  = t->sdr_range[0];
+		vt->rangehigh = t->sdr_range[1];
+	} else {
+		vt->rangelow = t->radio_range[0];
+		vt->rangehigh = t->radio_range[1];
 	}
 	/* Check if the radio device is active */
 	if (vt->type != t->mode)
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 09/10] [media] tuner-core: add support to get the tuner frequency range
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
                   ` (7 preceding siblings ...)
  2013-04-21 19:00 ` [PATCH RFCv3 08/10] [media] tuner-core: store tuner ranges at tuner struct Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-21 19:00 ` [PATCH RFCv3 10/10] [media] tuner-core: add support for SDR set_tuner Mauro Carvalho Chehab
  2013-04-22  7:34 ` [PATCH RFCv3 00/10] Add SDR at V4L2 API Hans Verkuil
  10 siblings, 0 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

For SDR, the tuner range is different than TV or radio
ranges. Only the actual tuner driver knows what's the
range supported by the device. So, call the tuner to
get it, if the tuner supports. Otherwise, keep the TV
range, as is it broader than the radio one.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/dvb-core/dvb_frontend.h | 2 ++
 drivers/media/v4l2-core/tuner-core.c  | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
index 371b6ca..74a50e6 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -215,6 +215,8 @@ struct dvb_tuner_ops {
 	int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
 	int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
 	int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
+	int (*get_tuner_freq_range)(struct dvb_frontend *fe,
+				    u32 *min_freq, u32 *max_freq);
 
 #define TUNER_STATUS_LOCKED 1
 #define TUNER_STATUS_STEREO 2
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index abdcda4..28bbcad 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -460,6 +460,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
 		t->tv_range[i] = tv_range[i] * 16;
 	}
 
+	if (fe_tuner_ops->get_tuner_freq_range) {
+		u32 min, max;
+		fe_tuner_ops->get_tuner_freq_range(&t->fe, &min, &max);
+		t->sdr_range[0] = min / 16;
+		t->sdr_range[1] = max / 16;
+	}
+
 	tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
 		  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
 		  t->mode_mask);
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH RFCv3 10/10] [media] tuner-core: add support for SDR set_tuner
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
                   ` (8 preceding siblings ...)
  2013-04-21 19:00 ` [PATCH RFCv3 09/10] [media] tuner-core: add support to get the tuner frequency range Mauro Carvalho Chehab
@ 2013-04-21 19:00 ` Mauro Carvalho Chehab
  2013-04-22  7:34 ` [PATCH RFCv3 00/10] Add SDR at V4L2 API Hans Verkuil
  10 siblings, 0 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-21 19:00 UTC (permalink / raw)
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List

Most SDR devices use TV tuners. Those generally require
to know what is the type of the envelope, in order to
adjust their PLL's and filters.

Add support to tune them via tuner-core.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/v4l2-core/tuner-core.c | 220 ++++++++++++++++++++++-------------
 1 file changed, 141 insertions(+), 79 deletions(-)

diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index 28bbcad..2b9eed6 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -121,10 +121,12 @@ struct tuner {
 	struct list_head    list;
 
 	/* keep track of the current settings */
-	v4l2_std_id         std;
+	v4l2_std_id         std, sdr_std;
 	unsigned int        tv_freq;
 	unsigned int        radio_freq;
+	unsigned int        sdr_freq;
 	unsigned int        audmode;
+	u32                 bandwidth;
 
 	enum v4l2_tuner_type mode;
 	unsigned int        mode_mask; /* Combination of allowable modes */
@@ -142,8 +144,9 @@ struct tuner {
  * Function prototypes
  */
 
-static void set_tv_freq(struct i2c_client *c, unsigned int freq);
-static void set_radio_freq(struct i2c_client *c, unsigned int freq);
+static void set_freq(struct tuner *t, unsigned int freq);
+static void set_tv_freq(struct tuner *t, struct analog_parameters *params);
+static void set_radio_freq(struct tuner *t, struct analog_parameters *params);
 
 /*
  * tuner attach/detach logic
@@ -440,19 +443,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
 
 	t->mode_mask = new_mode_mask;
 
-	/* Some tuners require more initialization setup before use,
-	   such as firmware download or device calibration.
-	   trying to set a frequency here will just fail
-	   FIXME: better to move set_freq to the tuner code. This is needed
-	   on analog tuners for PLL to properly work
-	 */
-	if (tune_now) {
-		if (V4L2_TUNER_IS_RADIO(t->mode))
-			set_radio_freq(c, t->radio_freq);
-		else
-			set_tv_freq(c, t->tv_freq);
-	}
-
 	/* Initializes the tuner ranges from modprobe parameters */
 	for (i = 0; i < 2; i++) {
 		t->radio_range[i] = radio_range[i] * 16000;
@@ -466,6 +456,28 @@ static void set_type(struct i2c_client *c, unsigned int type,
 		t->sdr_range[0] = min / 16;
 		t->sdr_range[1] = max / 16;
 	}
+	/*
+	 * FIXME: It is possible that, for some SDR devices, the analog
+	 * standard needs to be better known. In this case, it should use
+	 * V4L2 VIDIOC_S_STD to change the content of t->sdr_std to reflect
+	 * what type of RF is expected.
+	 * Adding support for it would require additional changes at
+	 * v4l2-dev, as tuner-core needs to know if the request comes from
+	 * a SDR devnode or from an analog TV devnode, because, a TV s_std
+	 * ops cause the tuner to switch modes.
+	 */
+	t->sdr_std = V4L2_STD_ALL;
+
+	/*
+	 * Some tuners require more initialization setup before use,
+	 * such as firmware download or device calibration.
+	 * trying to set a frequency here will just fail
+	 *
+	 * FIXME: better to move set_freq to the tuner code. This is needed
+	 *	  on analog tuners for PLL to properly work
+	 */
+	if (tune_now)
+		set_freq(t, 0);
 
 	tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
 		  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
@@ -805,16 +817,81 @@ static int set_mode(struct tuner *t, enum v4l2_tuner_type mode)
  */
 static void set_freq(struct tuner *t, unsigned int freq)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
+	struct analog_parameters params;
+	struct dtv_frontend_properties *c = &t->fe.dtv_property_cache;
+	struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
+	bool is_analog = true;
 
-	if (V4L2_TUNER_IS_RADIO(t->mode)) {
+	if (t->type == UNSET) {
+		tuner_warn("tuner type not set\n");
+		return;
+	}
+
+	memset(&params, 0, sizeof(params));
+
+	switch (t->mode) {
+	case V4L2_TUNER_ANALOG_TV:
+		if (!freq)
+			freq = t->tv_freq;
+
+		params.mode      = t->mode;
+		params.audmode   = t->audmode;
+		params.std       = t->std;
+		params.frequency = freq;
+		set_tv_freq(t, &params);
+		t->tv_freq = params.frequency;
+		return;
+	case V4L2_TUNER_RADIO:
 		if (!freq)
 			freq = t->radio_freq;
-		set_radio_freq(client, freq);
+		params.mode      = V4L2_TUNER_RADIO;
+		params.audmode   = t->audmode;
+		params.frequency = freq;
+		set_radio_freq(t, &params);
+		t->radio_freq = params.frequency;
+		return;
+	case V4L2_TUNER_SDR_RADIO:
+		params.mode = V4L2_TUNER_RADIO;
+		break;
+	case V4L2_TUNER_SDR_ATV:
+		params.mode = V4L2_TUNER_ANALOG_TV;
+		params.std = t->sdr_std;
+		break;
+	case V4L2_TUNER_SDR_DTV_ATSC:
+		is_analog = false;
+		c->delivery_system = SYS_ATSC;
+		c->bandwidth_hz = 6000000;
+		break;
+	case V4L2_TUNER_SDR_DTV_DVBT:
+		is_analog = false;
+		c->delivery_system = SYS_DVBT;
+		c->bandwidth_hz = t->bandwidth;
+		break;
+	case V4L2_TUNER_SDR_DTV_ISDBT:
+		is_analog = false;
+		c->delivery_system = SYS_ISDBT;
+		c->bandwidth_hz = t->bandwidth;
+		break;
+	case V4L2_TUNER_DIGITAL_TV:
+	case V4L2_TUNER_SDR_MAX:
+		is_analog = false;
+		c->delivery_system = SYS_DVBT;
+		c->bandwidth_hz = 8000000;
+		break;
+	}
+
+	if (!freq)
+		freq = t->sdr_freq;
+	if (is_analog) {
+		params.frequency = freq;
+		set_radio_freq(t, &params);
+		t->sdr_freq = params.frequency;
 	} else {
-		if (!freq)
-			freq = t->tv_freq;
-		set_tv_freq(client, freq);
+		t->standby = false;
+		c->frequency = freq * 16;
+		if (fe_tuner_ops->set_params)
+			fe_tuner_ops->set_params(&t->fe);
+		t->sdr_freq = (c->frequency + 7) / 16;
 	}
 }
 
@@ -825,46 +902,37 @@ static void set_freq(struct tuner *t, unsigned int freq)
 /**
  * set_tv_freq - Set tuner frequency,  freq in Units of 62.5 kHz = 1/16MHz
  *
- * @c:	i2c_client descriptor
- * @freq: frequency
+ * @t:		a pointer to the module's internal struct_tuner
+ * @params:	analog parameters to set
  */
-static void set_tv_freq(struct i2c_client *c, unsigned int freq)
+static void set_tv_freq(struct tuner *t, struct analog_parameters *params)
 {
-	struct tuner *t = to_tuner(i2c_get_clientdata(c));
 	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 
-	struct analog_parameters params = {
-		.mode      = t->mode,
-		.audmode   = t->audmode,
-		.std       = t->std
-	};
-
-	if (t->type == UNSET) {
-		tuner_warn("tuner type not set\n");
-		return;
-	}
 	if (NULL == analog_ops->set_params) {
-		tuner_warn("Tuner has no way to set tv freq\n");
+		tuner_warn("Tuner has no way to set TV frequency\n");
 		return;
 	}
-	if (freq < t->tv_range[0] || freq > t->tv_range[1]) {
-		tuner_dbg("TV freq (%d.%02d) out of range (%d-%d)\n",
-			   freq / 16, freq % 16 * 100 / 16, t->tv_range[0] / 16,
-			   t->tv_range[1] / 16);
-		/* V4L2 spec: if the freq is not possible then the closest
-		   possible value should be selected */
-		if (freq < t->tv_range[0])
-			freq = t->tv_range[0];
+	if (params->frequency < t->tv_range[0] ||
+	    params->frequency > t->tv_range[1]) {
+		tuner_dbg("TV frequency (%d.%02d) out of range (%d-%d)\n",
+			  params->frequency / 16,
+			  params->frequency % 16 * 100 / 16,
+			  t->tv_range[0] / 16, t->tv_range[1] / 16);
+		/*
+		 * V4L2 spec: if the params->frequency is not possible,
+		 * then the closest possible value should be selected
+		 */
+		if (params->frequency < t->tv_range[0])
+			params->frequency = t->tv_range[0];
 		else
-			freq = t->tv_range[1];
+			params->frequency = t->tv_range[1];
 	}
-	params.frequency = freq;
-	tuner_dbg("tv freq set to %d.%02d\n",
-			freq / 16, freq % 16 * 100 / 16);
-	t->tv_freq = freq;
+	tuner_dbg("TV frequency set to %d.%02d\n",
+		  params->frequency / 16, params->frequency % 16 * 100 / 16);
 	t->standby = false;
 
-	analog_ops->set_params(&t->fe, &params);
+	analog_ops->set_params(&t->fe, params);
 }
 
 /**
@@ -966,24 +1034,14 @@ static v4l2_std_id tuner_fixup_std(struct tuner *t, v4l2_std_id std)
 /**
  * set_radio_freq - Set tuner frequency,  freq in Units of 62.5 Hz  = 1/16kHz
  *
- * @c:	i2c_client descriptor
- * @freq: frequency
+ * @t:		a pointer to the module's internal struct_tuner
+ * @params:	analog parameters to set
  */
-static void set_radio_freq(struct i2c_client *c, unsigned int freq)
+static void set_radio_freq(struct tuner *t, struct analog_parameters *params)
 {
-	struct tuner *t = to_tuner(i2c_get_clientdata(c));
 	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 	u32 *range;
-	struct analog_parameters params = {
-		.mode      = t->mode,
-		.audmode   = t->audmode,
-		.std       = t->std
-	};
 
-	if (t->type == UNSET) {
-		tuner_warn("tuner type not set\n");
-		return;
-	}
 	if (NULL == analog_ops->set_params) {
 		tuner_warn("tuner has no way to set radio frequency\n");
 		return;
@@ -994,29 +1052,31 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
 	else
 		range = t->radio_range;
 
-	if (freq < range[0] || freq > range[1]) {
-		tuner_dbg("radio freq (%d.%02d) out of range (%d-%d)\n",
-			   freq / 16000, freq % 16000 * 100 / 16000,
+	if (params->frequency < range[0] || params->frequency > range[1]) {
+		tuner_dbg("radio frequency (%d.%02d) out of range (%d-%d)\n",
+			   params->frequency / 16000,
+			   params->frequency % 16000 * 100 / 16000,
 			   range[0] / 16000, range[1] / 16000);
-		/* V4L2 spec: if the freq is not possible then the closest
-		   possible value should be selected */
-		if (freq < range[0])
-			freq = range[0];
+		/*
+		 * V4L2 spec: if the params->frequency is not possible,
+		 * then the closest possible value should be selected
+		 */
+		if (params->frequency < range[0])
+			params->frequency = range[0];
 		else
-			freq = range[1];
+			params->frequency = range[1];
 	}
-	params.frequency = freq;
-	tuner_dbg("radio freq set to %d.%02d\n",
-			freq / 16000, freq % 16000 * 100 / 16000);
-	t->radio_freq = freq;
+	tuner_dbg("radio frequency set to %d.%02d\n",
+		  params->frequency / 16000,
+		  params->frequency % 16000 * 100 / 16000);
 	t->standby = false;
 
-	analog_ops->set_params(&t->fe, &params);
+	analog_ops->set_params(&t->fe, params);
 	/*
 	 * The tuner driver might decide to change the audmode if it only
 	 * supports stereo, so update t->audmode.
 	 */
-	t->audmode = params.audmode;
+	t->audmode = params->audmode;
 }
 
 /*
@@ -1269,7 +1329,7 @@ static int tuner_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 	if (set_mode(t, vt->type))
 		return 0;
 
-	if (V4L2_TUNER_IS_RADIO(t->mode)) {
+	if (vt->type == V4L2_TUNER_RADIO) {
 		t->audmode = vt->audmode;
 		/*
 		 * For radio audmode can only be mono or stereo. Map any
@@ -1280,6 +1340,8 @@ static int tuner_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
 		if (t->audmode != V4L2_TUNER_MODE_MONO &&
 		    t->audmode != V4L2_TUNER_MODE_STEREO)
 			t->audmode = V4L2_TUNER_MODE_STEREO;
+	} else if (V4L2_TUNER_IS_SDR(vt->type)) {
+		t->bandwidth = vt->bandwidth;
 	}
 	set_freq(t, 0);
 
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 01/10] [media] Add initial SDR support at V4L2 API
  2013-04-21 19:00 ` [PATCH RFCv3 01/10] [media] Add initial SDR support " Mauro Carvalho Chehab
@ 2013-04-22  6:56   ` Hans Verkuil
  0 siblings, 0 replies; 21+ messages in thread
From: Hans Verkuil @ 2013-04-22  6:56 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Media Mailing List

On Sun April 21 2013 21:00:30 Mauro Carvalho Chehab wrote:
> Adds the basic API bits for Software Digital Radio (SDR) at
> the V4L2 API.
> 
> A normal radio device is actually radio and hardware demod. As the demod
> is in hardware, several things that are required for the demodulate the
> signal (IF, bandwidth, sample rate, RF/IF filters, etc) are internal to
> the device and aren't part of the API.
> 
> SDR radio, on the other hand, requires that every control needed by the
> tuner to be exposed on userspace, as userspace needs to adjust the
> software decoder to match it.
> 
> As proposed at:
> 	http://comments.gmane.org/gmane.linux.drivers.video-input-infrastructure/63123
> 
> Add a new device node for SDR devices, and a VIDIOC_QUERYCAP
> capability (V4L2_CAP_SDR) to indicate that a devnode is SDR.
> 
> The stream output format also needs to be different, as it should
> output sample data, instead of video streams. As we need to document
> SDR, add one initial format there that will be later be used.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> ---
>  Documentation/DocBook/media/v4l/common.xml         | 35 ++++++++++++++++++
>  Documentation/DocBook/media/v4l/pixfmt.xml         | 41 ++++++++++++++++++++++
>  Documentation/DocBook/media/v4l/v4l2.xml           |  1 +
>  .../DocBook/media/v4l/vidioc-querycap.xml          |  7 ++++
>  drivers/media/v4l2-core/v4l2-dev.c                 |  3 ++
>  include/media/v4l2-dev.h                           |  3 +-
>  include/uapi/linux/videodev2.h                     | 11 ++++++
>  7 files changed, 100 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/common.xml b/Documentation/DocBook/media/v4l/common.xml
> index 1ddf354..f59c67d 100644
> --- a/Documentation/DocBook/media/v4l/common.xml
> +++ b/Documentation/DocBook/media/v4l/common.xml
> @@ -513,6 +513,41 @@ the &v4l2-capability; returned by the &VIDIOC-QUERYCAP; ioctl when the
>  device has one or more modulators.</para>
>      </section>
>  
> +  <section id="sdr_tuner">
> +    <title>Software Digital Radio (SDR) Tuners and Modulators</title>
> +
> +    <para>Those devices are special types of Radio devices that don't

s/don't/do not/

'don't' is a bit too informal IMHO.

> +have any analog demodulator. Instead, it samples the radio IF or baseband
> +and sends the samples for userspace to demodulate.</para>

s/for/to/

> +    <section>

Regards,

	Hans

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 02/10] [media] videodev2.h: Remove the unused old V4L1 buffer types
  2013-04-21 19:00 ` [PATCH RFCv3 02/10] [media] videodev2.h: Remove the unused old V4L1 buffer types Mauro Carvalho Chehab
@ 2013-04-22  6:56   ` Hans Verkuil
  0 siblings, 0 replies; 21+ messages in thread
From: Hans Verkuil @ 2013-04-22  6:56 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Media Mailing List

On Sun April 21 2013 21:00:31 Mauro Carvalho Chehab wrote:
> Those aren't used anywhere for a long time. Drop it.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

Acked-by: Hans Verkuil <hans.verkuil@cisco.com>

> ---
>  include/uapi/linux/videodev2.h | 21 ---------------------
>  1 file changed, 21 deletions(-)
> 
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 4aa24c3..5d8ee92 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -72,27 +72,6 @@
>  #define VIDEO_MAX_FRAME               32
>  #define VIDEO_MAX_PLANES               8
>  
> -#ifndef __KERNEL__
> -
> -/* These defines are V4L1 specific and should not be used with the V4L2 API!
> -   They will be removed from this header in the future. */
> -
> -#define VID_TYPE_CAPTURE	1	/* Can capture */
> -#define VID_TYPE_TUNER		2	/* Can tune */
> -#define VID_TYPE_TELETEXT	4	/* Does teletext */
> -#define VID_TYPE_OVERLAY	8	/* Overlay onto frame buffer */
> -#define VID_TYPE_CHROMAKEY	16	/* Overlay by chromakey */
> -#define VID_TYPE_CLIPPING	32	/* Can clip */
> -#define VID_TYPE_FRAMERAM	64	/* Uses the frame buffer memory */
> -#define VID_TYPE_SCALES		128	/* Scalable */
> -#define VID_TYPE_MONOCHROME	256	/* Monochrome only */
> -#define VID_TYPE_SUBCAPTURE	512	/* Can capture subareas of the image */
> -#define VID_TYPE_MPEG_DECODER	1024	/* Can decode MPEG streams */
> -#define VID_TYPE_MPEG_ENCODER	2048	/* Can encode MPEG streams */
> -#define VID_TYPE_MJPEG_DECODER	4096	/* Can decode MJPEG streams */
> -#define VID_TYPE_MJPEG_ENCODER	8192	/* Can encode MJPEG streams */
> -#endif
> -
>  /*
>   *	M I S C E L L A N E O U S
>   */
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 03/10] [media] V4L2 api: Add a buffer capture type for SDR
  2013-04-21 19:00 ` [PATCH RFCv3 03/10] [media] V4L2 api: Add a buffer capture type for SDR Mauro Carvalho Chehab
@ 2013-04-22  7:00   ` Hans Verkuil
  0 siblings, 0 replies; 21+ messages in thread
From: Hans Verkuil @ 2013-04-22  7:00 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Media Mailing List

On Sun April 21 2013 21:00:32 Mauro Carvalho Chehab wrote:
> As SDR devices are not video, VBI or RDS devices, it needs
> its own buffer type for capture.
> 
> Also, as discussed at:
> 	http://comments.gmane.org/gmane.linux.drivers.video-input-infrastructure/63123
> 
> It should be a way to enumerate and select the formats that the
> hardware supports, as one hardware may accept more than one format
> (cx88, for example, can likely support several different formats,
> as it will depend on how the RISC code for it will be written).
> 
> So, add a a new stream type (V4L2_BUF_TYPE_SDR_CAPTURE) at the
> V4L2 API, and the corresponding buffer function handlers.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> ---
>  Documentation/DocBook/media/v4l/dev-capture.xml | 26 ++++++++++++--------
>  Documentation/DocBook/media/v4l/io.xml          |  6 +++++
>  drivers/media/v4l2-core/v4l2-ioctl.c            | 32 +++++++++++++++++++++++++
>  include/media/v4l2-ioctl.h                      |  8 +++++++
>  include/uapi/linux/videodev2.h                  |  3 ++-
>  5 files changed, 64 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/dev-capture.xml b/Documentation/DocBook/media/v4l/dev-capture.xml
> index e1c5f94..7797d2d 100644
> --- a/Documentation/DocBook/media/v4l/dev-capture.xml
> +++ b/Documentation/DocBook/media/v4l/dev-capture.xml
> @@ -44,7 +44,7 @@ all video capture devices.</para>
>    </section>
>  
>    <section>
> -    <title>Image Format Negotiation</title>
> +    <title>Streaming Format Negotiation</title>
>  
>      <para>The result of a capture operation is determined by
>  cropping and image format parameters. The former select an area of the
> @@ -65,13 +65,18 @@ linkend="crop" />.</para>
>  
>      <para>To query the current image format applications set the
>  <structfield>type</structfield> field of a &v4l2-format; to
> -<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> or
> -<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> and call the
> -&VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill
> -the &v4l2-pix-format; <structfield>pix</structfield> or the
> -&v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member of the
> +<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
> +<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> or
> +<constant>V4L2_BUF_TYPE_VIDEO_SDR_CAPTURE</constant> or

s/V4L2_BUF_TYPE_VIDEO_SDR_CAPTURE/V4L2_BUF_TYPE_SDR_CAPTURE/

> +and call the &VIDIOC-G-FMT; ioctl with a pointer to this structure.</para>
> +

Regards,

	Hans

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 04/10] [media] V4L2 sdr API: Add fields for VIDIOC_[G|S]_TUNER
  2013-04-21 19:00 ` [PATCH RFCv3 04/10] [media] V4L2 sdr API: Add fields for VIDIOC_[G|S]_TUNER Mauro Carvalho Chehab
@ 2013-04-22  7:11   ` Hans Verkuil
  0 siblings, 0 replies; 21+ messages in thread
From: Hans Verkuil @ 2013-04-22  7:11 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Media Mailing List

On Sun April 21 2013 21:00:33 Mauro Carvalho Chehab wrote:
> As discussed at:
> 	http://comments.gmane.org/gmane.linux.drivers.video-input-infrastructure/63123
> 
> SDR radio require some other things at to set. VIDIOC_[G|S]_TUNER
> is currently not enough.
> 
> I proposed there to create an extra ioctl for it, but the thing
> is that VIDIOC_[G|S]_TUNER is meant to set what's needed to configure
> the tuner. So, add there the missing bits to:
> 	- set/get the tuner sampling rate;
> 	- set/get the tuner low pass bandwidth filter;
> 	- get the tuner IF.
> 
> VIDIOC_[G|S]_TUNER already provides:
> 	- tuner input switch;
> 	- tuner input name;
> 	- tuner capability flags;
> 	- tuner range;
> 	- signal strength;
> 	- afc.
> 
> There are still 3 u32 reserved fields there that may be used for
> SDR in the future, and may be neded at the final version.
> 
> For example, it may make sense to add a SDR flag with:
> 	- bandwidth inversion flag;
> 	- tuner PLL lock flag (or reuse signal strength for that).
> 
> It also makes sense to add sample_rate range there.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> ---
>  Documentation/DocBook/media/v4l/vidioc-g-tuner.xml | 30 ++++++++++++++---
>  drivers/media/tuners/tuner-xc2028.c                |  2 ++
>  include/uapi/linux/videodev2.h                     | 38 ++++++++++++++++++++--
>  3 files changed, 63 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
> index 6cc8201..b8a3bcf 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
> @@ -200,9 +200,10 @@ audio</entry>
>  <constant>_SAP</constant> flag is cleared in the
>  <structfield>capability</structfield> field, the corresponding
>  <constant>V4L2_TUNER_SUB_</constant> flag must not be set
> -here.</para><para>This field is valid only if this is the tuner of the
> +here.</para>
> +<para>This field is valid only for if this is the tuner of the
>  current video input, or when the structure refers to a radio
> -tuner.</para></entry>
> +tuner. This field is not used by SDR tuners.</para></entry>
>  	  </row>
>  	  <row>
>  	    <entry>__u32</entry>
> @@ -216,7 +217,7 @@ unless the requested mode is invalid or unsupported. See <xref
>  the selected and received audio programs do not
>  match.</para><para>Currently this is the only field of struct
>  <structname>v4l2_tuner</structname> applications can
> -change.</para></entry>
> +change. This field is not used by SDR tuners.</para></entry>
>  	  </row>
>  	  <row>
>  	    <entry>__u32</entry>
> @@ -234,7 +235,28 @@ settles at zero, &ie; range is what? --></entry>
>  	  </row>
>  	  <row>
>  	    <entry>__u32</entry>
> -	    <entry><structfield>reserved</structfield>[4]</entry>
> +	    <entry><structfield>sample_rate</structfield></entry>
> +	    <entry spanname="hspan">Sampling rate used by a SDR tuner, in Hz.
> +		    This value is valid only for SDR tuners.</entry>

Are frequencies >4GHz ever likely for SDR? If so, then a u64 might be needed
here.

> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>bandwidth</structfield></entry>
> +	    <entry spanname="hspan">Bandwidth allowed by the SDR tuner
> +		    low-pass saw filter, in Hz. This value is valid only for
> +		    SDR tuners.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>int_freq</structfield></entry>
> +	    <entry spanname="hspan">Intermediate Frequency (IF) used by
> +	    the tuner, in Hz. This value is valid only for
> +	    <constant>VIDIOC_G_TUNER</constant>, and it is valid only
> +	    on SDR tuners.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>reserved</structfield>[3]</entry>

It's not clear from this doc that this is an anonymous union. See e.g. the
decoder_cmd documentation how that is done elsewhere.

>  	    <entry spanname="hspan">Reserved for future extensions. Drivers and
>  applications must set the array to zero.</entry>
>  	  </row>
> diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c
> index 878d2c4..c61163f 100644
> --- a/drivers/media/tuners/tuner-xc2028.c
> +++ b/drivers/media/tuners/tuner-xc2028.c
> @@ -1020,6 +1020,8 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
>  	 * Maybe this might also be needed for DTV.
>  	 */
>  	switch (new_type) {
> +	default:			/* SDR currently not supported */
> +		goto ret;
>  	case V4L2_TUNER_ANALOG_TV:
>  		rc = send_seq(priv, {0x00, 0x00});
>  
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 974c49d..c002030 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -160,6 +160,22 @@ enum v4l2_tuner_type {
>  	V4L2_TUNER_RADIO	     = 1,
>  	V4L2_TUNER_ANALOG_TV	     = 2,
>  	V4L2_TUNER_DIGITAL_TV	     = 3,
> +/*
> + * Even not decoding the signal, SDR tuners may require to adjust IF,
> + * low pass filters, center frequency, etc based on the signal envelope,
> + * and its bandwidth. While we might be using here the V4L2_STD_*
> + * types, plus DVB delsys, that doesn't seem to be the better thing to

delsys? Is that a typo or is that DVB terminology that I am unfamiliar with?

s/better/best/

> + * do, as:
> + *	1) it would require 64 bits for V4L2 std + 32 bits for DVB std;
> + *	2) non-TV types of envelopes won't work.
> + *
> + * So, add a separate enum to describe the possible types of SDR envelopes.
> + */
> +	V4L2_TUNER_SDR_RADIO = 10,	/* Generic non-optimized Radio range */

I'd go with 0x10, just in case we ever need to do some bitmask magic.

> +	V4L2_TUNER_SDR_ATV,		/* Optimize for Analog TV */
> +	V4L2_TUNER_SDR_DTV_ATSC,	/* Optimize for Digital TV, ATSC */
> +	V4L2_TUNER_SDR_DTV_DVBT,	/* Optimize for Digital TV, DVB-T */
> +	V4L2_TUNER_SDR_DTV_ISDBT,	/* Optimize for Digital TV, ISDB-T */
>  };
>  
>  enum v4l2_memory {
> @@ -1291,6 +1307,7 @@ struct v4l2_querymenu {
>  /*
>   *	T U N I N G
>   */
> +
>  struct v4l2_tuner {
>  	__u32                   index;
>  	__u8			name[32];
> @@ -1298,11 +1315,26 @@ struct v4l2_tuner {
>  	__u32			capability;
>  	__u32			rangelow;
>  	__u32			rangehigh;
> -	__u32			rxsubchans;
> -	__u32			audmode;
> +
> +	union {
> +		/* non-SDR tuners */
> +		struct {
> +			__u32	rxsubchans;
> +			__u32	audmode;
> +		};
> +		/* SDR tuners - audio demod data makes no sense here */
> +		struct {
> +			__u32	sample_rate;	/* Sample rate, in Hz */
> +			__u32	bandwidth;	/* Bandwidth, in Hz */
> +		};
> +	};
> +
>  	__s32			signal;
>  	__s32			afc;
> -	__u32			reserved[4];
> +
> +		__u32	int_freq;	/* Read Only - IF used, in Hz */
> +	/* non-SDR tuners */
> +	__u32		reserved[3];
>  };

Before we finalize this API we must be really certain that all the fields we
need for the SDR tuner can actually fit in this struct. If we are not certain,
then a G/S_SDR_TUNER ioctl might be more appropriate.

Regards,

	Hans

>  
>  struct v4l2_modulator {
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 07/10] [media] tuner-core: add SDR support for g_tuner
  2013-04-21 19:00 ` [PATCH RFCv3 07/10] [media] tuner-core: add SDR support for g_tuner Mauro Carvalho Chehab
@ 2013-04-22  7:18   ` Hans Verkuil
  2013-04-22 11:57     ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 21+ messages in thread
From: Hans Verkuil @ 2013-04-22  7:18 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Media Mailing List

On Sun April 21 2013 21:00:36 Mauro Carvalho Chehab wrote:
> Properly initialize the fields for VIDIOC_G_TUNER, if the
> device is in SDR mode.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> ---
>  drivers/media/v4l2-core/tuner-core.c | 29 +++++++++++++++++++++++++----
>  1 file changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
> index b97ec63..e54b5ae 100644
> --- a/drivers/media/v4l2-core/tuner-core.c
> +++ b/drivers/media/v4l2-core/tuner-core.c
> @@ -1190,7 +1190,31 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>  	}
>  
>  	/* radio mode */
> -	if (vt->type == t->mode) {
> +	vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
> +
> +	if (V4L2_TUNER_IS_SDR(vt->type)) {
> +		vt->rangelow  = tv_range[0] * 16000;
> +		vt->rangehigh = tv_range[1] * 16000;

Why use tv_range for SDR? It's a bit odd for something called SD 'Radio'.

Regards,

	Hans

> +	else {
> +		vt->rangelow = radio_range[0] * 16000;
> +		vt->rangehigh = radio_range[1] * 16000;
> +	}
> +	/* Check if the radio device is active */
> +	if (vt->type != t->mode)
> +		return 0;
> +
> +	if (V4L2_TUNER_IS_SDR(vt->type)) {
> +		if (fe_tuner_ops->get_bandwidth)
> +			fe_tuner_ops->get_bandwidth(&t->fe,
> +							&vt->bandwidth);
> +		if (fe_tuner_ops->get_if_frequency)
> +			fe_tuner_ops->get_if_frequency(&t->fe,
> +							&vt->int_freq);
> +		/*
> +			* Sampe rate is not a tuner props - it is up to the
> +			* bridge driver to fill it.
> +			*/
> +	} else {
>  		vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
>  		if (fe_tuner_ops->get_status) {
>  			u32 tuner_status;
> @@ -1203,9 +1227,6 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>  		}
>  		vt->audmode = t->audmode;
>  	}
> -	vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
> -	vt->rangelow = radio_range[0] * 16000;
> -	vt->rangehigh = radio_range[1] * 16000;
>  
>  	return 0;
>  }
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 08/10] [media] tuner-core: store tuner ranges at tuner struct
  2013-04-21 19:00 ` [PATCH RFCv3 08/10] [media] tuner-core: store tuner ranges at tuner struct Mauro Carvalho Chehab
@ 2013-04-22  7:22   ` Hans Verkuil
  2013-04-22 12:12     ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 21+ messages in thread
From: Hans Verkuil @ 2013-04-22  7:22 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Media Mailing List

On Sun April 21 2013 21:00:37 Mauro Carvalho Chehab wrote:
> Instead of using global values for tuner ranges, store them
> internally. That fixes the need of using a different range
> for SDR radio, and will help to latter add a tuner ops to
> retrieve the tuner range for SDR mode.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> ---
>  drivers/media/v4l2-core/tuner-core.c | 59 ++++++++++++++++++++++--------------
>  1 file changed, 37 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
> index e54b5ae..abdcda4 100644
> --- a/drivers/media/v4l2-core/tuner-core.c
> +++ b/drivers/media/v4l2-core/tuner-core.c
> @@ -67,8 +67,8 @@ static char secam[] = "--";
>  static char ntsc[] = "-";
>  
>  module_param_named(debug, tuner_debug, int, 0644);
> -module_param_array(tv_range, int, NULL, 0644);
> -module_param_array(radio_range, int, NULL, 0644);
> +module_param_array(tv_range, int, NULL, 0444);
> +module_param_array(radio_range, int, NULL, 0444);

Shouldn't we add a sdr_range here as well?

>  module_param_string(pal, pal, sizeof(pal), 0644);
>  module_param_string(secam, secam, sizeof(secam), 0644);
>  module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
> @@ -134,6 +134,8 @@ struct tuner {
>  	unsigned int        type; /* chip type id */
>  	void                *config;
>  	const char          *name;
> +
> +	u32                 radio_range[2], tv_range[2], sdr_range[2];
>  };
>  
>  /*
> @@ -266,7 +268,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
>  	struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
>  	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
>  	unsigned char buffer[4];
> -	int tune_now = 1;
> +	int i, tune_now = 1;
>  
>  	if (type == UNSET || type == TUNER_ABSENT) {
>  		tuner_dbg("tuner 0x%02x: Tuner type absent\n", c->addr);
> @@ -451,6 +453,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
>  			set_tv_freq(c, t->tv_freq);
>  	}
>  
> +	/* Initializes the tuner ranges from modprobe parameters */
> +	for (i = 0; i < 2; i++) {
> +		t->radio_range[i] = radio_range[i] * 16000;
> +		t->sdr_range[i] = tv_range[i] * 16000;
> +		t->tv_range[i] = tv_range[i] * 16;
> +	}
> +
>  	tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
>  		  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
>  		  t->mode_mask);
> @@ -831,16 +840,16 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
>  		tuner_warn("Tuner has no way to set tv freq\n");
>  		return;
>  	}
> -	if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
> +	if (freq < t->tv_range[0] || freq > t->tv_range[1]) {
>  		tuner_dbg("TV freq (%d.%02d) out of range (%d-%d)\n",
> -			   freq / 16, freq % 16 * 100 / 16, tv_range[0],
> -			   tv_range[1]);
> +			   freq / 16, freq % 16 * 100 / 16, t->tv_range[0] / 16,
> +			   t->tv_range[1] / 16);
>  		/* V4L2 spec: if the freq is not possible then the closest
>  		   possible value should be selected */
> -		if (freq < tv_range[0] * 16)
> -			freq = tv_range[0] * 16;
> +		if (freq < t->tv_range[0])
> +			freq = t->tv_range[0];
>  		else
> -			freq = tv_range[1] * 16;
> +			freq = t->tv_range[1];
>  	}
>  	params.frequency = freq;
>  	tuner_dbg("tv freq set to %d.%02d\n",
> @@ -957,7 +966,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
>  {
>  	struct tuner *t = to_tuner(i2c_get_clientdata(c));
>  	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
> -
> +	u32 *range;
>  	struct analog_parameters params = {
>  		.mode      = t->mode,
>  		.audmode   = t->audmode,
> @@ -972,16 +981,22 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
>  		tuner_warn("tuner has no way to set radio frequency\n");
>  		return;
>  	}
> -	if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
> +
> +	if (V4L2_TUNER_IS_SDR(t->mode))
> +		range = t->sdr_range;
> +	else
> +		range = t->radio_range;
> +
> +	if (freq < range[0] || freq > range[1]) {
>  		tuner_dbg("radio freq (%d.%02d) out of range (%d-%d)\n",
>  			   freq / 16000, freq % 16000 * 100 / 16000,
> -			   radio_range[0], radio_range[1]);
> +			   range[0] / 16000, range[1] / 16000);
>  		/* V4L2 spec: if the freq is not possible then the closest
>  		   possible value should be selected */
> -		if (freq < radio_range[0] * 16000)
> -			freq = radio_range[0] * 16000;
> +		if (freq < range[0])
> +			freq = range[0];
>  		else
> -			freq = radio_range[1] * 16000;
> +			freq = range[1];
>  	}
>  	params.frequency = freq;
>  	tuner_dbg("radio freq set to %d.%02d\n",
> @@ -1184,8 +1199,8 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>  	}
>  	if (!V4L2_TUNER_IS_RADIO(vt->type)) {
>  		vt->capability |= V4L2_TUNER_CAP_NORM;
> -		vt->rangelow = tv_range[0] * 16;
> -		vt->rangehigh = tv_range[1] * 16;
> +		vt->rangelow = t->tv_range[0];
> +		vt->rangehigh = t->tv_range[1];
>  		return 0;
>  	}
>  
> @@ -1193,11 +1208,11 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>  	vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
>  
>  	if (V4L2_TUNER_IS_SDR(vt->type)) {
> -		vt->rangelow  = tv_range[0] * 16000;
> -		vt->rangehigh = tv_range[1] * 16000;
> -	else {
> -		vt->rangelow = radio_range[0] * 16000;
> -		vt->rangehigh = radio_range[1] * 16000;
> +		vt->rangelow  = t->sdr_range[0];
> +		vt->rangehigh = t->sdr_range[1];

Ah, OK. So using tv_range was just a temporary measure.

> +	} else {
> +		vt->rangelow = t->radio_range[0];
> +		vt->rangehigh = t->radio_range[1];
>  	}
>  	/* Check if the radio device is active */
>  	if (vt->type != t->mode)
> 

Regards,

	Hans

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 00/10] Add SDR at V4L2 API
  2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
                   ` (9 preceding siblings ...)
  2013-04-21 19:00 ` [PATCH RFCv3 10/10] [media] tuner-core: add support for SDR set_tuner Mauro Carvalho Chehab
@ 2013-04-22  7:34 ` Hans Verkuil
  10 siblings, 0 replies; 21+ messages in thread
From: Hans Verkuil @ 2013-04-22  7:34 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Linux Media Mailing List

On Sun April 21 2013 21:00:29 Mauro Carvalho Chehab wrote:
> This is a version 3 of the V4L2 API bits to support Software Digital
> Radio (SDR).
> 
> Changes from version 2:
> 
> 	- Patches got better described and named;
> 	- Merged all SDR analog TV into just one field;
> 	- Documented what parts of the [RFC v2013-04-11] SDR API
> 	  REQUIREMENT SPECIFICATION are being addressed on the
> 	  patches that touch on the V4L2 external API.
> 
> With regards to the [RFC v2013-04-11] SDR requirements spec[1], v3
> implements:
> 
> 	- operation mode inquire (Rx/Tx)
> 		- implemented via VIDIOC_QUERYCAP;
> 		- get/set doesn't make sense, as different devnodes
> 		  are used for RX and TX;
> 	- sampling resolution
> 		- implemented via VIDIOC_ENUM_FMT/VIDIOC_G_FMT/VIDIOC_S_FMT.
> 	- sampling rate
> 		- get/set - implemented via VIDIOC_G_TUNER/VIDIOC_S_TUNER.
> 		- inquire HW - TODO (planning is to also use the same
> 		  ioctl's for it);
> 		- It may make sense to move it out of TUNER ioctl, as
> 		  this is actually ADC/DAC settings. For the initial
> 		  tests, I'll likely use as is, but IMO, the beter is to
> 		  split it out of VIDIOC_G_TUNER/VIDIOC_S_TUNER.
> 	- inversion
> 		- TODO. If needed, probably will use VIDIOC_G_TUNER.
> 	- RF frequency
> 		- implemented using VIDIOC_S_FREQUENCY/VIDIOC_G_FREQUENCY
> 		- scale: 62.5 Hz.
> 		- TODO: add a lower scale, for very low freqs.
> 	- IF frequency
> 		- implemented via VIDIOC_G_TUNER/VIDIOC_S_TUNER.
> 	- tuner lock (frequency synthesizer / PLL)
> 		- TODO. May eventually use tuner->strength
> 	- tuner gains
> 		- TODO (V4L2 controls).
> 	- enable/disable auto gain
> 		- TODO (V4L2 controls).
> 	- tuner filters
> 		- TODO (V4L2 controls).
> 	- pass RF standard to tuner?
> 		- Partially implemented. It doesn't pass V4L2 analog TV
> 		  types yet.
> 		- TODO: add VIDIOC_S_STD support for SDR radio
> 	- antenna switch
> 		- implemented via VIDIOC_G_TUNER/VIDIOC_S_TUNER.
> 	- external LNA
> 		- TODO (maybe there's already a V4L2 control for it)
> 	- device locking between multiple APIs
> 		- TODO (well, there are resource locking already between
> 		 	DVB and V4L at driver level)

I have some patches here:

http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/tuner

adding support for tuner ownership (as discussed in the past) to V4L2.

It's untested, and it needs to be integrated in DVB as well. The actual
struct dealing with the tuner ownership is not tied to V4L2 so I am hoping
it can be integrated in DVB without too much effort.

As I understand it a pure DVB driver does not have to deal with tuner
ownership, so this is a problem only if V4L2 is involved as well. I think
that adding a struct tuner_owners pointer to some DVB internal struct would
be sufficient, and the DVB core can check if it is non-NULL and attempt to
take tuner ownership using it.

With yet another tuner mode we need something like this. I don't have time
to work further on this for the next few weeks, so I am hoping you might
find it useful.

I reviewed part of your patch series, but I did not go in-depth with the
tuner-core patches.

> 
> [1] http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/63323
> 
> TODO:
> 	- check if VB2 require changes (might require trivial ones, due
> 	  to the new buffer type);
> 
> 	- add a SDR driver testing the new features - likely a cx88 driver,
> but as cx88 doesn't use VB2,

Of course, you can also convert cx88 to vb2 :-)

> I might use some other driver. The advantage
> of using cx88 is that it has 2 ADC, one baseband and another IF that can
> be used at the same time, 8-bits or 10-bits and up to ~35 MHz of
> sampling rate.

Nice work!

Regards,

	Hans

> 
> Mauro Carvalho Chehab (10):
>   [media] Add initial SDR support at V4L2 API
>   [media] videodev2.h: Remove the unused old V4L1 buffer types
>   [media] V4L2 api: Add a buffer capture type for SDR
>   [media] V4L2 sdr API: Add fields for VIDIOC_[G|S]_TUNER
>   [media] v4l2-ioctl: Add tuner ioctl support for SDR radio type
>   [media] tuner-core: consider SDR as radio
>   [media] tuner-core: add SDR support for g_tuner
>   [media] tuner-core: store tuner ranges at tuner struct
>   [media] tuner-core: add support to get the tuner frequency range
>   [media] tuner-core: add support for SDR set_tuner
> 
>  Documentation/DocBook/media/v4l/common.xml         |  35 +++
>  Documentation/DocBook/media/v4l/dev-capture.xml    |  26 +-
>  Documentation/DocBook/media/v4l/io.xml             |   6 +
>  Documentation/DocBook/media/v4l/pixfmt.xml         |  41 +++
>  Documentation/DocBook/media/v4l/v4l2.xml           |   1 +
>  Documentation/DocBook/media/v4l/vidioc-g-tuner.xml |  30 ++-
>  .../DocBook/media/v4l/vidioc-querycap.xml          |   7 +
>  drivers/media/dvb-core/dvb_frontend.h              |   2 +
>  drivers/media/tuners/tuner-xc2028.c                |   2 +
>  drivers/media/v4l2-core/tuner-core.c               | 297 ++++++++++++++-------
>  drivers/media/v4l2-core/v4l2-dev.c                 |   3 +
>  drivers/media/v4l2-core/v4l2-ioctl.c               | 121 +++++++--
>  include/media/v4l2-dev.h                           |   3 +-
>  include/media/v4l2-ioctl.h                         |   8 +
>  include/uapi/linux/videodev2.h                     |  79 ++++--
>  15 files changed, 503 insertions(+), 158 deletions(-)
> 
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 07/10] [media] tuner-core: add SDR support for g_tuner
  2013-04-22  7:18   ` Hans Verkuil
@ 2013-04-22 11:57     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-22 11:57 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Linux Media Mailing List

Em 22-04-2013 04:18, Hans Verkuil escreveu:
> On Sun April 21 2013 21:00:36 Mauro Carvalho Chehab wrote:
>> Properly initialize the fields for VIDIOC_G_TUNER, if the
>> device is in SDR mode.
>>
>> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
>> ---
>>   drivers/media/v4l2-core/tuner-core.c | 29 +++++++++++++++++++++++++----
>>   1 file changed, 25 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
>> index b97ec63..e54b5ae 100644
>> --- a/drivers/media/v4l2-core/tuner-core.c
>> +++ b/drivers/media/v4l2-core/tuner-core.c
>> @@ -1190,7 +1190,31 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>>   	}
>>
>>   	/* radio mode */
>> -	if (vt->type == t->mode) {
>> +	vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
>> +
>> +	if (V4L2_TUNER_IS_SDR(vt->type)) {
>> +		vt->rangelow  = tv_range[0] * 16000;
>> +		vt->rangehigh = tv_range[1] * 16000;
>
> Why use tv_range for SDR? It's a bit odd for something called SD 'Radio'.

Because it is the widest known range, and it covers already the FM
range. A latter patch will improve the range, by adding a tuner
callback to query about what's the real supported range, with will
be typically broader than the TV one.

Regards,
Mauro

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 08/10] [media] tuner-core: store tuner ranges at tuner struct
  2013-04-22  7:22   ` Hans Verkuil
@ 2013-04-22 12:12     ` Mauro Carvalho Chehab
  2013-04-23  6:45       ` Hans Verkuil
  0 siblings, 1 reply; 21+ messages in thread
From: Mauro Carvalho Chehab @ 2013-04-22 12:12 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Linux Media Mailing List

Em 22-04-2013 04:22, Hans Verkuil escreveu:
> On Sun April 21 2013 21:00:37 Mauro Carvalho Chehab wrote:
>> Instead of using global values for tuner ranges, store them
>> internally. That fixes the need of using a different range
>> for SDR radio, and will help to latter add a tuner ops to
>> retrieve the tuner range for SDR mode.
>>
>> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
>> ---
>>   drivers/media/v4l2-core/tuner-core.c | 59 ++++++++++++++++++++++--------------
>>   1 file changed, 37 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
>> index e54b5ae..abdcda4 100644
>> --- a/drivers/media/v4l2-core/tuner-core.c
>> +++ b/drivers/media/v4l2-core/tuner-core.c
>> @@ -67,8 +67,8 @@ static char secam[] = "--";
>>   static char ntsc[] = "-";
>>
>>   module_param_named(debug, tuner_debug, int, 0644);
>> -module_param_array(tv_range, int, NULL, 0644);
>> -module_param_array(radio_range, int, NULL, 0644);
>> +module_param_array(tv_range, int, NULL, 0444);
>> +module_param_array(radio_range, int, NULL, 0444);
>
> Shouldn't we add a sdr_range here as well?

I don't think it is needed to have a modprobe parameter for that.
If user wants to change the range, VIDIOC_S_TUNER can be used.

Btw, I was tempted to even remove those ;)

>
>>   module_param_string(pal, pal, sizeof(pal), 0644);
>>   module_param_string(secam, secam, sizeof(secam), 0644);
>>   module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
>> @@ -134,6 +134,8 @@ struct tuner {
>>   	unsigned int        type; /* chip type id */
>>   	void                *config;
>>   	const char          *name;
>> +
>> +	u32                 radio_range[2], tv_range[2], sdr_range[2];
>>   };
>>
>>   /*
>> @@ -266,7 +268,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
>>   	struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
>>   	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
>>   	unsigned char buffer[4];
>> -	int tune_now = 1;
>> +	int i, tune_now = 1;
>>
>>   	if (type == UNSET || type == TUNER_ABSENT) {
>>   		tuner_dbg("tuner 0x%02x: Tuner type absent\n", c->addr);
>> @@ -451,6 +453,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
>>   			set_tv_freq(c, t->tv_freq);
>>   	}
>>
>> +	/* Initializes the tuner ranges from modprobe parameters */
>> +	for (i = 0; i < 2; i++) {
>> +		t->radio_range[i] = radio_range[i] * 16000;
>> +		t->sdr_range[i] = tv_range[i] * 16000;
>> +		t->tv_range[i] = tv_range[i] * 16;
>> +	}
>> +
>>   	tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
>>   		  c->adapter->name, c->driver->driver.name, c->addr << 1, type,
>>   		  t->mode_mask);
>> @@ -831,16 +840,16 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
>>   		tuner_warn("Tuner has no way to set tv freq\n");
>>   		return;
>>   	}
>> -	if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
>> +	if (freq < t->tv_range[0] || freq > t->tv_range[1]) {
>>   		tuner_dbg("TV freq (%d.%02d) out of range (%d-%d)\n",
>> -			   freq / 16, freq % 16 * 100 / 16, tv_range[0],
>> -			   tv_range[1]);
>> +			   freq / 16, freq % 16 * 100 / 16, t->tv_range[0] / 16,
>> +			   t->tv_range[1] / 16);
>>   		/* V4L2 spec: if the freq is not possible then the closest
>>   		   possible value should be selected */
>> -		if (freq < tv_range[0] * 16)
>> -			freq = tv_range[0] * 16;
>> +		if (freq < t->tv_range[0])
>> +			freq = t->tv_range[0];
>>   		else
>> -			freq = tv_range[1] * 16;
>> +			freq = t->tv_range[1];
>>   	}
>>   	params.frequency = freq;
>>   	tuner_dbg("tv freq set to %d.%02d\n",
>> @@ -957,7 +966,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
>>   {
>>   	struct tuner *t = to_tuner(i2c_get_clientdata(c));
>>   	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
>> -
>> +	u32 *range;
>>   	struct analog_parameters params = {
>>   		.mode      = t->mode,
>>   		.audmode   = t->audmode,
>> @@ -972,16 +981,22 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
>>   		tuner_warn("tuner has no way to set radio frequency\n");
>>   		return;
>>   	}
>> -	if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
>> +
>> +	if (V4L2_TUNER_IS_SDR(t->mode))
>> +		range = t->sdr_range;
>> +	else
>> +		range = t->radio_range;
>> +
>> +	if (freq < range[0] || freq > range[1]) {
>>   		tuner_dbg("radio freq (%d.%02d) out of range (%d-%d)\n",
>>   			   freq / 16000, freq % 16000 * 100 / 16000,
>> -			   radio_range[0], radio_range[1]);
>> +			   range[0] / 16000, range[1] / 16000);
>>   		/* V4L2 spec: if the freq is not possible then the closest
>>   		   possible value should be selected */
>> -		if (freq < radio_range[0] * 16000)
>> -			freq = radio_range[0] * 16000;
>> +		if (freq < range[0])
>> +			freq = range[0];
>>   		else
>> -			freq = radio_range[1] * 16000;
>> +			freq = range[1];
>>   	}
>>   	params.frequency = freq;
>>   	tuner_dbg("radio freq set to %d.%02d\n",
>> @@ -1184,8 +1199,8 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>>   	}
>>   	if (!V4L2_TUNER_IS_RADIO(vt->type)) {
>>   		vt->capability |= V4L2_TUNER_CAP_NORM;
>> -		vt->rangelow = tv_range[0] * 16;
>> -		vt->rangehigh = tv_range[1] * 16;
>> +		vt->rangelow = t->tv_range[0];
>> +		vt->rangehigh = t->tv_range[1];
>>   		return 0;
>>   	}
>>
>> @@ -1193,11 +1208,11 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>>   	vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
>>
>>   	if (V4L2_TUNER_IS_SDR(vt->type)) {
>> -		vt->rangelow  = tv_range[0] * 16000;
>> -		vt->rangehigh = tv_range[1] * 16000;
>> -	else {
>> -		vt->rangelow = radio_range[0] * 16000;
>> -		vt->rangehigh = radio_range[1] * 16000;
>> +		vt->rangelow  = t->sdr_range[0];
>> +		vt->rangehigh = t->sdr_range[1];
>
> Ah, OK. So using tv_range was just a temporary measure.

Yes. Now that a tuner callback was added, tuner-core can just use
whatever is there. For tuners that don't implement the callback, it
will still use the TV range, with is the broader known range for all
existing tuners.

As my plan is to allow the cx88 driver to be used as SDR, in thesis,
all existing tuners could be used on SDR mode[1], and all of them supports
the TV range, as, at least currently, all SDR devices we're working with
are TV devices.

There are actually some fixes that may be needed here in the future.
As you know, TV tuners can actually have 2 separate ranges (VHF and UHF).
Most devices support a continuous range from VHF min to UHF max freq, but
there are some with a gap between VHF and UHF.

Also, some tuners supports a much wider range, but sometimes with
gaps in the middle.

So, I expect that SDR tuners will need to support multiple tuner
ranges.

Regards,
Mauro

[1] Some experiments are required, though. Devices with tda9887 (and
similar) could be filtering out the audio sub-carrier.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH RFCv3 08/10] [media] tuner-core: store tuner ranges at tuner struct
  2013-04-22 12:12     ` Mauro Carvalho Chehab
@ 2013-04-23  6:45       ` Hans Verkuil
  0 siblings, 0 replies; 21+ messages in thread
From: Hans Verkuil @ 2013-04-23  6:45 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: Linux Media Mailing List

On Monday, April 22, 2013 14:12:57 Mauro Carvalho Chehab wrote:
> Em 22-04-2013 04:22, Hans Verkuil escreveu:
> > On Sun April 21 2013 21:00:37 Mauro Carvalho Chehab wrote:
> >> Instead of using global values for tuner ranges, store them
> >> internally. That fixes the need of using a different range
> >> for SDR radio, and will help to latter add a tuner ops to
> >> retrieve the tuner range for SDR mode.
> >>
> >> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
> >> ---
> >>   drivers/media/v4l2-core/tuner-core.c | 59 ++++++++++++++++++++++--------------
> >>   1 file changed, 37 insertions(+), 22 deletions(-)
> >>
> >> diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
> >> index e54b5ae..abdcda4 100644
> >> --- a/drivers/media/v4l2-core/tuner-core.c
> >> +++ b/drivers/media/v4l2-core/tuner-core.c
> >> @@ -67,8 +67,8 @@ static char secam[] = "--";
> >>   static char ntsc[] = "-";
> >>
> >>   module_param_named(debug, tuner_debug, int, 0644);
> >> -module_param_array(tv_range, int, NULL, 0644);
> >> -module_param_array(radio_range, int, NULL, 0644);
> >> +module_param_array(tv_range, int, NULL, 0444);
> >> +module_param_array(radio_range, int, NULL, 0444);
> >
> > Shouldn't we add a sdr_range here as well?
> 
> I don't think it is needed to have a modprobe parameter for that.
> If user wants to change the range, VIDIOC_S_TUNER can be used.

You can't change the range using S_TUNER, it's not a settable field.

> 
> Btw, I was tempted to even remove those ;)

I'd either remove them or add an sdr_range rather than leaving it in
an inconsistent state.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2013-04-23  6:45 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-21 19:00 [PATCH RFCv3 00/10] Add SDR at V4L2 API Mauro Carvalho Chehab
2013-04-21 19:00 ` [PATCH RFCv3 01/10] [media] Add initial SDR support " Mauro Carvalho Chehab
2013-04-22  6:56   ` Hans Verkuil
2013-04-21 19:00 ` [PATCH RFCv3 02/10] [media] videodev2.h: Remove the unused old V4L1 buffer types Mauro Carvalho Chehab
2013-04-22  6:56   ` Hans Verkuil
2013-04-21 19:00 ` [PATCH RFCv3 03/10] [media] V4L2 api: Add a buffer capture type for SDR Mauro Carvalho Chehab
2013-04-22  7:00   ` Hans Verkuil
2013-04-21 19:00 ` [PATCH RFCv3 04/10] [media] V4L2 sdr API: Add fields for VIDIOC_[G|S]_TUNER Mauro Carvalho Chehab
2013-04-22  7:11   ` Hans Verkuil
2013-04-21 19:00 ` [PATCH RFCv3 05/10] [media] v4l2-ioctl: Add tuner ioctl support for SDR radio type Mauro Carvalho Chehab
2013-04-21 19:00 ` [PATCH RFCv3 06/10] [media] tuner-core: consider SDR as radio Mauro Carvalho Chehab
2013-04-21 19:00 ` [PATCH RFCv3 07/10] [media] tuner-core: add SDR support for g_tuner Mauro Carvalho Chehab
2013-04-22  7:18   ` Hans Verkuil
2013-04-22 11:57     ` Mauro Carvalho Chehab
2013-04-21 19:00 ` [PATCH RFCv3 08/10] [media] tuner-core: store tuner ranges at tuner struct Mauro Carvalho Chehab
2013-04-22  7:22   ` Hans Verkuil
2013-04-22 12:12     ` Mauro Carvalho Chehab
2013-04-23  6:45       ` Hans Verkuil
2013-04-21 19:00 ` [PATCH RFCv3 09/10] [media] tuner-core: add support to get the tuner frequency range Mauro Carvalho Chehab
2013-04-21 19:00 ` [PATCH RFCv3 10/10] [media] tuner-core: add support for SDR set_tuner Mauro Carvalho Chehab
2013-04-22  7:34 ` [PATCH RFCv3 00/10] Add SDR at V4L2 API Hans Verkuil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).