]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'v4l_for_linus' into to_next
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>
Tue, 20 Oct 2015 18:07:19 +0000 (16:07 -0200)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Tue, 20 Oct 2015 18:07:19 +0000 (16:07 -0200)
* v4l_for_linus:
  [media] m88ds3103: use own reg update_bits() implementation
  [media] rtl28xxu: fix control message flaws
  [media] v4l2-flash-led-class: Add missing VIDEO_V4L2 Kconfig dependency
  [media] netup_unidvb: fix potential crash when spi is NULL
  [media] si2168: Bounds check firmware
  [media] si2157: Bounds check firmware
  [media] ir-hix5hd2: drop the use of IRQF_NO_SUSPEND
  [media] c8sectpfe: fix return of garbage
  [media] c8sectpfe: fix ininitialized error return on firmware load failure
  [media] lnbh25: Fix lnbh25_attach() function return type
  [media] horus3a: Fix horus3a_attach() function parameters

139 files changed:
Documentation/DocBook/device-drivers.tmpl
Documentation/DocBook/media/dvb/dvbapi.xml
Documentation/DocBook/media/dvb/kdapi.xml [deleted file]
Documentation/DocBook/media/v4l/compat.xml
Documentation/DocBook/media/v4l/controls.xml
Documentation/DocBook/media/v4l/dev-sdr.xml
Documentation/DocBook/media/v4l/io.xml
Documentation/DocBook/media/v4l/pixfmt.xml
Documentation/DocBook/media/v4l/v4l2.xml
Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml
Documentation/DocBook/media/v4l/vidioc-g-fmt.xml
Documentation/DocBook/media/v4l/vidioc-g-modulator.xml
Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
Documentation/DocBook/media/v4l/vidioc-querycap.xml
Documentation/DocBook/media_api.tmpl
Documentation/video4linux/v4l2-pci-skeleton.c
drivers/input/touchscreen/sur40.c
drivers/media/dvb-core/demux.h
drivers/media/dvb-core/dmxdev.c
drivers/media/dvb-core/dvb_ca_en50221.h
drivers/media/dvb-core/dvb_demux.c
drivers/media/dvb-core/dvb_net.c
drivers/media/dvb-frontends/drxd_hard.c
drivers/media/dvb-frontends/rtl2832_sdr.c
drivers/media/i2c/ml86v7667.c
drivers/media/i2c/smiapp/smiapp-core.c
drivers/media/pci/cobalt/cobalt-v4l2.c
drivers/media/pci/cx23885/cx23885-417.c
drivers/media/pci/cx23885/cx23885-dvb.c
drivers/media/pci/cx23885/cx23885-vbi.c
drivers/media/pci/cx23885/cx23885-video.c
drivers/media/pci/cx25821/cx25821-video.c
drivers/media/pci/cx88/cx88-blackbird.c
drivers/media/pci/cx88/cx88-dvb.c
drivers/media/pci/cx88/cx88-vbi.c
drivers/media/pci/cx88/cx88-video.c
drivers/media/pci/dt3155/dt3155.c
drivers/media/pci/ivtv/ivtv-yuv.c
drivers/media/pci/netup_unidvb/netup_unidvb_core.c
drivers/media/pci/saa7134/saa7134-ts.c
drivers/media/pci/saa7134/saa7134-vbi.c
drivers/media/pci/saa7134/saa7134-video.c
drivers/media/pci/saa7134/saa7134.h
drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
drivers/media/pci/solo6x10/solo6x10-v4l2.c
drivers/media/pci/sta2x11/sta2x11_vip.c
drivers/media/pci/ttpci/av7110.c
drivers/media/pci/ttpci/av7110_av.c
drivers/media/pci/tw68/tw68-video.c
drivers/media/platform/am437x/am437x-vpfe.c
drivers/media/platform/blackfin/bfin_capture.c
drivers/media/platform/coda/coda-common.c
drivers/media/platform/davinci/vpbe_display.c
drivers/media/platform/davinci/vpif_capture.c
drivers/media/platform/davinci/vpif_display.c
drivers/media/platform/exynos-gsc/gsc-m2m.c
drivers/media/platform/exynos4-is/fimc-capture.c
drivers/media/platform/exynos4-is/fimc-isp-video.c
drivers/media/platform/exynos4-is/fimc-lite.c
drivers/media/platform/exynos4-is/fimc-m2m.c
drivers/media/platform/m2m-deinterlace.c
drivers/media/platform/marvell-ccic/mcam-core.c
drivers/media/platform/mx2_emmaprp.c
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/rcar_jpu.c
drivers/media/platform/s3c-camif/camif-capture.c
drivers/media/platform/s5p-g2d/g2d.c
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
drivers/media/platform/s5p-tv/mixer_video.c
drivers/media/platform/sh_veu.c
drivers/media/platform/sh_vou.c
drivers/media/platform/soc_camera/atmel-isi.c
drivers/media/platform/soc_camera/mx2_camera.c
drivers/media/platform/soc_camera/mx3_camera.c
drivers/media/platform/soc_camera/rcar_vin.c
drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
drivers/media/platform/sti/bdisp/bdisp-v4l2.c
drivers/media/platform/sti/c8sectpfe/Kconfig
drivers/media/platform/ti-vpe/vpe.c
drivers/media/platform/vim2m.c
drivers/media/platform/vivid/Kconfig
drivers/media/platform/vivid/vivid-core.c
drivers/media/platform/vivid/vivid-osd.c
drivers/media/platform/vivid/vivid-sdr-cap.c
drivers/media/platform/vivid/vivid-vbi-cap.c
drivers/media/platform/vivid/vivid-vbi-out.c
drivers/media/platform/vivid/vivid-vid-cap.c
drivers/media/platform/vivid/vivid-vid-out.c
drivers/media/platform/vsp1/vsp1_video.c
drivers/media/platform/xilinx/xilinx-dma.c
drivers/media/usb/airspy/airspy.c
drivers/media/usb/au0828/au0828-vbi.c
drivers/media/usb/au0828/au0828-video.c
drivers/media/usb/cx231xx/cx231xx-video.c
drivers/media/usb/em28xx/em28xx-vbi.c
drivers/media/usb/em28xx/em28xx-video.c
drivers/media/usb/go7007/go7007-v4l2.c
drivers/media/usb/hackrf/hackrf.c
drivers/media/usb/msi2500/msi2500.c
drivers/media/usb/pwc/pwc-if.c
drivers/media/usb/s2255/s2255drv.c
drivers/media/usb/stk1160/stk1160-v4l.c
drivers/media/usb/ttusb-dec/ttusb_dec.c
drivers/media/usb/usbtv/usbtv-video.c
drivers/media/usb/uvc/uvc_queue.c
drivers/media/v4l2-core/Makefile
drivers/media/v4l2-core/v4l2-compat-ioctl32.c
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/media/v4l2-core/v4l2-dev.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/media/v4l2-core/v4l2-trace.c
drivers/media/v4l2-core/vb2-trace.c [new file with mode: 0644]
drivers/media/v4l2-core/videobuf-core.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/media/v4l2-core/videobuf2-dma-sg.c
drivers/media/v4l2-core/videobuf2-internal.h [new file with mode: 0644]
drivers/media/v4l2-core/videobuf2-v4l2.c
drivers/staging/media/davinci_vpfe/vpfe_video.c
drivers/staging/media/omap4iss/iss.c
drivers/staging/media/omap4iss/iss_video.c
drivers/usb/gadget/function/uvc_queue.c
include/media/lirc_dev.h
include/media/tuner-types.h
include/media/tuner.h
include/media/tveeprom.h
include/media/v4l2-ioctl.h
include/media/videobuf2-core.h
include/media/videobuf2-dvb.h
include/media/videobuf2-v4l2.h
include/trace/events/v4l2.h
include/trace/events/vb2.h [new file with mode: 0644]
include/uapi/linux/v4l2-controls.h
include/uapi/linux/videodev2.h
scripts/kernel-doc

index 31cefc9af98e9ba60bd104fdb8247ff59363e59c..42a2d8593e39cd15acbab6ace23ed08e5c33a313 100644 (file)
@@ -221,6 +221,9 @@ X!Isound/sound_firmware.c
      <title>Media Devices</title>
 
      <sect1><title>Video2Linux devices</title>
+!Iinclude/media/tuner.h
+!Iinclude/media/tuner-types.h
+!Iinclude/media/tveeprom.h
 !Iinclude/media/v4l2-async.h
 !Iinclude/media/v4l2-ctrls.h
 !Iinclude/media/v4l2-dv-timings.h
@@ -240,15 +243,82 @@ X!Isound/sound_firmware.c
 !Idrivers/media/dvb-core/dvb_math.h
 !Idrivers/media/dvb-core/dvb_ringbuffer.h
 !Idrivers/media/dvb-core/dvbdev.h
-     </sect1>
-     <sect1><title>Remote Controller devices</title>
+       <sect1><title>Digital TV Demux API</title>
+           <para>The kernel demux API defines a driver-internal interface for
+           registering low-level, hardware specific driver to a hardware
+           independent demux layer. It is only of interest for Digital TV
+           device driver writers. The header file for this API is named
+           <constant>demux.h</constant> and located in
+           <constant>drivers/media/dvb-core</constant>.</para>
+
+       <para>The demux API should be implemented for each demux in the
+       system. It is used to select the TS source of a demux and to manage
+       the demux resources. When the demux client allocates a resource via
+       the demux API, it receives a pointer to the API of that
+       resource.</para>
+       <para>Each demux receives its TS input from a DVB front-end or from
+       memory, as set via this demux API. In a system with more than one
+       front-end, the API can be used to select one of the DVB front-ends
+       as a TS source for a demux, unless this is fixed in the HW platform.
+       The demux API only controls front-ends regarding to their connections
+       with demuxes; the APIs used to set the other front-end parameters,
+       such as tuning, are not defined in this document.</para>
+       <para>The functions that implement the abstract interface demux should
+       be defined static or module private and registered to the Demux
+       core for external access. It is not necessary to implement every
+       function in the struct <constant>dmx_demux</constant>. For example,
+       a demux interface might support Section filtering, but not PES
+       filtering. The API client is expected to check the value of any
+       function pointer before calling the function: the value of NULL means
+       that the &#8220;function is not available&#8221;.</para>
+       <para>Whenever the functions of the demux API modify shared data,
+       the possibilities of lost update and race condition problems should
+       be addressed, e.g. by protecting parts of code with mutexes.</para>
+       <para>Note that functions called from a bottom half context must not
+       sleep. Even a simple memory allocation without using GFP_ATOMIC can
+       result in a kernel thread being put to sleep if swapping is needed.
+       For example, the Linux kernel calls the functions of a network device
+       interface from a bottom half context. Thus, if a demux API function
+       is called from network device code, the function must not sleep.
+       </para>
+    </sect1>
+
+    <section id="demux_callback_api">
+       <title>Demux Callback API</title>
+       <para>This kernel-space API comprises the callback functions that
+       deliver filtered data to the demux client. Unlike the other DVB
+       kABIs, these functions are provided by the client and called from
+       the demux code.</para>
+       <para>The function pointers of this abstract interface are not
+       packed into a structure as in the other demux APIs, because the
+       callback functions are registered and used independent of each
+       other. As an example, it is possible for the API client to provide
+       several callback functions for receiving TS packets and no
+       callbacks for PES packets or sections.</para>
+       <para>The functions that implement the callback API need not be
+       re-entrant: when a demux driver calls one of these functions,
+       the driver is not allowed to call the function again before
+       the original call returns. If a callback is triggered by a
+       hardware interrupt, it is recommended to use the Linux
+       &#8220;bottom half&#8221; mechanism or start a tasklet instead of
+       making the callback function call directly from a hardware
+       interrupt.</para>
+       <para>This mechanism is implemented by
+       <link linkend='API-dmx-ts-cb'>dmx_ts_cb()</link> and
+       <link linkend='API-dmx-section-cb'>dmx_section_cb()</link>.</para>
+    </section>
+
+!Idrivers/media/dvb-core/demux.h
+    </sect1>
+    <sect1><title>Remote Controller devices</title>
 !Iinclude/media/rc-core.h
-     </sect1>
-     <sect1><title>Media Controller devices</title>
+!Iinclude/media/lirc_dev.h
+    </sect1>
+    <sect1><title>Media Controller devices</title>
 !Iinclude/media/media-device.h
 !Iinclude/media/media-devnode.h
 !Iinclude/media/media-entity.h
-     </sect1>
+    </sect1>
 
   </chapter>
 
index 858fd7d1710401f1783598f6686cf16dadf9b168..8576481e20aebc287e24c011d8fac099c9a63e4c 100644 (file)
@@ -125,9 +125,6 @@ Added ISDB-T test originally written by Patrick Boettcher
        &sub-audio;
     </section>
   </chapter>
-  <chapter id="dvb_kdapi">
-    &sub-kdapi;
-  </chapter>
   <chapter id="dvb_examples">
     &sub-examples;
   </chapter>
diff --git a/Documentation/DocBook/media/dvb/kdapi.xml b/Documentation/DocBook/media/dvb/kdapi.xml
deleted file mode 100644 (file)
index 68bcd33..0000000
+++ /dev/null
@@ -1,2309 +0,0 @@
-<title>Kernel Demux API</title>
-<para>The kernel demux API defines a driver-internal interface for registering low-level,
-hardware specific driver to a hardware independent demux layer. It is only of interest for
-DVB device driver writers. The header file for this API is named <constant>demux.h</constant> and located in
-<constant>">drivers/media/dvb-core</constant>.
-</para>
-<para>Maintainer note: This section must be reviewed. It is probably out of date.
-</para>
-
-<section id="kernel_demux_data_types">
-<title>Kernel Demux Data Types</title>
-
-
-<section id="dmx_success_t">
-<title>dmx_success_t</title>
- <programlisting>
- typedef enum {
-   DMX_OK = 0, /&#x22C6; Received Ok &#x22C6;/
-   DMX_LENGTH_ERROR, /&#x22C6; Incorrect length &#x22C6;/
-   DMX_OVERRUN_ERROR, /&#x22C6; Receiver ring buffer overrun &#x22C6;/
-   DMX_CRC_ERROR, /&#x22C6; Incorrect CRC &#x22C6;/
-   DMX_FRAME_ERROR, /&#x22C6; Frame alignment error &#x22C6;/
-   DMX_FIFO_ERROR, /&#x22C6; Receiver FIFO overrun &#x22C6;/
-   DMX_MISSED_ERROR /&#x22C6; Receiver missed packet &#x22C6;/
- } dmx_success_t;
-</programlisting>
-
-</section>
-<section id="ts_filter_types">
-<title>TS filter types</title>
- <programlisting>
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
- /&#x22C6; TS packet reception &#x22C6;/
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
-
- /&#x22C6; TS filter type for set_type() &#x22C6;/
-
- #define TS_PACKET       1   /&#x22C6; send TS packets (188 bytes) to callback (default) &#x22C6;/
- #define TS_PAYLOAD_ONLY 2   /&#x22C6; in case TS_PACKET is set, only send the TS
-                               payload (&#x003C;=184 bytes per packet) to callback &#x22C6;/
- #define TS_DECODER      4   /&#x22C6; send stream to built-in decoder (if present) &#x22C6;/
-</programlisting>
-
-</section>
-<section id="dmx_ts_pes_t">
-<title>dmx_ts_pes_t</title>
-<para>The structure
-</para>
-<programlisting>
- typedef enum
- {
-        DMX_TS_PES_AUDIO,   /&#x22C6; also send packets to audio decoder (if it exists) &#x22C6;/
-        DMX_TS_PES_VIDEO,   /&#x22C6; ... &#x22C6;/
-        DMX_TS_PES_TELETEXT,
-        DMX_TS_PES_SUBTITLE,
-        DMX_TS_PES_PCR,
-        DMX_TS_PES_OTHER,
- } dmx_ts_pes_t;
-</programlisting>
-<para>describes the PES type for filters which write to a built-in decoder. The correspond (and
-should be kept identical) to the types in the demux device.
-</para>
-<programlisting>
- struct dmx_ts_feed_s {
-        int is_filtering; /&#x22C6; Set to non-zero when filtering in progress &#x22C6;/
-        struct dmx_demux_s&#x22C6; parent; /&#x22C6; Back-pointer &#x22C6;/
-        void&#x22C6; priv; /&#x22C6; Pointer to private data of the API client &#x22C6;/
-        int (&#x22C6;set) (struct dmx_ts_feed_s&#x22C6; feed,
-                    __u16 pid,
-                    size_t callback_length,
-                    size_t circular_buffer_size,
-                    int descramble,
-                    struct timespec timeout);
-        int (&#x22C6;start_filtering) (struct dmx_ts_feed_s&#x22C6; feed);
-        int (&#x22C6;stop_filtering) (struct dmx_ts_feed_s&#x22C6; feed);
-        int (&#x22C6;set_type) (struct dmx_ts_feed_s&#x22C6; feed,
-                         int type,
-                         dmx_ts_pes_t pes_type);
- };
-
- typedef struct dmx_ts_feed_s dmx_ts_feed_t;
-</programlisting>
- <programlisting>
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
- /&#x22C6; PES packet reception (not supported yet) &#x22C6;/
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
-
- typedef struct dmx_pes_filter_s {
-        struct dmx_pes_s&#x22C6; parent; /&#x22C6; Back-pointer &#x22C6;/
-        void&#x22C6; priv; /&#x22C6; Pointer to private data of the API client &#x22C6;/
- } dmx_pes_filter_t;
-</programlisting>
- <programlisting>
- typedef struct dmx_pes_feed_s {
-        int is_filtering; /&#x22C6; Set to non-zero when filtering in progress &#x22C6;/
-        struct dmx_demux_s&#x22C6; parent; /&#x22C6; Back-pointer &#x22C6;/
-        void&#x22C6; priv; /&#x22C6; Pointer to private data of the API client &#x22C6;/
-        int (&#x22C6;set) (struct dmx_pes_feed_s&#x22C6; feed,
-                    __u16 pid,
-                    size_t circular_buffer_size,
-                    int descramble,
-                    struct timespec timeout);
-        int (&#x22C6;start_filtering) (struct dmx_pes_feed_s&#x22C6; feed);
-        int (&#x22C6;stop_filtering) (struct dmx_pes_feed_s&#x22C6; feed);
-        int (&#x22C6;allocate_filter) (struct dmx_pes_feed_s&#x22C6; feed,
-                                dmx_pes_filter_t&#x22C6;&#x22C6; filter);
-        int (&#x22C6;release_filter) (struct dmx_pes_feed_s&#x22C6; feed,
-                               dmx_pes_filter_t&#x22C6; filter);
- } dmx_pes_feed_t;
-</programlisting>
- <programlisting>
- typedef struct {
-        __u8 filter_value [DMX_MAX_FILTER_SIZE];
-        __u8 filter_mask [DMX_MAX_FILTER_SIZE];
-        struct dmx_section_feed_s&#x22C6; parent; /&#x22C6; Back-pointer &#x22C6;/
-        void&#x22C6; priv; /&#x22C6; Pointer to private data of the API client &#x22C6;/
- } dmx_section_filter_t;
-</programlisting>
- <programlisting>
- struct dmx_section_feed_s {
-        int is_filtering; /&#x22C6; Set to non-zero when filtering in progress &#x22C6;/
-        struct dmx_demux_s&#x22C6; parent; /&#x22C6; Back-pointer &#x22C6;/
-        void&#x22C6; priv; /&#x22C6; Pointer to private data of the API client &#x22C6;/
-        int (&#x22C6;set) (struct dmx_section_feed_s&#x22C6; feed,
-                    __u16 pid,
-                    size_t circular_buffer_size,
-                    int descramble,
-                    int check_crc);
-        int (&#x22C6;allocate_filter) (struct dmx_section_feed_s&#x22C6; feed,
-                                dmx_section_filter_t&#x22C6;&#x22C6; filter);
-        int (&#x22C6;release_filter) (struct dmx_section_feed_s&#x22C6; feed,
-                               dmx_section_filter_t&#x22C6; filter);
-        int (&#x22C6;start_filtering) (struct dmx_section_feed_s&#x22C6; feed);
-        int (&#x22C6;stop_filtering) (struct dmx_section_feed_s&#x22C6; feed);
- };
- typedef struct dmx_section_feed_s dmx_section_feed_t;
-
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
- /&#x22C6; Callback functions &#x22C6;/
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
-
- typedef int (&#x22C6;dmx_ts_cb) ( __u8 &#x22C6; buffer1,
-                           size_t buffer1_length,
-                           __u8 &#x22C6; buffer2,
-                           size_t buffer2_length,
-                           dmx_ts_feed_t&#x22C6; source,
-                           dmx_success_t success);
-
- typedef int (&#x22C6;dmx_section_cb) ( __u8 &#x22C6; buffer1,
-                                size_t buffer1_len,
-                                __u8 &#x22C6; buffer2,
-                                size_t buffer2_len,
-                                dmx_section_filter_t &#x22C6; source,
-                                dmx_success_t success);
-
- typedef int (&#x22C6;dmx_pes_cb) ( __u8 &#x22C6; buffer1,
-                            size_t buffer1_len,
-                            __u8 &#x22C6; buffer2,
-                            size_t buffer2_len,
-                            dmx_pes_filter_t&#x22C6; source,
-                            dmx_success_t success);
-
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
- /&#x22C6; DVB Front-End &#x22C6;/
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
-
- typedef enum {
-        DMX_OTHER_FE = 0,
-        DMX_SATELLITE_FE,
-        DMX_CABLE_FE,
-        DMX_TERRESTRIAL_FE,
-        DMX_LVDS_FE,
-        DMX_ASI_FE, /&#x22C6; DVB-ASI interface &#x22C6;/
-        DMX_MEMORY_FE
- } dmx_frontend_source_t;
-
- typedef struct {
-        /&#x22C6; The following char&#x22C6; fields point to NULL terminated strings &#x22C6;/
-        char&#x22C6; id;                    /&#x22C6; Unique front-end identifier &#x22C6;/
-        char&#x22C6; vendor;                /&#x22C6; Name of the front-end vendor &#x22C6;/
-        char&#x22C6; model;                 /&#x22C6; Name of the front-end model &#x22C6;/
-        struct list_head connectivity_list; /&#x22C6; List of front-ends that can
-                                               be connected to a particular
-                                               demux &#x22C6;/
-        void&#x22C6; priv;     /&#x22C6; Pointer to private data of the API client &#x22C6;/
-        dmx_frontend_source_t source;
- } dmx_frontend_t;
-
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
- /&#x22C6; MPEG-2 TS Demux &#x22C6;/
- /&#x22C6;--------------------------------------------------------------------------&#x22C6;/
-
- /&#x22C6;
-  &#x22C6; Flags OR'ed in the capabilites field of struct dmx_demux_s.
-  &#x22C6;/
-
- #define DMX_TS_FILTERING                        1
- #define DMX_PES_FILTERING                       2
- #define DMX_SECTION_FILTERING                   4
- #define DMX_MEMORY_BASED_FILTERING              8    /&#x22C6; write() available &#x22C6;/
- #define DMX_CRC_CHECKING                        16
- #define DMX_TS_DESCRAMBLING                     32
- #define DMX_SECTION_PAYLOAD_DESCRAMBLING        64
- #define DMX_MAC_ADDRESS_DESCRAMBLING            128
-</programlisting>
-
-</section>
-<section id="demux_demux_t">
-<title>demux_demux_t</title>
- <programlisting>
- /&#x22C6;
-  &#x22C6; DMX_FE_ENTRY(): Casts elements in the list of registered
-  &#x22C6; front-ends from the generic type struct list_head
-  &#x22C6; to the type &#x22C6; dmx_frontend_t
-  &#x22C6;.
- &#x22C6;/
-
- #define DMX_FE_ENTRY(list) list_entry(list, dmx_frontend_t, connectivity_list)
-
- struct dmx_demux_s {
-        /&#x22C6; The following char&#x22C6; fields point to NULL terminated strings &#x22C6;/
-        char&#x22C6; id;                    /&#x22C6; Unique demux identifier &#x22C6;/
-        char&#x22C6; vendor;                /&#x22C6; Name of the demux vendor &#x22C6;/
-        char&#x22C6; model;                 /&#x22C6; Name of the demux model &#x22C6;/
-        __u32 capabilities;          /&#x22C6; Bitfield of capability flags &#x22C6;/
-        dmx_frontend_t&#x22C6; frontend;    /&#x22C6; Front-end connected to the demux &#x22C6;/
-        struct list_head reg_list;   /&#x22C6; List of registered demuxes &#x22C6;/
-        void&#x22C6; priv;                  /&#x22C6; Pointer to private data of the API client &#x22C6;/
-        int users;                   /&#x22C6; Number of users &#x22C6;/
-        int (&#x22C6;open) (struct dmx_demux_s&#x22C6; demux);
-        int (&#x22C6;close) (struct dmx_demux_s&#x22C6; demux);
-        int (&#x22C6;write) (struct dmx_demux_s&#x22C6; demux, const char&#x22C6; buf, size_t count);
-        int (&#x22C6;allocate_ts_feed) (struct dmx_demux_s&#x22C6; demux,
-                                 dmx_ts_feed_t&#x22C6;&#x22C6; feed,
-                                 dmx_ts_cb callback);
-        int (&#x22C6;release_ts_feed) (struct dmx_demux_s&#x22C6; demux,
-                                dmx_ts_feed_t&#x22C6; feed);
-        int (&#x22C6;allocate_pes_feed) (struct dmx_demux_s&#x22C6; demux,
-                                  dmx_pes_feed_t&#x22C6;&#x22C6; feed,
-                                  dmx_pes_cb callback);
-        int (&#x22C6;release_pes_feed) (struct dmx_demux_s&#x22C6; demux,
-                                 dmx_pes_feed_t&#x22C6; feed);
-        int (&#x22C6;allocate_section_feed) (struct dmx_demux_s&#x22C6; demux,
-                                      dmx_section_feed_t&#x22C6;&#x22C6; feed,
-                                      dmx_section_cb callback);
-        int (&#x22C6;release_section_feed) (struct dmx_demux_s&#x22C6; demux,
-                                     dmx_section_feed_t&#x22C6; feed);
-        int (&#x22C6;descramble_mac_address) (struct dmx_demux_s&#x22C6; demux,
-                                       __u8&#x22C6; buffer1,
-                                       size_t buffer1_length,
-                                       __u8&#x22C6; buffer2,
-                                       size_t buffer2_length,
-                                       __u16 pid);
-        int (&#x22C6;descramble_section_payload) (struct dmx_demux_s&#x22C6; demux,
-                                           __u8&#x22C6; buffer1,
-                                           size_t buffer1_length,
-                                           __u8&#x22C6; buffer2, size_t buffer2_length,
-                                           __u16 pid);
-        int (&#x22C6;add_frontend) (struct dmx_demux_s&#x22C6; demux,
-                             dmx_frontend_t&#x22C6; frontend);
-        int (&#x22C6;remove_frontend) (struct dmx_demux_s&#x22C6; demux,
-                                dmx_frontend_t&#x22C6; frontend);
-        struct list_head&#x22C6; (&#x22C6;get_frontends) (struct dmx_demux_s&#x22C6; demux);
-        int (&#x22C6;connect_frontend) (struct dmx_demux_s&#x22C6; demux,
-                                 dmx_frontend_t&#x22C6; frontend);
-        int (&#x22C6;disconnect_frontend) (struct dmx_demux_s&#x22C6; demux);
-
-
-        /&#x22C6; added because js cannot keep track of these himself &#x22C6;/
-        int (&#x22C6;get_pes_pids) (struct dmx_demux_s&#x22C6; demux, __u16 &#x22C6;pids);
- };
- typedef struct dmx_demux_s dmx_demux_t;
-</programlisting>
-
-</section>
-<section id="demux_directory">
-<title>Demux directory</title>
- <programlisting>
- /&#x22C6;
-  &#x22C6; DMX_DIR_ENTRY(): Casts elements in the list of registered
-  &#x22C6; demuxes from the generic type struct list_head&#x22C6; to the type dmx_demux_t
-  &#x22C6;.
-  &#x22C6;/
-
- #define DMX_DIR_ENTRY(list) list_entry(list, dmx_demux_t, reg_list)
-
- int dmx_register_demux (dmx_demux_t&#x22C6; demux);
- int dmx_unregister_demux (dmx_demux_t&#x22C6; demux);
- struct list_head&#x22C6; dmx_get_demuxes (void);
-</programlisting>
- </section></section>
-<section id="demux_directory_api">
-<title>Demux Directory API</title>
-<para>The demux directory is a Linux kernel-wide facility for registering and accessing the
-MPEG-2 TS demuxes in the system. Run-time registering and unregistering of demux drivers
-is possible using this API.
-</para>
-<para>All demux drivers in the directory implement the abstract interface dmx_demux_t.
-</para>
-
-<section
-role="subsection"><title>dmx_register_demux()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function makes a demux driver interface available to the Linux kernel. It is
- usually called by the init_module() function of the kernel module that contains
- the demux driver. The caller of this function is responsible for allocating
- dynamic or static memory for the demux structure and for initializing its fields
- before calling this function. The memory allocated for the demux structure
- must not be freed before calling dmx_unregister_demux(),</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int dmx_register_demux ( dmx_demux_t &#x22C6;demux )</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t*
- demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux structure.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EEXIST</para>
-</entry><entry
- align="char">
-<para>A demux with the same value of the id field already stored
- in the directory.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOSPC</para>
-</entry><entry
- align="char">
-<para>No space left in the directory.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>dmx_unregister_demux()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function is called to indicate that the given demux interface is no
- longer available. The caller of this function is responsible for freeing the
- memory of the demux structure, if it was dynamically allocated before calling
- dmx_register_demux(). The cleanup_module() function of the kernel module
- that contains the demux driver should call this function. Note that this function
- fails if the demux is currently in use, i.e., release_demux() has not been called
- for the interface.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int dmx_unregister_demux ( dmx_demux_t &#x22C6;demux )</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t*
- demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux structure which is to be
- unregistered.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENODEV</para>
-</entry><entry
- align="char">
-<para>The specified demux is not registered in the demux
- directory.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EBUSY</para>
-</entry><entry
- align="char">
-<para>The specified demux is currently in use.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>dmx_get_demuxes()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Provides the caller with the list of registered demux interfaces, using the
- standard list structure defined in the include file linux/list.h. The include file
- demux.h defines the macro DMX_DIR_ENTRY() for converting an element of
- the generic type struct list_head* to the type dmx_demux_t*. The caller must
- not free the memory of any of the elements obtained via this function call.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>struct list_head &#x22C6;dmx_get_demuxes ()</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>none</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>struct list_head *</para>
-</entry><entry
- align="char">
-<para>A list of demux interfaces, or NULL in the case of an
- empty list.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
- </section></section>
-<section id="demux_api">
-<title>Demux API</title>
-<para>The demux API should be implemented for each demux in the system. It is used to select
-the TS source of a demux and to manage the demux resources. When the demux
-client allocates a resource via the demux API, it receives a pointer to the API of that
-resource.
-</para>
-<para>Each demux receives its TS input from a DVB front-end or from memory, as set via the
-demux API. In a system with more than one front-end, the API can be used to select one of
-the DVB front-ends as a TS source for a demux, unless this is fixed in the HW platform. The
-demux API only controls front-ends regarding their connections with demuxes; the APIs
-used to set the other front-end parameters, such as tuning, are not defined in this
-document.
-</para>
-<para>The functions that implement the abstract interface demux should be defined static or
-module private and registered to the Demux Directory for external access. It is not necessary
-to implement every function in the demux_t struct, however (for example, a demux interface
-might support Section filtering, but not TS or PES filtering). The API client is expected to
-check the value of any function pointer before calling the function: the value of NULL means
-&#8220;function not available&#8221;.
-</para>
-<para>Whenever the functions of the demux API modify shared data, the possibilities of lost
-update and race condition problems should be addressed, e.g. by protecting parts of code with
-mutexes. This is especially important on multi-processor hosts.
-</para>
-<para>Note that functions called from a bottom half context must not sleep, at least in the 2.2.x
-kernels. Even a simple memory allocation can result in a kernel thread being put to sleep if
-swapping is needed. For example, the Linux kernel calls the functions of a network device
-interface from a bottom half context. Thus, if a demux API function is called from network
-device code, the function must not sleep.
-</para>
-
-
-<section id="kdapi_fopen">
-<title>open()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function reserves the demux for use by the caller and, if necessary,
- initializes the demux. When the demux is no longer needed, the function close()
- should be called. It should be possible for multiple clients to access the demux
- at the same time. Thus, the function implementation should increment the
- demux usage count when open() is called and decrement it when close() is
- called.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int open ( demux_t&#x22C6; demux );</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>demux_t* demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EUSERS</para>
-</entry><entry
- align="char">
-<para>Maximum usage count reached.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section>
-<section id="kdapi_fclose">
-<title>close()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function reserves the demux for use by the caller and, if necessary,
- initializes the demux. When the demux is no longer needed, the function close()
- should be called. It should be possible for multiple clients to access the demux
- at the same time. Thus, the function implementation should increment the
- demux usage count when open() is called and decrement it when close() is
- called.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int close(demux_t&#x22C6; demux);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>demux_t* demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENODEV</para>
-</entry><entry
- align="char">
-<para>The demux was not in use.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section>
-<section id="kdapi_fwrite">
-<title>write()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function provides the demux driver with a memory buffer containing TS
- packets. Instead of receiving TS packets from the DVB front-end, the demux
- driver software will read packets from memory. Any clients of this demux
- with active TS, PES or Section filters will receive filtered data via the Demux
- callback API (see 0). The function returns when all the data in the buffer has
- been consumed by the demux. Demux hardware typically cannot read TS from
- memory. If this is the case, memory-based filtering has to be implemented
- entirely in software.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int write(demux_t&#x22C6; demux, const char&#x22C6; buf, size_t
- count);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>demux_t* demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>const char* buf</para>
-</entry><entry
- align="char">
-<para>Pointer to the TS data in kernel-space memory.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t length</para>
-</entry><entry
- align="char">
-<para>Length of the TS data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOSYS</para>
-</entry><entry
- align="char">
-<para>The command is not implemented.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>allocate_ts_feed()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Allocates a new TS feed, which is used to filter the TS packets carrying a
- certain PID. The TS feed normally corresponds to a hardware PID filter on the
- demux chip.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int allocate_ts_feed(dmx_demux_t&#x22C6; demux,
- dmx_ts_feed_t&#x22C6;&#x22C6; feed, dmx_ts_cb callback);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>demux_t* demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_ts_feed_t**
- feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the TS feed API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_ts_cb callback</para>
-</entry><entry
- align="char">
-<para>Pointer to the callback function for passing received TS
- packet</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EBUSY</para>
-</entry><entry
- align="char">
-<para>No more TS feeds available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOSYS</para>
-</entry><entry
- align="char">
-<para>The command is not implemented.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>release_ts_feed()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Releases the resources allocated with allocate_ts_feed(). Any filtering in
- progress on the TS feed should be stopped before calling this function.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int release_ts_feed(dmx_demux_t&#x22C6; demux,
- dmx_ts_feed_t&#x22C6; feed);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>demux_t* demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_ts_feed_t* feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the TS feed API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>allocate_section_feed()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Allocates a new section feed, i.e. a demux resource for filtering and receiving
- sections. On platforms with hardware support for section filtering, a section
- feed is directly mapped to the demux HW. On other platforms, TS packets are
- first PID filtered in hardware and a hardware section filter then emulated in
- software. The caller obtains an API pointer of type dmx_section_feed_t as an
- out parameter. Using this API the caller can set filtering parameters and start
- receiving sections.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int allocate_section_feed(dmx_demux_t&#x22C6; demux,
- dmx_section_feed_t &#x22C6;&#x22C6;feed, dmx_section_cb callback);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>demux_t *demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_section_feed_t
- **feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the section feed API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_section_cb
- callback</para>
-</entry><entry
- align="char">
-<para>Pointer to the callback function for passing received
- sections.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EBUSY</para>
-</entry><entry
- align="char">
-<para>No more section feeds available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOSYS</para>
-</entry><entry
- align="char">
-<para>The command is not implemented.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>release_section_feed()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Releases the resources allocated with allocate_section_feed(), including
- allocated filters. Any filtering in progress on the section feed should be stopped
- before calling this function.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int release_section_feed(dmx_demux_t&#x22C6; demux,
- dmx_section_feed_t &#x22C6;feed);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>demux_t *demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_section_feed_t
- *feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the section feed API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>descramble_mac_address()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function runs a descrambling algorithm on the destination MAC
- address field of a DVB Datagram Section, replacing the original address
- with its un-encrypted version. Otherwise, the description on the function
- descramble_section_payload() applies also to this function.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int descramble_mac_address(dmx_demux_t&#x22C6; demux, __u8
- &#x22C6;buffer1, size_t buffer1_length, __u8 &#x22C6;buffer2,
- size_t buffer2_length, __u16 pid);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t
- *demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u8 *buffer1</para>
-</entry><entry
- align="char">
-<para>Pointer to the first byte of the section.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t buffer1_length</para>
-</entry><entry
- align="char">
-<para>Length of the section data, including headers and CRC,
- in buffer1.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u8* buffer2</para>
-</entry><entry
- align="char">
-<para>Pointer to the tail of the section data, or NULL. The
- pointer has a non-NULL value if the section wraps past
- the end of a circular buffer.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t buffer2_length</para>
-</entry><entry
- align="char">
-<para>Length of the section data, including headers and CRC,
- in buffer2.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u16 pid</para>
-</entry><entry
- align="char">
-<para>The PID on which the section was received. Useful
- for obtaining the descrambling key, e.g. from a DVB
- Common Access facility.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOSYS</para>
-</entry><entry
- align="char">
-<para>No descrambling facility available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>descramble_section_payload()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function runs a descrambling algorithm on the payload of a DVB
- Datagram Section, replacing the original payload with its un-encrypted
- version. The function will be called from the demux API implementation;
- the API client need not call this function directly. Section-level scrambling
- algorithms are currently standardized only for DVB-RCC (return channel
- over 2-directional cable TV network) systems. For all other DVB networks,
- encryption schemes are likely to be proprietary to each data broadcaster. Thus,
- it is expected that this function pointer will have the value of NULL (i.e.,
- function not available) in most demux API implementations. Nevertheless, it
- should be possible to use the function pointer as a hook for dynamically adding
- a &#8220;plug-in&#8221; descrambling facility to a demux driver.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>While this function is not needed with hardware-based section descrambling,
- the descramble_section_payload function pointer can be used to override the
- default hardware-based descrambling algorithm: if the function pointer has a
- non-NULL value, the corresponding function should be used instead of any
- descrambling hardware.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int descramble_section_payload(dmx_demux_t&#x22C6; demux,
- __u8 &#x22C6;buffer1, size_t buffer1_length, __u8 &#x22C6;buffer2,
- size_t buffer2_length, __u16 pid);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t
- *demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u8 *buffer1</para>
-</entry><entry
- align="char">
-<para>Pointer to the first byte of the section.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t buffer1_length</para>
-</entry><entry
- align="char">
-<para>Length of the section data, including headers and CRC,
- in buffer1.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u8 *buffer2</para>
-</entry><entry
- align="char">
-<para>Pointer to the tail of the section data, or NULL. The
- pointer has a non-NULL value if the section wraps past
- the end of a circular buffer.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t buffer2_length</para>
-</entry><entry
- align="char">
-<para>Length of the section data, including headers and CRC,
- in buffer2.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u16 pid</para>
-</entry><entry
- align="char">
-<para>The PID on which the section was received. Useful
- for obtaining the descrambling key, e.g. from a DVB
- Common Access facility.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOSYS</para>
-</entry><entry
- align="char">
-<para>No descrambling facility available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>add_frontend()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Registers a connectivity between a demux and a front-end, i.e., indicates that
- the demux can be connected via a call to connect_frontend() to use the given
- front-end as a TS source. The client of this function has to allocate dynamic or
- static memory for the frontend structure and initialize its fields before calling
- this function. This function is normally called during the driver initialization.
- The caller must not free the memory of the frontend struct before successfully
- calling remove_frontend().</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int add_frontend(dmx_demux_t &#x22C6;demux, dmx_frontend_t
- &#x22C6;frontend);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t*
- demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_frontend_t*
- frontend</para>
-</entry><entry
- align="char">
-<para>Pointer to the front-end instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EEXIST</para>
-</entry><entry
- align="char">
-<para>A front-end with the same value of the id field already
- registered.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINUSE</para>
-</entry><entry
- align="char">
-<para>The demux is in use.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOMEM</para>
-</entry><entry
- align="char">
-<para>No more front-ends can be added.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>remove_frontend()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Indicates that the given front-end, registered by a call to add_frontend(), can
- no longer be connected as a TS source by this demux. The function should be
- called when a front-end driver or a demux driver is removed from the system.
- If the front-end is in use, the function fails with the return value of -EBUSY.
- After successfully calling this function, the caller can free the memory of
- the frontend struct if it was dynamically allocated before the add_frontend()
- operation.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int remove_frontend(dmx_demux_t&#x22C6; demux,
- dmx_frontend_t&#x22C6; frontend);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t*
- demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_frontend_t*
- frontend</para>
-</entry><entry
- align="char">
-<para>Pointer to the front-end instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EBUSY</para>
-</entry><entry
- align="char">
-<para>The front-end is in use, i.e. a call to connect_frontend()
- has not been followed by a call to disconnect_frontend().</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>get_frontends()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Provides the APIs of the front-ends that have been registered for this demux.
- Any of the front-ends obtained with this call can be used as a parameter for
- connect_frontend().</para>
-</entry>
- </row><row><entry
- align="char">
-<para>The include file demux.h contains the macro DMX_FE_ENTRY() for
- converting an element of the generic type struct list_head* to the type
- dmx_frontend_t*. The caller must not free the memory of any of the elements
- obtained via this function call.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>struct list_head&#x22C6; get_frontends(dmx_demux_t&#x22C6; demux);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t*
- demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t*</para>
-</entry><entry
- align="char">
-<para>A list of front-end interfaces, or NULL in the case of an
- empty list.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>connect_frontend()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Connects the TS output of the front-end to the input of the demux. A demux
- can only be connected to a front-end registered to the demux with the function
- add_frontend().</para>
-</entry>
- </row><row><entry
- align="char">
-<para>It may or may not be possible to connect multiple demuxes to the same
- front-end, depending on the capabilities of the HW platform. When not used,
- the front-end should be released by calling disconnect_frontend().</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int connect_frontend(dmx_demux_t&#x22C6; demux,
- dmx_frontend_t&#x22C6; frontend);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t*
- demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_frontend_t*
- frontend</para>
-</entry><entry
- align="char">
-<para>Pointer to the front-end instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EBUSY</para>
-</entry><entry
- align="char">
-<para>The front-end is in use.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>disconnect_frontend()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Disconnects the demux and a front-end previously connected by a
- connect_frontend() call.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int disconnect_frontend(dmx_demux_t&#x22C6; demux);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_demux_t*
- demux</para>
-</entry><entry
- align="char">
-<para>Pointer to the demux API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
- </section></section>
-<section id="demux_callback_api">
-<title>Demux Callback API</title>
-<para>This kernel-space API comprises the callback functions that deliver filtered data to the
-demux client. Unlike the other APIs, these API functions are provided by the client and called
-from the demux code.
-</para>
-<para>The function pointers of this abstract interface are not packed into a structure as in the
-other demux APIs, because the callback functions are registered and used independent
-of each other. As an example, it is possible for the API client to provide several
-callback functions for receiving TS packets and no callbacks for PES packets or
-sections.
-</para>
-<para>The functions that implement the callback API need not be re-entrant: when a demux
-driver calls one of these functions, the driver is not allowed to call the function again before
-the original call returns. If a callback is triggered by a hardware interrupt, it is recommended
-to use the Linux &#8220;bottom half&#8221; mechanism or start a tasklet instead of making the callback
-function call directly from a hardware interrupt.
-</para>
-
-<section
-role="subsection"><title>dmx_ts_cb()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function, provided by the client of the demux API, is called from the
- demux code. The function is only called when filtering on this TS feed has
- been enabled using the start_filtering() function.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>Any TS packets that match the filter settings are copied to a circular buffer. The
- filtered TS packets are delivered to the client using this callback function. The
- size of the circular buffer is controlled by the circular_buffer_size parameter
- of the set() function in the TS Feed API. It is expected that the buffer1 and
- buffer2 callback parameters point to addresses within the circular buffer, but
- other implementations are also possible. Note that the called party should not
- try to free the memory the buffer1 and buffer2 parameters point to.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>When this function is called, the buffer1 parameter typically points to the
- start of the first undelivered TS packet within a circular buffer. The buffer2
- buffer parameter is normally NULL, except when the received TS packets have
- crossed the last address of the circular buffer and &#8221;wrapped&#8221; to the beginning
- of the buffer. In the latter case the buffer1 parameter would contain an address
- within the circular buffer, while the buffer2 parameter would contain the first
- address of the circular buffer.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>The number of bytes delivered with this function (i.e. buffer1_length +
- buffer2_length) is usually equal to the value of callback_length parameter
- given in the set() function, with one exception: if a timeout occurs before
- receiving callback_length bytes of TS data, any undelivered packets are
- immediately delivered to the client by calling this function. The timeout
- duration is controlled by the set() function in the TS Feed API.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>If a TS packet is received with errors that could not be fixed by the TS-level
- forward error correction (FEC), the Transport_error_indicator flag of the TS
- packet header should be set. The TS packet should not be discarded, as
- the error can possibly be corrected by a higher layer protocol. If the called
- party is slow in processing the callback, it is possible that the circular buffer
- eventually fills up. If this happens, the demux driver should discard any TS
- packets received while the buffer is full. The error should be indicated to the
- client on the next callback by setting the success parameter to the value of
- DMX_OVERRUN_ERROR.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>The type of data returned to the callback can be selected by the new
- function int (*set_type) (struct dmx_ts_feed_s* feed, int type, dmx_ts_pes_t
- pes_type) which is part of the dmx_ts_feed_s struct (also cf. to the
- include file ost/demux.h) The type parameter decides if the raw TS packet
- (TS_PACKET) or just the payload (TS_PACKET&#8212;TS_PAYLOAD_ONLY)
- should be returned. If additionally the TS_DECODER bit is set the stream
- will also be sent to the hardware MPEG decoder. In this case, the second
- flag decides as what kind of data the stream should be interpreted. The
- possible choices are one of DMX_TS_PES_AUDIO, DMX_TS_PES_VIDEO,
- DMX_TS_PES_TELETEXT, DMX_TS_PES_SUBTITLE,
- DMX_TS_PES_PCR, or DMX_TS_PES_OTHER.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int dmx_ts_cb(__u8&#x22C6; buffer1, size_t buffer1_length,
- __u8&#x22C6; buffer2, size_t buffer2_length, dmx_ts_feed_t&#x22C6;
- source, dmx_success_t success);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>__u8* buffer1</para>
-</entry><entry
- align="char">
-<para>Pointer to the start of the filtered TS packets.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t buffer1_length</para>
-</entry><entry
- align="char">
-<para>Length of the TS data in buffer1.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u8* buffer2</para>
-</entry><entry
- align="char">
-<para>Pointer to the tail of the filtered TS packets, or NULL.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t buffer2_length</para>
-</entry><entry
- align="char">
-<para>Length of the TS data in buffer2.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_ts_feed_t*
- source</para>
-</entry><entry
- align="char">
-<para>Indicates which TS feed is the source of the callback.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_success_t
- success</para>
-</entry><entry
- align="char">
-<para>Indicates if there was an error in TS reception.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>Continue filtering.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-1</para>
-</entry><entry
- align="char">
-<para>Stop filtering - has the same effect as a call to
- stop_filtering() on the TS Feed API.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>dmx_section_cb()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function, provided by the client of the demux API, is called from the
- demux code. The function is only called when filtering of sections has been
- enabled using the function start_filtering() of the section feed API. When the
- demux driver has received a complete section that matches at least one section
- filter, the client is notified via this callback function. Normally this function is
- called for each received section; however, it is also possible to deliver multiple
- sections with one callback, for example when the system load is high. If an
- error occurs while receiving a section, this function should be called with
- the corresponding error type set in the success field, whether or not there is
- data to deliver. The Section Feed implementation should maintain a circular
- buffer for received sections. However, this is not necessary if the Section Feed
- API is implemented as a client of the TS Feed API, because the TS Feed
- implementation then buffers the received data. The size of the circular buffer
- can be configured using the set() function in the Section Feed API. If there
- is no room in the circular buffer when a new section is received, the section
- must be discarded. If this happens, the value of the success parameter should
- be DMX_OVERRUN_ERROR on the next callback.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int dmx_section_cb(__u8&#x22C6; buffer1, size_t
- buffer1_length, __u8&#x22C6; buffer2, size_t
- buffer2_length, dmx_section_filter_t&#x22C6; source,
- dmx_success_t success);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>__u8* buffer1</para>
-</entry><entry
- align="char">
-<para>Pointer to the start of the filtered section, e.g. within the
- circular buffer of the demux driver.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t buffer1_length</para>
-</entry><entry
- align="char">
-<para>Length of the filtered section data in buffer1, including
- headers and CRC.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u8* buffer2</para>
-</entry><entry
- align="char">
-<para>Pointer to the tail of the filtered section data, or NULL.
- Useful to handle the wrapping of a circular buffer.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t buffer2_length</para>
-</entry><entry
- align="char">
-<para>Length of the filtered section data in buffer2, including
- headers and CRC.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_section_filter_t*
- filter</para>
-</entry><entry
- align="char">
-<para>Indicates the filter that triggered the callback.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_success_t
- success</para>
-</entry><entry
- align="char">
-<para>Indicates if there was an error in section reception.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>Continue filtering.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-1</para>
-</entry><entry
- align="char">
-<para>Stop filtering - has the same effect as a call to
- stop_filtering() on the Section Feed API.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
- </section></section>
-<section id="ts_feed_api">
-<title>TS Feed API</title>
-<para>A TS feed is typically mapped to a hardware PID filter on the demux chip.
-Using this API, the client can set the filtering properties to start/stop filtering TS
-packets on a particular TS feed. The API is defined as an abstract interface of the type
-dmx_ts_feed_t.
-</para>
-<para>The functions that implement the interface should be defined static or module private. The
-client can get the handle of a TS feed API by calling the function allocate_ts_feed() in the
-demux API.
-</para>
-
-<section
-role="subsection"><title>set()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function sets the parameters of a TS feed. Any filtering in progress on the
- TS feed must be stopped before calling this function.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int set ( dmx_ts_feed_t&#x22C6; feed, __u16 pid, size_t
- callback_length, size_t circular_buffer_size, int
- descramble, struct timespec timeout);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_ts_feed_t* feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the TS feed API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u16 pid</para>
-</entry><entry
- align="char">
-<para>PID value to filter. Only the TS packets carrying the
- specified PID will be passed to the API client.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t
- callback_length</para>
-</entry><entry
- align="char">
-<para>Number of bytes to deliver with each call to the
- dmx_ts_cb() callback function. The value of this
- parameter should be a multiple of 188.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t
- circular_buffer_size</para>
-</entry><entry
- align="char">
-<para>Size of the circular buffer for the filtered TS packets.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int descramble</para>
-</entry><entry
- align="char">
-<para>If non-zero, descramble the filtered TS packets.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct timespec
- timeout</para>
-</entry><entry
- align="char">
-<para>Maximum time to wait before delivering received TS
- packets to the client.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOMEM</para>
-</entry><entry
- align="char">
-<para>Not enough memory for the requested buffer size.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOSYS</para>
-</entry><entry
- align="char">
-<para>No descrambling facility available for TS.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>start_filtering()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Starts filtering TS packets on this TS feed, according to its settings. The PID
- value to filter can be set by the API client. All matching TS packets are
- delivered asynchronously to the client, using the callback function registered
- with allocate_ts_feed().</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int start_filtering(dmx_ts_feed_t&#x22C6; feed);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_ts_feed_t* feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the TS feed API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>stop_filtering()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Stops filtering TS packets on this TS feed.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int stop_filtering(dmx_ts_feed_t&#x22C6; feed);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_ts_feed_t* feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the TS feed API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
- </section></section>
-<section id="section_feed_api">
-<title>Section Feed API</title>
-<para>A section feed is a resource consisting of a PID filter and a set of section filters. Using this
-API, the client can set the properties of a section feed and to start/stop filtering. The API is
-defined as an abstract interface of the type dmx_section_feed_t. The functions that implement
-the interface should be defined static or module private. The client can get the handle of
-a section feed API by calling the function allocate_section_feed() in the demux
-API.
-</para>
-<para>On demux platforms that provide section filtering in hardware, the Section Feed API
-implementation provides a software wrapper for the demux hardware. Other platforms may
-support only PID filtering in hardware, requiring that TS packets are converted to sections in
-software. In the latter case the Section Feed API implementation can be a client of the TS
-Feed API.
-</para>
-
-</section>
-<section id="kdapi_set">
-<title>set()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function sets the parameters of a section feed. Any filtering in progress on
- the section feed must be stopped before calling this function. If descrambling
- is enabled, the payload_scrambling_control and address_scrambling_control
- fields of received DVB datagram sections should be observed. If either one is
- non-zero, the section should be descrambled either in hardware or using the
- functions descramble_mac_address() and descramble_section_payload() of the
- demux API. Note that according to the MPEG-2 Systems specification, only
- the payloads of private sections can be scrambled while the rest of the section
- data must be sent in the clear.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int set(dmx_section_feed_t&#x22C6; feed, __u16 pid, size_t
- circular_buffer_size, int descramble, int
- check_crc);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_section_feed_t*
- feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the section feed API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u16 pid</para>
-</entry><entry
- align="char">
-<para>PID value to filter; only the TS packets carrying the
- specified PID will be accepted.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t
- circular_buffer_size</para>
-</entry><entry
- align="char">
-<para>Size of the circular buffer for filtered sections.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int descramble</para>
-</entry><entry
- align="char">
-<para>If non-zero, descramble any sections that are scrambled.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int check_crc</para>
-</entry><entry
- align="char">
-<para>If non-zero, check the CRC values of filtered sections.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOMEM</para>
-</entry><entry
- align="char">
-<para>Not enough memory for the requested buffer size.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOSYS</para>
-</entry><entry
- align="char">
-<para>No descrambling facility available for sections.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameters.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>allocate_filter()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function is used to allocate a section filter on the demux. It should only be
- called when no filtering is in progress on this section feed. If a filter cannot be
- allocated, the function fails with -ENOSPC. See in section ?? for the format of
- the section filter.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>The bitfields filter_mask and filter_value should only be modified when no
- filtering is in progress on this section feed. filter_mask controls which bits of
- filter_value are compared with the section headers/payload. On a binary value
- of 1 in filter_mask, the corresponding bits are compared. The filter only accepts
- sections that are equal to filter_value in all the tested bit positions. Any changes
- to the values of filter_mask and filter_value are guaranteed to take effect only
- when the start_filtering() function is called next time. The parent pointer in
- the struct is initialized by the API implementation to the value of the feed
- parameter. The priv pointer is not used by the API implementation, and can
- thus be freely utilized by the caller of this function. Any data pointed to by the
- priv pointer is available to the recipient of the dmx_section_cb() function call.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>While the maximum section filter length (DMX_MAX_FILTER_SIZE) is
- currently set at 16 bytes, hardware filters of that size are not available on all
- platforms. Therefore, section filtering will often take place first in hardware,
- followed by filtering in software for the header bytes that were not covered
- by a hardware filter. The filter_mask field can be checked to determine how
- many bytes of the section filter are actually used, and if the hardware filter will
- suffice. Additionally, software-only section filters can optionally be allocated
- to clients when all hardware section filters are in use. Note that on most demux
- hardware it is not possible to filter on the section_length field of the section
- header &#8211; thus this field is ignored, even though it is included in filter_value and
- filter_mask fields.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int allocate_filter(dmx_section_feed_t&#x22C6; feed,
- dmx_section_filter_t&#x22C6;&#x22C6; filter);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_section_feed_t*
- feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the section feed API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_section_filter_t**
- filter</para>
-</entry><entry
- align="char">
-<para>Pointer to the allocated filter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENOSPC</para>
-</entry><entry
- align="char">
-<para>No filters of given type and length available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameters.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>release_filter()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This function releases all the resources of a previously allocated section filter.
- The function should not be called while filtering is in progress on this section
- feed. After calling this function, the caller should not try to dereference the
- filter pointer.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int release_filter ( dmx_section_feed_t&#x22C6; feed,
- dmx_section_filter_t&#x22C6; filter);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_section_feed_t*
- feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the section feed API and instance data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_section_filter_t*
- filter</para>
-</entry><entry
- align="char">
-<para>I/O Pointer to the instance data of a section filter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-ENODEV</para>
-</entry><entry
- align="char">
-<para>No such filter allocated.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>start_filtering()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Starts filtering sections on this section feed, according to its settings. Sections
- are first filtered based on their PID and then matched with the section
- filters allocated for this feed. If the section matches the PID filter and
- at least one section filter, it is delivered to the API client. The section
- is delivered asynchronously using the callback function registered with
- allocate_section_feed().</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int start_filtering ( dmx_section_feed_t&#x22C6; feed );</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_section_feed_t*
- feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the section feed API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section
-role="subsection"><title>stop_filtering()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>Stops filtering sections on this section feed. Note that any changes to the
- filtering parameters (filter_value, filter_mask, etc.) should only be made when
- filtering is stopped.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int stop_filtering ( dmx_section_feed_t&#x22C6; feed );</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>dmx_section_feed_t*
- feed</para>
-</entry><entry
- align="char">
-<para>Pointer to the section feed API and instance data.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURNS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>0</para>
-</entry><entry
- align="char">
-<para>The function was completed without errors.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>-EINVAL</para>
-</entry><entry
- align="char">
-<para>Bad parameter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section>
index a0aef85d33c1f94041d46bd7f48db037385522cc..5701a08ed792dae2cf3fdbd5a8a8bda4fe29cc2d 100644 (file)
@@ -2591,6 +2591,26 @@ and &v4l2-mbus-framefmt;.
       </orderedlist>
     </section>
 
+    <section>
+      <title>V4L2 in Linux 4.4</title>
+      <orderedlist>
+       <listitem>
+         <para>Renamed <constant>V4L2_TUNER_ADC</constant> to
+<constant>V4L2_TUNER_SDR</constant>. The use of
+<constant>V4L2_TUNER_ADC</constant> is deprecated now.
+         </para>
+       </listitem>
+       <listitem>
+         <para>Added <constant>V4L2_CID_RF_TUNER_RF_GAIN</constant>
+RF Tuner control.</para>
+       </listitem>
+       <listitem>
+         <para>Added transmitter support for Software Defined Radio (SDR)
+Interface.</para>
+       </listitem>
+      </orderedlist>
+    </section>
+
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
 
index 33aece5418800c51e0b6756e2fc02dc4e222e253..f13a429093f174c406b293a5ca21e8e4d1526e47 100644 (file)
@@ -5417,6 +5417,18 @@ set. Unit is in Hz. The range and step are driver-specific.</entry>
             <row>
               <entry spanname="descr">Enables/disables IF automatic gain control (AGC)</entry>
             </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_RF_GAIN</constant>&nbsp;</entry>
+              <entry>integer</entry>
+            </row>
+            <row>
+              <entry spanname="descr">The RF amplifier is the very first
+amplifier on the receiver signal path, just right after the antenna input.
+The difference between the LNA gain and the RF gain in this document is that
+the LNA gain is integrated in the tuner chip while the RF gain is a separate
+chip. There may be both RF and LNA gain controls in the same device.
+The range and step are driver-specific.</entry>
+            </row>
             <row>
               <entry spanname="id"><constant>V4L2_CID_RF_TUNER_LNA_GAIN</constant>&nbsp;</entry>
               <entry>integer</entry>
@@ -5425,6 +5437,8 @@ set. Unit is in Hz. The range and step are driver-specific.</entry>
               <entry spanname="descr">LNA (low noise amplifier) gain is first
 gain stage on the RF tuner signal path. It is located very close to tuner
 antenna input. Used when <constant>V4L2_CID_RF_TUNER_LNA_GAIN_AUTO</constant> is not set.
+See <constant>V4L2_CID_RF_TUNER_RF_GAIN</constant> to understand how RF gain
+and LNA gain differs from the each others.
 The range and step are driver-specific.</entry>
             </row>
             <row>
index f8903568a243d81dcd2f5e5a76ab40e37b4b4e22..a659771f7b7cca90feb6e22958d1e480e881d084 100644 (file)
@@ -28,6 +28,16 @@ Devices supporting the SDR receiver interface set the
 <structfield>capabilities</structfield> field of &v4l2-capability;
 returned by the &VIDIOC-QUERYCAP; ioctl. That flag means the device has an
 Analog to Digital Converter (ADC), which is a mandatory element for the SDR receiver.
+    </para>
+    <para>
+Devices supporting the SDR transmitter interface set the
+<constant>V4L2_CAP_SDR_OUTPUT</constant> and
+<constant>V4L2_CAP_MODULATOR</constant> flag in the
+<structfield>capabilities</structfield> field of &v4l2-capability;
+returned by the &VIDIOC-QUERYCAP; ioctl. That flag means the device has an
+Digital to Analog Converter (DAC), which is a mandatory element for the SDR transmitter.
+    </para>
+    <para>
 At least one of the read/write, streaming or asynchronous I/O methods must
 be supported.
     </para>
@@ -39,15 +49,16 @@ be supported.
     <para>
 SDR devices can support <link linkend="control">controls</link>, and must
 support the <link linkend="tuner">tuner</link> ioctls. Tuner ioctls are used
-for setting the ADC sampling rate (sampling frequency) and the possible RF tuner
-frequency.
+for setting the ADC/DAC sampling rate (sampling frequency) and the possible
+radio frequency (RF).
     </para>
 
     <para>
-The <constant>V4L2_TUNER_ADC</constant> tuner type is used for ADC tuners, and
-the <constant>V4L2_TUNER_RF</constant> tuner type is used for RF tuners. The
-tuner index of the RF tuner (if any) must always follow the ADC tuner index.
-Normally the ADC tuner is #0 and the RF tuner is #1.
+The <constant>V4L2_TUNER_SDR</constant> tuner type is used for setting SDR
+device ADC/DAC frequency, and the <constant>V4L2_TUNER_RF</constant>
+tuner type is used for setting radio frequency.
+The tuner index of the RF tuner (if any) must always follow the SDR tuner index.
+Normally the SDR tuner is #0 and the RF tuner is #1.
     </para>
 
     <para>
@@ -59,9 +70,9 @@ The &VIDIOC-S-HW-FREQ-SEEK; ioctl is not supported.
     <title>Data Format Negotiation</title>
 
     <para>
-The SDR capture device uses the <link linkend="format">format</link> ioctls to
-select the capture format. Both the sampling resolution and the data streaming
-format are bound to that selectable format. In addition to the basic
+The SDR device uses the <link linkend="format">format</link> ioctls to
+select the capture and output format. Both the sampling resolution and the data
+streaming format are bound to that selectable format. In addition to the basic
 <link linkend="format">format</link> ioctls, the &VIDIOC-ENUM-FMT; ioctl
 must be supported as well.
     </para>
@@ -69,7 +80,8 @@ must be supported as well.
     <para>
 To use the <link linkend="format">format</link> ioctls applications set the
 <structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant> and use the &v4l2-sdr-format;
+<constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant> or
+<constant>V4L2_BUF_TYPE_SDR_OUTPUT</constant> and use the &v4l2-sdr-format;
 <structfield>sdr</structfield> member of the <structfield>fmt</structfield>
 union as needed per the desired operation.
 Currently there is two fields, <structfield>pixelformat</structfield> and
index 7bbc2a48911ea26b876f2ed92ab70d881e5c38e1..da654031ef3fd82d5ec73c56ad65af38e131e0f3 100644 (file)
@@ -1006,8 +1006,14 @@ must set this to 0.</entry>
          <row>
            <entry><constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant></entry>
            <entry>11</entry>
-           <entry>Buffer for Software Defined Radio (SDR), see <xref
-               linkend="sdr" />.</entry>
+           <entry>Buffer for Software Defined Radio (SDR) capture stream, see
+               <xref linkend="sdr" />.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_BUF_TYPE_SDR_OUTPUT</constant></entry>
+           <entry>12</entry>
+           <entry>Buffer for Software Defined Radio (SDR) output stream, see
+               <xref linkend="sdr" />.</entry>
          </row>
        </tbody>
       </tgroup>
index 70cd0fd02e12dfe19f1af77833df2a3411901b9f..d871245d29735a0084ea422539a0dc23f106ca10 100644 (file)
@@ -1732,7 +1732,7 @@ extended control <constant>V4L2_CID_MPEG_STREAM_TYPE</constant>, see
   <section id="sdr-formats">
     <title>SDR Formats</title>
 
-    <para>These formats are used for <link linkend="sdr">SDR Capture</link>
+    <para>These formats are used for <link linkend="sdr">SDR</link>
 interface only.</para>
 
     &sub-sdr-cu08;
index e98caa1c39bd21ed89ca24e47a85f1733bf38be9..7e61643358de034df628a0106e84e1e222315566 100644 (file)
@@ -151,9 +151,18 @@ Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab,
 structs, ioctls) must be noted in more detail in the history chapter
 (compat.xml), along with the possible impact on existing drivers and
 applications. -->
+      <revision>
+       <revnumber>4.4</revnumber>
+       <date>2015-05-26</date>
+       <authorinitials>ap</authorinitials>
+       <revremark>Renamed V4L2_TUNER_ADC to V4L2_TUNER_SDR.
+Added V4L2_CID_RF_TUNER_RF_GAIN control.
+Added transmitter support for Software Defined Radio (SDR) Interface.
+       </revremark>
+      </revision>
 
       <revision>
-       <revnumber>3.21</revnumber>
+       <revnumber>4.1</revnumber>
        <date>2015-02-13</date>
        <authorinitials>mcc</authorinitials>
        <revremark>Fix documentation for media controller device nodes and add support for DVB device nodes.
@@ -557,7 +566,7 @@ and discussions on the V4L mailing list.</revremark>
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 3.19</subtitle>
+ <subtitle>Revision 4.4</subtitle>
 
   <chapter id="common">
     &sub-common;
index fc1d4625a78cf3d5450c25fd576d5e225a95bea1..70a4a08e940495563bf11fde360017e04afedcc2 100644 (file)
@@ -130,7 +130,7 @@ encoding will continue until the end of the current <wordasword>Group
 Of Pictures</wordasword>, otherwise encoding will stop immediately.
 When the encoder is already stopped, this command does
 nothing. mem2mem encoders will send a <constant>V4L2_EVENT_EOS</constant> event
-when the last frame has been decoded and all frames are ready to be dequeued and
+when the last frame has been encoded and all frames are ready to be dequeued and
 will set the <constant>V4L2_BUF_FLAG_LAST</constant> buffer flag on the last
 buffer of the capture queue to indicate there will be no new buffers produced to
 dequeue. This buffer may be empty, indicated by the driver setting the
index 4fe19a7a9a31efa3b2628e683853ef295ccf7932..ffcb448251f048a505045d4f8170a2bea2b0ab64 100644 (file)
@@ -175,7 +175,7 @@ capture and output devices.</entry>
            <entry>&v4l2-sdr-format;</entry>
            <entry><structfield>sdr</structfield></entry>
            <entry>Definition of a data format, see
-<xref linkend="pixfmt" />, used by SDR capture devices.</entry>
+<xref linkend="pixfmt" />, used by SDR capture and output devices.</entry>
          </row>
          <row>
            <entry></entry>
index 7068b599a00dd331c39c14a2f52c79d1c21708f8..96e17b344c5d510f6f93ad13098f32da8157c9cd 100644 (file)
@@ -78,6 +78,12 @@ different audio modulation if the request cannot be satisfied. However
 this is a write-only ioctl, it does not return the actual audio
 modulation selected.</para>
 
+    <para><link linkend="sdr">SDR</link> specific modulator types are
+<constant>V4L2_TUNER_SDR</constant> and <constant>V4L2_TUNER_RF</constant>.
+For SDR devices <structfield>txsubchans</structfield> field must be
+initialized to zero.
+The term 'modulator' means SDR transmitter in this context.</para>
+
     <para>To change the radio frequency the &VIDIOC-S-FREQUENCY; ioctl
 is available.</para>
 
@@ -140,7 +146,13 @@ indicator, for example a stereo pilot tone.</entry>
          </row>
          <row>
            <entry>__u32</entry>
-           <entry><structfield>reserved</structfield>[4]</entry>
+           <entry><structfield>type</structfield></entry>
+           <entry spanname="hspan">Type of the modulator, see <xref
+               linkend="v4l2-tuner-type" />.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>reserved</structfield>[3]</entry>
            <entry>Reserved for future extensions. Drivers and
 applications must set the array to zero.</entry>
          </row>
index b0d865933da69247aaf85a569d1de4cc1a28acf4..459b7e561f3c1e1ed32dd556a936eb5c04849f20 100644 (file)
@@ -80,6 +80,12 @@ if the requested mode is invalid or unsupported. Since this is a
 <!-- FIXME -->write-only ioctl, it does not return the actually
 selected audio mode.</para>
 
+    <para><link linkend="sdr">SDR</link> specific tuner types are
+<constant>V4L2_TUNER_SDR</constant> and <constant>V4L2_TUNER_RF</constant>.
+For SDR devices <structfield>audmode</structfield> field must be
+initialized to zero.
+The term 'tuner' means SDR receiver in this context.</para>
+
     <para>To change the radio frequency the &VIDIOC-S-FREQUENCY; ioctl
 is available.</para>
 
@@ -261,6 +267,16 @@ applications must set the array to zero.</entry>
            <entry>2</entry>
            <entry></entry>
          </row>
+         <row>
+           <entry><constant>V4L2_TUNER_SDR</constant></entry>
+           <entry>4</entry>
+           <entry></entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_TUNER_RF</constant></entry>
+           <entry>5</entry>
+           <entry></entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index 20fda75a012dc130e8a94b1935d5efe574a5dae3..cd82148dedd7ddb922c5156e7792b8735af32d4b 100644 (file)
@@ -306,6 +306,12 @@ modulator programming see
            <entry>0x00200000</entry>
            <entry>The device supports the &v4l2-pix-format; extended
 fields.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_CAP_SDR_OUTPUT</constant></entry>
+           <entry>0x00400000</entry>
+           <entry>The device supports the
+<link linkend="sdr">SDR Output</link> interface.</entry>
          </row>
          <row>
            <entry><constant>V4L2_CAP_READWRITE</constant></entry>
index f3f5fe5b64c93ef2cf4954d9c4b4daf0615921e8..92037033f5eb3d14500129c9892514ce9c270469 100644 (file)
@@ -38,7 +38,7 @@
        <title>LINUX MEDIA INFRASTRUCTURE API</title>
 
        <copyright>
-               <year>2009-2014</year>
+               <year>2009-2015</year>
                <holder>LinuxTV Developers</holder>
        </copyright>
 
index 9c80c090e92df7233f1ddf645f638c0a09329bf8..95ae8286009280a568e18a98cd6ecd0d59f1fc36 100644 (file)
@@ -37,6 +37,7 @@
 #include <media/v4l2-dv-timings.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 MODULE_DESCRIPTION("V4L2 PCI Skeleton Driver");
@@ -162,10 +163,11 @@ static irqreturn_t skeleton_irq(int irq, void *dev_id)
  * minimum number: many DMA engines need a minimum of 2 buffers in the
  * queue and you need to have another available for userspace processing.
  */
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned int *nbuffers, unsigned int *nplanes,
                       unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct skeleton *skel = vb2_get_drv_priv(vq);
 
        skel->field = skel->format.field;
index 98d094587e855820a7803e4e76a24dc21f54f913..d214f22ed305aab0773fe783c2e692c62fc342eb 100644 (file)
@@ -644,10 +644,11 @@ static void sur40_disconnect(struct usb_interface *interface)
  * minimum number: many DMA engines need a minimum of 2 buffers in the
  * queue and you need to have another available for userspace processing.
  */
-static int sur40_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int sur40_queue_setup(struct vb2_queue *q, const void *parg,
                       unsigned int *nbuffers, unsigned int *nplanes,
                       unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct sur40_state *sur40 = vb2_get_drv_priv(q);
 
        if (q->num_buffers + *nbuffers < 3)
index 833191bcd81077542b054e3989ee564c7afd3228..ccc1f43cb9a9b11767c0eee35aa323f908fee370 100644 (file)
@@ -32,9 +32,9 @@
 #include <linux/time.h>
 #include <linux/dvb/dmx.h>
 
-/*--------------------------------------------------------------------------*/
-/* Common definitions */
-/*--------------------------------------------------------------------------*/
+/*
+ * Common definitions
+ */
 
 /*
  * DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter.
@@ -45,7 +45,8 @@
 #endif
 
 /*
- * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
+ * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed
+ * filter.
  */
 
 #ifndef DMX_MAX_SECTION_SIZE
 #define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188)
 #endif
 
-
 /*
- * enum dmx_success: Success codes for the Demux Callback API.
+ * TS packet reception
  */
 
-enum dmx_success {
-  DMX_OK = 0, /* Received Ok */
-  DMX_LENGTH_ERROR, /* Incorrect length */
-  DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
-  DMX_CRC_ERROR, /* Incorrect CRC */
-  DMX_FRAME_ERROR, /* Frame alignment error */
-  DMX_FIFO_ERROR, /* Receiver FIFO overrun */
-  DMX_MISSED_ERROR /* Receiver missed packet */
-} ;
-
-/*--------------------------------------------------------------------------*/
-/* TS packet reception */
-/*--------------------------------------------------------------------------*/
-
-/* TS filter type for set() */
-
-#define TS_PACKET       1   /* send TS packets (188 bytes) to callback (default) */
-#define        TS_PAYLOAD_ONLY 2   /* in case TS_PACKET is set, only send the TS
-                              payload (<=184 bytes per packet) to callback */
-#define TS_DECODER      4   /* send stream to built-in decoder (if present) */
-#define TS_DEMUX        8   /* in case TS_PACKET is set, send the TS to
-                              the demux device, not to the dvr device */
+/**
+ * enum ts_filter_type - filter type bitmap for dmx_ts_feed.set()
+ *
+ * @TS_PACKET:         Send TS packets (188 bytes) to callback (default).
+ * @TS_PAYLOAD_ONLY:   In case TS_PACKET is set, only send the TS payload
+ *                     (<=184 bytes per packet) to callback
+ * @TS_DECODER:                Send stream to built-in decoder (if present).
+ * @TS_DEMUX:          In case TS_PACKET is set, send the TS to the demux
+ *                     device, not to the dvr device
+ */
+enum ts_filter_type {
+       TS_PACKET = 1,
+       TS_PAYLOAD_ONLY = 2,
+       TS_DECODER = 4,
+       TS_DEMUX = 8,
+};
 
+/**
+ * struct dmx_ts_feed - Structure that contains a TS feed filter
+ *
+ * @is_filtering:      Set to non-zero when filtering in progress
+ * @parent:            pointer to struct dmx_demux
+ * @priv:              pointer to private data of the API client
+ * @set:               sets the TS filter
+ * @start_filtering:   starts TS filtering
+ * @stop_filtering:    stops TS filtering
+ *
+ * A TS feed is typically mapped to a hardware PID filter on the demux chip.
+ * Using this API, the client can set the filtering properties to start/stop
+ * filtering TS packets on a particular TS feed.
+ */
 struct dmx_ts_feed {
-       int is_filtering; /* Set to non-zero when filtering in progress */
-       struct dmx_demux *parent; /* Back-pointer */
-       void *priv; /* Pointer to private data of the API client */
-       int (*set) (struct dmx_ts_feed *feed,
-                   u16 pid,
-                   int type,
-                   enum dmx_ts_pes pes_type,
-                   size_t circular_buffer_size,
-                   struct timespec timeout);
-       int (*start_filtering) (struct dmx_ts_feed* feed);
-       int (*stop_filtering) (struct dmx_ts_feed* feed);
+       int is_filtering;
+       struct dmx_demux *parent;
+       void *priv;
+       int (*set)(struct dmx_ts_feed *feed,
+                  u16 pid,
+                  int type,
+                  enum dmx_ts_pes pes_type,
+                  size_t circular_buffer_size,
+                  struct timespec timeout);
+       int (*start_filtering)(struct dmx_ts_feed *feed);
+       int (*stop_filtering)(struct dmx_ts_feed *feed);
 };
 
-/*--------------------------------------------------------------------------*/
-/* Section reception */
-/*--------------------------------------------------------------------------*/
+/*
+ * Section reception
+ */
 
+/**
+ * struct dmx_section_filter - Structure that describes a section filter
+ *
+ * @filter_value: Contains up to 16 bytes (128 bits) of the TS section header
+ *               that will be matched by the section filter
+ * @filter_mask:  Contains a 16 bytes (128 bits) filter mask with the bits
+ *               specified by @filter_value that will be used on the filter
+ *               match logic.
+ * @filter_mode:  Contains a 16 bytes (128 bits) filter mode.
+ * @parent:      Pointer to struct dmx_section_feed.
+ * @priv:        Pointer to private data of the API client.
+ *
+ *
+ * The @filter_mask controls which bits of @filter_value are compared with
+ * the section headers/payload. On a binary value of 1 in filter_mask, the
+ * corresponding bits are compared. The filter only accepts sections that are
+ * equal to filter_value in all the tested bit positions.
+ */
 struct dmx_section_filter {
-       u8 filter_value [DMX_MAX_FILTER_SIZE];
-       u8 filter_mask [DMX_MAX_FILTER_SIZE];
-       u8 filter_mode [DMX_MAX_FILTER_SIZE];
-       struct dmx_section_feedparent; /* Back-pointer */
-       voidpriv; /* Pointer to private data of the API client */
+       u8 filter_value[DMX_MAX_FILTER_SIZE];
+       u8 filter_mask[DMX_MAX_FILTER_SIZE];
+       u8 filter_mode[DMX_MAX_FILTER_SIZE];
+       struct dmx_section_feed *parent; /* Back-pointer */
+       void *priv; /* Pointer to private data of the API client */
 };
 
+/**
+ * struct dmx_section_feed - Structure that contains a section feed filter
+ *
+ * @is_filtering:      Set to non-zero when filtering in progress
+ * @parent:            pointer to struct dmx_demux
+ * @priv:              pointer to private data of the API client
+ * @check_crc:         If non-zero, check the CRC values of filtered sections.
+ * @set:               sets the section filter
+ * @allocate_filter:   This function is used to allocate a section filter on
+ *                     the demux. It should only be called when no filtering
+ *                     is in progress on this section feed. If a filter cannot
+ *                     be allocated, the function fails with -ENOSPC.
+ * @release_filter:    This function releases all the resources of a
+ *                     previously allocated section filter. The function
+ *                     should not be called while filtering is in progress
+ *                     on this section feed. After calling this function,
+ *                     the caller should not try to dereference the filter
+ *                     pointer.
+ * @start_filtering:   starts section filtering
+ * @stop_filtering:    stops section filtering
+ *
+ * A TS feed is typically mapped to a hardware PID filter on the demux chip.
+ * Using this API, the client can set the filtering properties to start/stop
+ * filtering TS packets on a particular TS feed.
+ */
 struct dmx_section_feed {
-       int is_filtering; /* Set to non-zero when filtering in progress */
-       struct dmx_demux* parent; /* Back-pointer */
-       void* priv; /* Pointer to private data of the API client */
+       int is_filtering;
+       struct dmx_demux *parent;
+       void *priv;
 
        int check_crc;
+
+       /* private: Used internally at dvb_demux.c */
        u32 crc_val;
 
        u8 *secbuf;
        u8 secbuf_base[DMX_MAX_SECFEED_SIZE];
        u16 secbufp, seclen, tsfeedp;
 
-       int (*set) (struct dmx_section_feed* feed,
-                   u16 pid,
-                   size_t circular_buffer_size,
-                   int check_crc);
-       int (*allocate_filter) (struct dmx_section_feed* feed,
-                               struct dmx_section_filter** filter);
-       int (*release_filter) (struct dmx_section_feed* feed,
-                              struct dmx_section_filter* filter);
-       int (*start_filtering) (struct dmx_section_feed* feed);
-       int (*stop_filtering) (struct dmx_section_feed* feed);
+       /* public: */
+       int (*set)(struct dmx_section_feed *feed,
+                  u16 pid,
+                  size_t circular_buffer_size,
+                  int check_crc);
+       int (*allocate_filter)(struct dmx_section_feed *feed,
+                              struct dmx_section_filter **filter);
+       int (*release_filter)(struct dmx_section_feed *feed,
+                             struct dmx_section_filter *filter);
+       int (*start_filtering)(struct dmx_section_feed *feed);
+       int (*stop_filtering)(struct dmx_section_feed *feed);
 };
 
-/*--------------------------------------------------------------------------*/
-/* Callback functions */
-/*--------------------------------------------------------------------------*/
-
-typedef int (*dmx_ts_cb) ( const u8 * buffer1,
-                          size_t buffer1_length,
-                          const u8 * buffer2,
-                          size_t buffer2_length,
-                          struct dmx_ts_feed* source,
-                          enum dmx_success success);
+/*
+ * Callback functions
+ */
 
-typedef int (*dmx_section_cb) (        const u8 * buffer1,
-                               size_t buffer1_len,
-                               const u8 * buffer2,
-                               size_t buffer2_len,
-                               struct dmx_section_filter * source,
-                               enum dmx_success success);
+/**
+ * typedef dmx_ts_cb - DVB demux TS filter callback function prototype
+ *
+ * @buffer1:           Pointer to the start of the filtered TS packets.
+ * @buffer1_length:    Length of the TS data in buffer1.
+ * @buffer2:           Pointer to the tail of the filtered TS packets, or NULL.
+ * @buffer2_length:    Length of the TS data in buffer2.
+ * @source:            Indicates which TS feed is the source of the callback.
+ *
+ * This function callback prototype, provided by the client of the demux API,
+ * is called from the demux code. The function is only called when filtering
+ * on ae TS feed has been enabled using the start_filtering() function at
+ * the &dmx_demux.
+ * Any TS packets that match the filter settings are copied to a circular
+ * buffer. The filtered TS packets are delivered to the client using this
+ * callback function. The size of the circular buffer is controlled by the
+ * circular_buffer_size parameter of the &dmx_ts_feed.@set function.
+ * It is expected that the @buffer1 and @buffer2 callback parameters point to
+ * addresses within the circular buffer, but other implementations are also
+ * possible. Note that the called party should not try to free the memory
+ * the @buffer1 and @buffer2 parameters point to.
+ *
+ * When this function is called, the @buffer1 parameter typically points to
+ * the start of the first undelivered TS packet within a circular buffer.
+ * The @buffer2 buffer parameter is normally NULL, except when the received
+ * TS packets have crossed the last address of the circular buffer and
+ * ”wrapped” to the beginning of the buffer. In the latter case the @buffer1
+ * parameter would contain an address within the circular buffer, while the
+ * @buffer2 parameter would contain the first address of the circular buffer.
+ * The number of bytes delivered with this function (i.e. @buffer1_length +
+ * @buffer2_length) is usually equal to the value of callback_length parameter
+ * given in the set() function, with one exception: if a timeout occurs before
+ * receiving callback_length bytes of TS data, any undelivered packets are
+ * immediately delivered to the client by calling this function. The timeout
+ * duration is controlled by the set() function in the TS Feed API.
+ *
+ * If a TS packet is received with errors that could not be fixed by the
+ * TS-level forward error correction (FEC), the Transport_error_indicator
+ * flag of the TS packet header should be set. The TS packet should not be
+ * discarded, as the error can possibly be corrected by a higher layer
+ * protocol. If the called party is slow in processing the callback, it
+ * is possible that the circular buffer eventually fills up. If this happens,
+ * the demux driver should discard any TS packets received while the buffer
+ * is full and return -EOVERFLOW.
+ *
+ * The type of data returned to the callback can be selected by the
+ * &dmx_ts_feed.@set function. The type parameter decides if the raw
+ * TS packet (TS_PACKET) or just the payload (TS_PACKET|TS_PAYLOAD_ONLY)
+ * should be returned. If additionally the TS_DECODER bit is set the stream
+ * will also be sent to the hardware MPEG decoder.
+ *
+ * Return:
+ *     0, on success;
+ *     -EOVERFLOW, on buffer overflow.
+ */
+typedef int (*dmx_ts_cb)(const u8 *buffer1,
+                        size_t buffer1_length,
+                        const u8 *buffer2,
+                        size_t buffer2_length,
+                        struct dmx_ts_feed *source);
+
+/**
+ * typedef dmx_section_cb - DVB demux TS filter callback function prototype
+ *
+ * @buffer1:           Pointer to the start of the filtered section, e.g.
+ *                     within the circular buffer of the demux driver.
+ * @buffer1_len:       Length of the filtered section data in @buffer1,
+ *                     including headers and CRC.
+ * @buffer2:           Pointer to the tail of the filtered section data,
+ *                     or NULL. Useful to handle the wrapping of a
+ *                     circular buffer.
+ * @buffer2_len:       Length of the filtered section data in @buffer2,
+ *                     including headers and CRC.
+ * @source:            Indicates which section feed is the source of the
+ *                     callback.
+ *
+ * This function callback prototype, provided by the client of the demux API,
+ * is called from the demux code. The function is only called when
+ * filtering of sections has been enabled using the function
+ * &dmx_ts_feed.@start_filtering. When the demux driver has received a
+ * complete section that matches at least one section filter, the client
+ * is notified via this callback function. Normally this function is called
+ * for each received section; however, it is also possible to deliver
+ * multiple sections with one callback, for example when the system load
+ * is high. If an error occurs while receiving a section, this
+ * function should be called with the corresponding error type set in the
+ * success field, whether or not there is data to deliver. The Section Feed
+ * implementation should maintain a circular buffer for received sections.
+ * However, this is not necessary if the Section Feed API is implemented as
+ * a client of the TS Feed API, because the TS Feed implementation then
+ * buffers the received data. The size of the circular buffer can be
+ * configured using the &dmx_ts_feed.@set function in the Section Feed API.
+ * If there is no room in the circular buffer when a new section is received,
+ * the section must be discarded. If this happens, the value of the success
+ * parameter should be DMX_OVERRUN_ERROR on the next callback.
+ */
+typedef int (*dmx_section_cb)(const u8 *buffer1,
+                             size_t buffer1_len,
+                             const u8 *buffer2,
+                             size_t buffer2_len,
+                             struct dmx_section_filter *source);
 
 /*--------------------------------------------------------------------------*/
 /* DVB Front-End */
 /*--------------------------------------------------------------------------*/
 
+/**
+ * enum dmx_frontend_source - Used to identify the type of frontend
+ *
+ * @DMX_MEMORY_FE:     The source of the demux is memory. It means that
+ *                     the MPEG-TS to be filtered comes from userspace,
+ *                     via write() syscall.
+ *
+ * @DMX_FRONTEND_0:    The source of the demux is a frontend connected
+ *                     to the demux.
+ */
 enum dmx_frontend_source {
        DMX_MEMORY_FE,
        DMX_FRONTEND_0,
-       DMX_FRONTEND_1,
-       DMX_FRONTEND_2,
-       DMX_FRONTEND_3,
-       DMX_STREAM_0,    /* external stream input, e.g. LVDS */
-       DMX_STREAM_1,
-       DMX_STREAM_2,
-       DMX_STREAM_3
 };
 
+/**
+ * struct dmx_frontend - Structure that lists the frontends associated with
+ *                      a demux
+ *
+ * @connectivity_list: List of front-ends that can be connected to a
+ *                     particular demux;
+ * @source:            Type of the frontend.
+ *
+ * FIXME: this structure should likely be replaced soon by some
+ *     media-controller based logic.
+ */
 struct dmx_frontend {
-       struct list_head connectivity_list; /* List of front-ends that can
-                                              be connected to a particular
-                                              demux */
+       struct list_head connectivity_list;
        enum dmx_frontend_source source;
 };
 
-/*--------------------------------------------------------------------------*/
-/* MPEG-2 TS Demux */
-/*--------------------------------------------------------------------------*/
-
 /*
- * Flags OR'ed in the capabilities field of struct dmx_demux.
+ * MPEG-2 TS Demux
  */
 
-#define DMX_TS_FILTERING                        1
-#define DMX_PES_FILTERING                       2
-#define DMX_SECTION_FILTERING                   4
-#define DMX_MEMORY_BASED_FILTERING              8    /* write() available */
-#define DMX_CRC_CHECKING                        16
-#define DMX_TS_DESCRAMBLING                     32
+/**
+ * enum dmx_demux_caps - MPEG-2 TS Demux capabilities bitmap
+ *
+ * @DMX_TS_FILTERING:          set if TS filtering is supported;
+ * @DMX_SECTION_FILTERING:     set if section filtering is supported;
+ * @DMX_MEMORY_BASED_FILTERING:        set if write() available.
+ *
+ * Those flags are OR'ed in the &dmx_demux.&capabilities field
+ */
+enum dmx_demux_caps {
+       DMX_TS_FILTERING = 1,
+       DMX_SECTION_FILTERING = 4,
+       DMX_MEMORY_BASED_FILTERING = 8,
+};
 
 /*
  * Demux resource type identifier.
@@ -200,42 +358,241 @@ struct dmx_frontend {
  *.
 */
 
-#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list)
+#define DMX_FE_ENTRY(list) \
+       list_entry(list, struct dmx_frontend, connectivity_list)
+
+/**
+ * struct dmx_demux - Structure that contains the demux capabilities and
+ *                   callbacks.
+ *
+ * @capabilities: Bitfield of capability flags.
+ *
+ * @frontend: Front-end connected to the demux
+ *
+ * @priv: Pointer to private data of the API client
+ *
+ * @open: This function reserves the demux for use by the caller and, if
+ *     necessary, initializes the demux. When the demux is no longer needed,
+ *     the function @close should be called. It should be possible for
+ *     multiple clients to access the demux at the same time. Thus, the
+ *     function implementation should increment the demux usage count when
+ *     @open is called and decrement it when @close is called.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     It returns
+ *             0 on success;
+ *             -EUSERS, if maximum usage count was reached;
+ *             -EINVAL, on bad parameter.
+ *
+ * @close: This function reserves the demux for use by the caller and, if
+ *     necessary, initializes the demux. When the demux is no longer needed,
+ *     the function @close should be called. It should be possible for
+ *     multiple clients to access the demux at the same time. Thus, the
+ *     function implementation should increment the demux usage count when
+ *     @open is called and decrement it when @close is called.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     It returns
+ *             0 on success;
+ *             -ENODEV, if demux was not in use (e. g. no users);
+ *             -EINVAL, on bad parameter.
+ *
+ * @write: This function provides the demux driver with a memory buffer
+ *     containing TS packets. Instead of receiving TS packets from the DVB
+ *     front-end, the demux driver software will read packets from memory.
+ *     Any clients of this demux with active TS, PES or Section filters will
+ *     receive filtered data via the Demux callback API (see 0). The function
+ *     returns when all the data in the buffer has been consumed by the demux.
+ *     Demux hardware typically cannot read TS from memory. If this is the
+ *     case, memory-based filtering has to be implemented entirely in software.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     The @buf function parameter contains a pointer to the TS data in
+ *     kernel-space memory.
+ *     The @count function parameter contains the length of the TS data.
+ *     It returns
+ *             0 on success;
+ *             -ERESTARTSYS, if mutex lock was interrupted;
+ *             -EINTR, if a signal handling is pending;
+ *             -ENODEV, if demux was removed;
+ *             -EINVAL, on bad parameter.
+ *
+ * @allocate_ts_feed: Allocates a new TS feed, which is used to filter the TS
+ *     packets carrying a certain PID. The TS feed normally corresponds to a
+ *     hardware PID filter on the demux chip.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     The @feed function parameter contains a pointer to the TS feed API and
+ *     instance data.
+ *     The @callback function parameter contains a pointer to the callback
+ *     function for passing received TS packet.
+ *     It returns
+ *             0 on success;
+ *             -ERESTARTSYS, if mutex lock was interrupted;
+ *             -EBUSY, if no more TS feeds is available;
+ *             -EINVAL, on bad parameter.
+ *
+ * @release_ts_feed: Releases the resources allocated with @allocate_ts_feed.
+ *     Any filtering in progress on the TS feed should be stopped before
+ *     calling this function.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     The @feed function parameter contains a pointer to the TS feed API and
+ *     instance data.
+ *     It returns
+ *             0 on success;
+ *             -EINVAL on bad parameter.
+ *
+ * @allocate_section_feed: Allocates a new section feed, i.e. a demux resource
+ *     for filtering and receiving sections. On platforms with hardware
+ *     support for section filtering, a section feed is directly mapped to
+ *     the demux HW. On other platforms, TS packets are first PID filtered in
+ *     hardware and a hardware section filter then emulated in software. The
+ *     caller obtains an API pointer of type dmx_section_feed_t as an out
+ *     parameter. Using this API the caller can set filtering parameters and
+ *     start receiving sections.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     The @feed function parameter contains a pointer to the TS feed API and
+ *     instance data.
+ *     The @callback function parameter contains a pointer to the callback
+ *     function for passing received TS packet.
+ *     It returns
+ *             0 on success;
+ *             -EBUSY, if no more TS feeds is available;
+ *             -EINVAL, on bad parameter.
+ *
+ * @release_section_feed: Releases the resources allocated with
+ *     @allocate_section_feed, including allocated filters. Any filtering in
+ *     progress on the section feed should be stopped before calling this
+ *     function.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     The @feed function parameter contains a pointer to the TS feed API and
+ *     instance data.
+ *     It returns
+ *             0 on success;
+ *             -EINVAL, on bad parameter.
+ *
+ * @add_frontend: Registers a connectivity between a demux and a front-end,
+ *     i.e., indicates that the demux can be connected via a call to
+ *     @connect_frontend to use the given front-end as a TS source. The
+ *     client of this function has to allocate dynamic or static memory for
+ *     the frontend structure and initialize its fields before calling this
+ *     function. This function is normally called during the driver
+ *     initialization. The caller must not free the memory of the frontend
+ *     struct before successfully calling @remove_frontend.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     The @frontend function parameter contains a pointer to the front-end
+ *     instance data.
+ *     It returns
+ *             0 on success;
+ *             -EINVAL, on bad parameter.
+ *
+ * @remove_frontend: Indicates that the given front-end, registered by a call
+ *     to @add_frontend, can no longer be connected as a TS source by this
+ *     demux. The function should be called when a front-end driver or a demux
+ *     driver is removed from the system. If the front-end is in use, the
+ *     function fails with the return value of -EBUSY. After successfully
+ *     calling this function, the caller can free the memory of the frontend
+ *     struct if it was dynamically allocated before the @add_frontend
+ *     operation.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     The @frontend function parameter contains a pointer to the front-end
+ *     instance data.
+ *     It returns
+ *             0 on success;
+ *             -ENODEV, if the front-end was not found,
+ *             -EINVAL, on bad parameter.
+ *
+ * @get_frontends: Provides the APIs of the front-ends that have been
+ *     registered for this demux. Any of the front-ends obtained with this
+ *     call can be used as a parameter for @connect_frontend. The include
+ *     file demux.h contains the macro DMX_FE_ENTRY() for converting an
+ *     element of the generic type struct &list_head * to the type
+ *     struct &dmx_frontend *. The caller must not free the memory of any of
+ *     the elements obtained via this function call.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     It returns a struct list_head pointer to the list of front-end
+ *     interfaces, or NULL in the case of an empty list.
+ *
+ * @connect_frontend: Connects the TS output of the front-end to the input of
+ *     the demux. A demux can only be connected to a front-end registered to
+ *     the demux with the function @add_frontend. It may or may not be
+ *     possible to connect multiple demuxes to the same front-end, depending
+ *     on the capabilities of the HW platform. When not used, the front-end
+ *     should be released by calling @disconnect_frontend.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     The @frontend function parameter contains a pointer to the front-end
+ *     instance data.
+ *     It returns
+ *             0 on success;
+ *             -EINVAL, on bad parameter.
+ *
+ * @disconnect_frontend: Disconnects the demux and a front-end previously
+ *     connected by a @connect_frontend call.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     It returns
+ *             0 on success;
+ *             -EINVAL on bad parameter.
+ *
+ * @get_pes_pids: Get the PIDs for DMX_PES_AUDIO0, DMX_PES_VIDEO0,
+ *     DMX_PES_TELETEXT0, DMX_PES_SUBTITLE0 and DMX_PES_PCR0.
+ *     The @demux function parameter contains a pointer to the demux API and
+ *     instance data.
+ *     The @pids function parameter contains an array with five u16 elements
+ *     where the PIDs will be stored.
+ *     It returns
+ *             0 on success;
+ *             -EINVAL on bad parameter.
+ */
 
 struct dmx_demux {
-       u32 capabilities;            /* Bitfield of capability flags */
-       struct dmx_frontend* frontend;    /* Front-end connected to the demux */
-       void* priv;                  /* Pointer to private data of the API client */
-       int (*open) (struct dmx_demux* demux);
-       int (*close) (struct dmx_demux* demux);
-       int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
-       int (*allocate_ts_feed) (struct dmx_demux* demux,
-                                struct dmx_ts_feed** feed,
-                                dmx_ts_cb callback);
-       int (*release_ts_feed) (struct dmx_demux* demux,
-                               struct dmx_ts_feed* feed);
-       int (*allocate_section_feed) (struct dmx_demux* demux,
-                                     struct dmx_section_feed** feed,
-                                     dmx_section_cb callback);
-       int (*release_section_feed) (struct dmx_demux* demux,
-                                    struct dmx_section_feed* feed);
-       int (*add_frontend) (struct dmx_demux* demux,
-                            struct dmx_frontend* frontend);
-       int (*remove_frontend) (struct dmx_demux* demux,
-                               struct dmx_frontend* frontend);
-       struct list_head* (*get_frontends) (struct dmx_demux* demux);
-       int (*connect_frontend) (struct dmx_demux* demux,
-                                struct dmx_frontend* frontend);
-       int (*disconnect_frontend) (struct dmx_demux* demux);
-
-       int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
-
-       int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
-
-       int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
-
-       int (*get_stc) (struct dmx_demux* demux, unsigned int num,
-                       u64 *stc, unsigned int *base);
+       enum dmx_demux_caps capabilities;
+       struct dmx_frontend *frontend;
+       void *priv;
+       int (*open)(struct dmx_demux *demux);
+       int (*close)(struct dmx_demux *demux);
+       int (*write)(struct dmx_demux *demux, const char __user *buf,
+                    size_t count);
+       int (*allocate_ts_feed)(struct dmx_demux *demux,
+                               struct dmx_ts_feed **feed,
+                               dmx_ts_cb callback);
+       int (*release_ts_feed)(struct dmx_demux *demux,
+                              struct dmx_ts_feed *feed);
+       int (*allocate_section_feed)(struct dmx_demux *demux,
+                                    struct dmx_section_feed **feed,
+                                    dmx_section_cb callback);
+       int (*release_section_feed)(struct dmx_demux *demux,
+                                   struct dmx_section_feed *feed);
+       int (*add_frontend)(struct dmx_demux *demux,
+                           struct dmx_frontend *frontend);
+       int (*remove_frontend)(struct dmx_demux *demux,
+                              struct dmx_frontend *frontend);
+       struct list_head *(*get_frontends)(struct dmx_demux *demux);
+       int (*connect_frontend)(struct dmx_demux *demux,
+                               struct dmx_frontend *frontend);
+       int (*disconnect_frontend)(struct dmx_demux *demux);
+
+       int (*get_pes_pids)(struct dmx_demux *demux, u16 *pids);
+
+       /* private: Not used upstream and never documented */
+#if 0
+       int (*get_caps)(struct dmx_demux *demux, struct dmx_caps *caps);
+       int (*set_source)(struct dmx_demux *demux, const dmx_source_t *src);
+#endif
+       /*
+        * private: Only used at av7110, to read some data from firmware.
+        *      As this was never documented, we have no clue about what's
+        *      there, and its usage on other drivers aren't encouraged.
+        */
+       int (*get_stc)(struct dmx_demux *demux, unsigned int num,
+                      u64 *stc, unsigned int *base);
 };
 
 #endif /* #ifndef __DEMUX_H */
index d0e3f9d85f34c7eb9d2c42b88b597ab128025c02..ea9abde902e9eb4b34075f970f905e9021f96a09 100644 (file)
@@ -352,8 +352,7 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
 
 static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
                                       const u8 *buffer2, size_t buffer2_len,
-                                      struct dmx_section_filter *filter,
-                                      enum dmx_success success)
+                                      struct dmx_section_filter *filter)
 {
        struct dmxdev_filter *dmxdevfilter = filter->priv;
        int ret;
@@ -386,8 +385,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
 
 static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
                                  const u8 *buffer2, size_t buffer2_len,
-                                 struct dmx_ts_feed *feed,
-                                 enum dmx_success success)
+                                 struct dmx_ts_feed *feed)
 {
        struct dmxdev_filter *dmxdevfilter = feed->priv;
        struct dvb_ringbuffer *buffer;
@@ -1023,6 +1021,9 @@ static int dvb_demux_do_ioctl(struct file *file,
                dmxdev->demux->get_pes_pids(dmxdev->demux, parg);
                break;
 
+#if 0
+       /* Not used upstream and never documented */
+
        case DMX_GET_CAPS:
                if (!dmxdev->demux->get_caps) {
                        ret = -EINVAL;
@@ -1038,6 +1039,7 @@ static int dvb_demux_do_ioctl(struct file *file,
                }
                ret = dmxdev->demux->set_source(dmxdev->demux, parg);
                break;
+#endif
 
        case DMX_GET_STC:
                if (!dmxdev->demux->get_stc) {
index aba3b4fbd704c6fd74157c8d261939b8fd82052e..1e4bbbd34d911fc5f22b2421f3b45a385c094c07 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 #ifndef _DVB_CA_EN50221_H_
 #define DVB_CA_EN50221_CAMCHANGE_REMOVED               0
 #define DVB_CA_EN50221_CAMCHANGE_INSERTED              1
 
-
-
-/* Structure describing a CA interface */
+/**
+ * struct dvb_ca_en50221- Structure describing a CA interface
+ *
+ * @owner:             the module owning this structure
+ * @read_attribute_mem:        function for reading attribute memory on the CAM
+ * @write_attribute_mem: function for writing attribute memory on the CAM
+ * @read_cam_control:  function for reading the control interface on the CAM
+ * @write_cam_control: function for reading the control interface on the CAM
+ * @slot_reset:                function to reset the CAM slot
+ * @slot_shutdown:     function to shutdown a CAM slot
+ * @slot_ts_enable:    function to enable the Transport Stream on a CAM slot
+ * @poll_slot_status:  function to poll slot status. Only necessary if
+ *                     DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set.
+ * @data:              private data, used by caller.
+ * @private:           Opaque data used by the dvb_ca core. Do not modify!
+ *
+ * NOTE: the read_*, write_* and poll_slot_status functions will be
+ * called for different slots concurrently and need to use locks where
+ * and if appropriate. There will be no concurrent access to one slot.
+ */
 struct dvb_ca_en50221 {
+       struct module *owner;
 
-       /* the module owning this structure */
-       struct module* owner;
-
-       /* NOTE: the read_*, write_* and poll_slot_status functions will be
-        * called for different slots concurrently and need to use locks where
-        * and if appropriate. There will be no concurrent access to one slot.
-        */
+       int (*read_attribute_mem)(struct dvb_ca_en50221 *ca,
+                                 int slot, int address);
+       int (*write_attribute_mem)(struct dvb_ca_en50221 *ca,
+                                  int slot, int address, u8 value);
 
-       /* functions for accessing attribute memory on the CAM */
-       int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
-       int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value);
+       int (*read_cam_control)(struct dvb_ca_en50221 *ca,
+                               int slot, u8 address);
+       int (*write_cam_control)(struct dvb_ca_en50221 *ca,
+                                int slot, u8 address, u8 value);
 
-       /* functions for accessing the control interface on the CAM */
-       int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address);
-       int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value);
+       int (*slot_reset)(struct dvb_ca_en50221 *ca, int slot);
+       int (*slot_shutdown)(struct dvb_ca_en50221 *ca, int slot);
+       int (*slot_ts_enable)(struct dvb_ca_en50221 *ca, int slot);
 
-       /* Functions for controlling slots */
-       int (*slot_reset)(struct dvb_ca_en50221* ca, int slot);
-       int (*slot_shutdown)(struct dvb_ca_en50221* ca, int slot);
-       int (*slot_ts_enable)(struct dvb_ca_en50221* ca, int slot);
+       int (*poll_slot_status)(struct dvb_ca_en50221 *ca, int slot, int open);
 
-       /*
-       * Poll slot status.
-       * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set
-       */
-       int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open);
+       void *data;
 
-       /* private data, used by caller */
-       void* data;
-
-       /* Opaque data used by the dvb_ca core. Do not modify! */
-       void* private;
+       void *private;
 };
 
-
-
-
-/* ******************************************************************************** */
-/* Functions for reporting IRQ events */
+/*
+ * Functions for reporting IRQ events
+ */
 
 /**
  * dvb_ca_en50221_camchange_irq - A CAMCHANGE IRQ has occurred.
@@ -89,7 +88,8 @@ struct dvb_ca_en50221 {
  * @slot: Slot concerned.
  * @change_type: One of the DVB_CA_CAMCHANGE_* values
  */
-void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type);
+void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot,
+                                 int change_type);
 
 /**
  * dvb_ca_en50221_camready_irq - A CAMREADY IRQ has occurred.
@@ -97,7 +97,7 @@ void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int ch
  * @pubca: CA instance.
  * @slot: Slot concerned.
  */
-void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221pubca, int slot);
+void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot);
 
 /**
  * dvb_ca_en50221_frda_irq - An FR or a DA IRQ has occurred.
@@ -105,12 +105,11 @@ void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot);
  * @ca: CA instance.
  * @slot: Slot concerned.
  */
-void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot);
-
+void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *ca, int slot);
 
-
-/* ******************************************************************************** */
-/* Initialisation/shutdown functions */
+/*
+ * Initialisation/shutdown functions
+ */
 
 /**
  * dvb_ca_en50221_init - Initialise a new DVB CA device.
@@ -122,15 +121,15 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot);
  *
  * @return 0 on success, nonzero on failure
  */
-extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count);
+extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
+                              struct dvb_ca_en50221 *ca, int flags,
+                              int slot_count);
 
 /**
  * dvb_ca_en50221_release - Release a DVB CA device.
  *
  * @ca: The associated dvb_ca instance.
  */
-extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca);
-
-
+extern void dvb_ca_en50221_release(struct dvb_ca_en50221 *ca);
 
 #endif
index 6c7ff0cdcd32ddd44cae9dcf85e98054a7601052..0cc5e935166ca8908a6fb79afbaf8b80613f2843 100644 (file)
@@ -130,7 +130,7 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
 
        feed->peslen += count;
 
-       return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
+       return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts);
 }
 
 static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
@@ -152,7 +152,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
                return 0;
 
        return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
-                           NULL, 0, &f->filter, DMX_OK);
+                           NULL, 0, &f->filter);
 }
 
 static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
@@ -367,8 +367,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
                        if (feed->ts_type & TS_PAYLOAD_ONLY)
                                dvb_dmx_swfilter_payload(feed, buf);
                        else
-                               feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
-                                           DMX_OK);
+                               feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
                }
                if (feed->ts_type & TS_DECODER)
                        if (feed->demux->write_to_decoder)
@@ -469,7 +468,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
                if (feed->pid == pid)
                        dvb_dmx_swfilter_packet_type(feed, buf);
                else if (feed->pid == 0x2000)
-                       feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+                       feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
        }
 }
 
@@ -588,7 +587,7 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
 
        spin_lock_irqsave(&demux->lock, flags);
 
-       demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK);
+       demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts);
 
        spin_unlock_irqrestore(&demux->lock, flags);
 }
index b81e026edab3003f3532d63853aabb685ebd65d1..ce4332e80a910fe653632ad4a9b870eb675bd592 100644 (file)
@@ -761,7 +761,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 
 static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
                               const u8 *buffer2, size_t buffer2_len,
-                              struct dmx_ts_feed *feed, enum dmx_success success)
+                              struct dmx_ts_feed *feed)
 {
        struct net_device *dev = feed->priv;
 
@@ -870,8 +870,7 @@ static void dvb_net_sec(struct net_device *dev,
 
 static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
                 const u8 *buffer2, size_t buffer2_len,
-                struct dmx_section_filter *filter,
-                enum dmx_success success)
+                struct dmx_section_filter *filter)
 {
        struct net_device *dev = filter->priv;
 
index 34b9441840da297b7104fc63b743424cae7fcf95..445a15c2714fe62af2b22a61e1e78eef64b89d52 100644 (file)
@@ -2950,10 +2950,9 @@ struct dvb_frontend *drxd_attach(const struct drxd_config *config,
 {
        struct drxd_state *state = NULL;
 
-       state = kmalloc(sizeof(struct drxd_state), GFP_KERNEL);
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
        if (!state)
                return NULL;
-       memset(state, 0, sizeof(*state));
 
        state->ops = drxd_ops;
        state->dev = dev;
index bf306a230eb06367b48e55b12d16d655e596cde3..dcd8d94c10376ce31ab691a1c460696c14d876b2 100644 (file)
@@ -490,7 +490,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
 
 /* Videobuf2 operations */
 static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
-               const struct v4l2_format *fmt, unsigned int *nbuffers,
+               const void *parg, unsigned int *nbuffers,
                unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
        struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq);
index d1e7102d11fd1ba0b15738c7b094d208dcad9709..38a20fe181eef9b09e73cdf266ce4642a074a6f3 100644 (file)
@@ -437,7 +437,6 @@ MODULE_DEVICE_TABLE(i2c, ml86v7667_id);
 static struct i2c_driver ml86v7667_i2c_driver = {
        .driver = {
                .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
        },
        .probe          = ml86v7667_probe,
        .remove         = ml86v7667_remove,
index 636ebd6fe5dccd1e7cea987da713598f895f5df5..fb39dfd55e7531ccd9e24a952454f9b050023dee 100644 (file)
@@ -3131,6 +3131,7 @@ static const struct of_device_id smiapp_of_table[] = {
        { .compatible = "nokia,smia" },
        { },
 };
+MODULE_DEVICE_TABLE(of, smiapp_of_table);
 
 static const struct i2c_device_id smiapp_id_table[] = {
        { SMIAPP_NAME, 0 },
index 7d331a4c33a2b15304b5aa1887ff03906966f212..ff46e424262f04d5c6aca7a55ccda9743b803483 100644 (file)
@@ -43,11 +43,11 @@ static const struct v4l2_dv_timings cea1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
 
 /* vb2 DMA streaming ops */
 
-static int cobalt_queue_setup(struct vb2_queue *q,
-                       const struct v4l2_format *fmt,
+static int cobalt_queue_setup(struct vb2_queue *q, const void *parg,
                        unsigned int *num_buffers, unsigned int *num_planes,
                        unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct cobalt_stream *s = q->drv_priv;
        unsigned size = s->stride * s->height;
 
index 316a32213eff3993460f5e013f330a9356367022..88a3afb66d10bde76002c2da4ee16493bb10f2bd 100644 (file)
@@ -1138,7 +1138,7 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index 09ad51280295be49d2d5308bb2a4a6c97f19ae79..c4307ad8594c577e074aab2cb2728f3c42db01a8 100644 (file)
@@ -92,7 +92,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index 6c9bb0316abaf76c393c5241d43f6692eacc7818..cf3cb1324c55ad7c60d02878ff86f59f87ee1620 100644 (file)
@@ -121,7 +121,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev    *dev,
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index b6a193df618ae9dc4a62ebc657127b7869dc01a1..71a80e2b842ca9c395cb4a000f77ae482fb57dbc 100644 (file)
@@ -315,7 +315,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
        return 0;
 }
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index f1deb8fd271ca009acb787ce2a26033fe4289e60..26e3e296d615afdc87d0b49253f3b56772c7f3cd 100644 (file)
@@ -141,10 +141,11 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
        return handled;
 }
 
-static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int cx25821_queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct cx25821_channel *chan = q->drv_priv;
        unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3;
 
index 49d0b7c5271bd28f7e1b5d343ef100835121ae9a..8b889135be8a3ede1d026bbb6379b78fbabaad57 100644 (file)
@@ -637,7 +637,7 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index f0923fb5a35dd118c33e32d14a97a6cbe1b007fd..f04835073844be588918f94eb4022bf62567eb44 100644 (file)
@@ -82,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index 1d65543003b43f2897dd536ed3e204a676cfa50a..007a5eee8e5ed50db347e4f984785f4c5b4e54b4 100644 (file)
@@ -107,7 +107,7 @@ int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index c6a337abdbb3651e9f1fcb723a0164c949e8af8a..f3b12dbbe9a18bfd605251a46d01cb163fec2dfa 100644 (file)
@@ -429,7 +429,7 @@ static int restart_video_queue(struct cx8800_dev    *dev,
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index f27a8582d17958c18128bba96af79ed7fe573c11..d84abde5ea295ddb0963b86364933a53c944bc22 100644 (file)
@@ -131,11 +131,12 @@ static int wait_i2c_reg(void __iomem *addr)
 }
 
 static int
-dt3155_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+dt3155_queue_setup(struct vb2_queue *vq, const void *parg,
                unsigned int *nbuffers, unsigned int *num_planes,
                unsigned int sizes[], void *alloc_ctxs[])
 
 {
+       const struct v4l2_format *fmt = parg;
        struct dt3155_priv *pd = vb2_get_drv_priv(vq);
        unsigned size = pd->width * pd->height;
 
index 2ad65eb29832754b54a5d190257cadd5d6a09031..2b8e7b2f2b865fdd616356fa764a2d3fbe8e901f 100644 (file)
@@ -75,15 +75,15 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
        ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
 
        /* Get user pages for DMA Xfer */
-       down_read(&current->mm->mmap_sem);
-       y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
+       y_pages = get_user_pages_unlocked(current, current->mm,
+                               y_dma.uaddr, y_dma.page_count, 0, 1,
+                               &dma->map[0]);
        uv_pages = 0; /* silence gcc. value is set and consumed only if: */
        if (y_pages == y_dma.page_count) {
-               uv_pages = get_user_pages(current, current->mm,
-                                         uv_dma.uaddr, uv_dma.page_count, 0, 1,
-                                         &dma->map[y_pages], NULL);
+               uv_pages = get_user_pages_unlocked(current, current->mm,
+                                       uv_dma.uaddr, uv_dma.page_count, 0, 1,
+                                       &dma->map[y_pages]);
        }
-       up_read(&current->mm->mmap_sem);
 
        if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
                int rc = -EFAULT;
index 04c8411ea27d58a3f28899778fd10c71bed11250..83c90d3462e9b4384c1bb25d8621a65c556e092e 100644 (file)
@@ -277,7 +277,7 @@ static irqreturn_t netup_unidvb_isr(int irq, void *dev_id)
 }
 
 static int netup_unidvb_queue_setup(struct vb2_queue *vq,
-                                   const struct v4l2_format *fmt,
+                                   const void *parg,
                                    unsigned int *nbuffers,
                                    unsigned int *nplanes,
                                    unsigned int sizes[],
index b0ef37dc770aa1062bc827034fe91dea36f8ddee..7fb5ee7e20acfe37cd4e6df68f7800ef203f2d5c 100644 (file)
@@ -116,7 +116,7 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
 }
 EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
 
-int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index fb1605e25e528de71dfe6f4d390e40f4a4e91d77..6271b0eb02653a11290b2e35909d3834385f8f25 100644 (file)
@@ -138,7 +138,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
                                    saa7134_buffer_startpage(buf));
 }
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index 602d53d6122c6099deca74ff9b1b005a1239a959..518086c7aed5cb2bc26e0c873231327e14018ca2 100644 (file)
@@ -904,7 +904,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
                                    saa7134_buffer_startpage(buf));
 }
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index fea0514dfa4a814ab78ca80c20e5b1362eeeeec7..6b6d234f5cab213f4a40c65ed481e168447cdaaf 100644 (file)
@@ -820,7 +820,7 @@ void saa7134_video_fini(struct saa7134_dev *dev);
 
 int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
 int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
-int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[]);
 int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count);
index 78ac3fe22b45240b3104bc0ddab05f026ec3d53a..1bd2fd47421fc43e02b7ad39c28546e55b3ea69e 100644 (file)
@@ -663,7 +663,7 @@ static int solo_ring_thread(void *data)
 }
 
 static int solo_enc_queue_setup(struct vb2_queue *q,
-                               const struct v4l2_format *fmt,
+                               const void *parg,
                                unsigned int *num_buffers,
                                unsigned int *num_planes, unsigned int sizes[],
                                void *alloc_ctxs[])
index 57d0d9cf190ed8c07cb58b7b8a7648c8bc71a4c0..26df903585d7dd02a54077bc24bbba8acda87b40 100644 (file)
@@ -313,7 +313,7 @@ static void solo_stop_thread(struct solo_dev *solo_dev)
        solo_dev->kthread = NULL;
 }
 
-static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int solo_queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index fc99f33d65e943225ee2aaa075ebb36ddcb0755e..6367b455a7e7ea4f2b053b222b12d6f67b1589bd 100644 (file)
@@ -265,7 +265,7 @@ static void vip_active_buf_next(struct sta2x11_vip *vip)
 
 
 /* Videobuf2 Operations */
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned int *nbuffers, unsigned int *nplanes,
                       unsigned int sizes[], void *alloc_ctxs[])
 {
index 3f24fce74fc1a7963ff7b64f924e18cded93984f..f89364951ebdfce98cf1f2c86be284c182316c3d 100644 (file)
@@ -303,7 +303,6 @@ static int arm_thread(void *data)
 static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
                                u8 *buffer2, size_t buffer2_len,
                                struct dvb_demux_filter *dvbdmxfilter,
-                               enum dmx_success success,
                                struct av7110 *av7110)
 {
        if (!dvbdmxfilter->feed->demux->dmx.frontend)
@@ -329,16 +328,14 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
                }
                return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
                                                  buffer2, buffer2_len,
-                                                 &dvbdmxfilter->filter,
-                                                 DMX_OK);
+                                                 &dvbdmxfilter->filter);
        case DMX_TYPE_TS:
                if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
                        return 0;
                if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
                        return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
                                                         buffer2, buffer2_len,
-                                                        &dvbdmxfilter->feed->feed.ts,
-                                                        DMX_OK);
+                                                        &dvbdmxfilter->feed->feed.ts);
                else
                        av7110_p2t_write(buffer1, buffer1_len,
                                         dvbdmxfilter->feed->pid,
@@ -422,7 +419,7 @@ static void debiirq(unsigned long cookie)
                        DvbDmxFilterCallback((u8 *)av7110->debi_virt,
                                             av7110->debilen, NULL, 0,
                                             av7110->handle2filter[handle],
-                                            DMX_OK, av7110);
+                                            av7110);
                xfer = RX_BUFF;
                break;
 
index 9544cfc06601373e85e40c40bd443d3c5461e572..9ed1ec7d3551e668b2e066698ef63cd1120b9566 100644 (file)
@@ -102,7 +102,7 @@ int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
                buf[4] = buf[5] = 0;
        if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
                return dvbdmxfeed->cb.ts(buf, len, NULL, 0,
-                                        &dvbdmxfeed->feed.ts, DMX_OK);
+                                        &dvbdmxfeed->feed.ts);
        else
                return dvb_filter_pes2ts(p2t, buf, len, 1);
 }
@@ -112,7 +112,7 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
        struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
 
        dvbdmxfeed->cb.ts(data, 188, NULL, 0,
-                         &dvbdmxfeed->feed.ts, DMX_OK);
+                         &dvbdmxfeed->feed.ts);
        return 0;
 }
 
@@ -815,7 +815,7 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
                        memcpy(obuf + l, buf + c, TS_SIZE - l);
                        c = length;
                }
-               feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+               feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts);
                pes_start = 0;
        }
 }
index 323721439b8e82a91de70cba81a9b9023763d618..4c3293dcddbcde3cd6b37584c6665d870fef1bc8 100644 (file)
@@ -376,10 +376,11 @@ static int tw68_buffer_count(unsigned int size, unsigned int count)
 /* ------------------------------------------------------------- */
 /* vb2 queue operations                                          */
 
-static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int tw68_queue_setup(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct tw68_dev *dev = vb2_get_drv_priv(q);
        unsigned tot_bufs = q->num_buffers + *num_buffers;
 
index 488d2754c27cf065d514aae864ea27ba37f0d821..f0480d687f174b259affc527713a394187e069ee 100644 (file)
@@ -1908,10 +1908,11 @@ static void vpfe_calculate_offsets(struct vpfe_device *vpfe)
  * the buffer count and buffer size
  */
 static int vpfe_queue_setup(struct vb2_queue *vq,
-                           const struct v4l2_format *fmt,
+                           const void *parg,
                            unsigned int *nbuffers, unsigned int *nplanes,
                            unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct vpfe_device *vpfe = vb2_get_drv_priv(vq);
 
        if (fmt && fmt->fmt.pix.sizeimage < vpfe->fmt.fmt.pix.sizeimage)
@@ -2551,11 +2552,12 @@ static int vpfe_probe(struct platform_device *pdev)
        if (IS_ERR(ccdc->ccdc_cfg.base_addr))
                return PTR_ERR(ccdc->ccdc_cfg.base_addr);
 
-       vpfe->irq = platform_get_irq(pdev, 0);
-       if (vpfe->irq <= 0) {
+       ret = platform_get_irq(pdev, 0);
+       if (ret <= 0) {
                dev_err(&pdev->dev, "No IRQ resource\n");
                return -ENODEV;
        }
+       vpfe->irq = ret;
 
        ret = devm_request_irq(vpfe->pdev, vpfe->irq, vpfe_isr, 0,
                               "vpfe_capture0", vpfe);
index db059eb0ff197f712a9f15b094aa28a3b870f9fa..7764b9c482ef9f2af8e1f2b84fd1ebd4454f1d29 100644 (file)
@@ -202,10 +202,11 @@ static void bcap_free_sensor_formats(struct bcap_device *bcap_dev)
 }
 
 static int bcap_queue_setup(struct vb2_queue *vq,
-                               const struct v4l2_format *fmt,
+                               const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct bcap_device *bcap_dev = vb2_get_drv_priv(vq);
 
        if (fmt && fmt->fmt.pix.sizeimage < bcap_dev->fmt.sizeimage)
index 60336eec75af7ce4360bd515464472ce6dde123c..15516a6e3a3916c090762d360ee10fdaeba0efbc 100644 (file)
@@ -1131,8 +1131,7 @@ static void set_default_params(struct coda_ctx *ctx)
 /*
  * Queue operations
  */
-static int coda_queue_setup(struct vb2_queue *vq,
-                               const struct v4l2_format *fmt,
+static int coda_queue_setup(struct vb2_queue *vq, const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
index 39f8ccfae339d8d506bfa4c68546b4f5abba1cb7..6d91422c4e4c755f0b73d6806a9be31e7c00307c 100644 (file)
@@ -228,11 +228,12 @@ static int vpbe_buffer_prepare(struct vb2_buffer *vb)
  * This function allocates memory for the buffers
  */
 static int
-vpbe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+vpbe_buffer_queue_setup(struct vb2_queue *vq, const void *parg,
                        unsigned int *nbuffers, unsigned int *nplanes,
                        unsigned int sizes[], void *alloc_ctxs[])
 
 {
+       const struct v4l2_format *fmt = parg;
        /* Get the file handle object and layer object */
        struct vpbe_layer *layer = vb2_get_drv_priv(vq);
        struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
index b29bb64db8bf6f8cf061b6f832a4c7c6ce26cd59..c1e573b7cc6fb9ee66d6bcc05b7e977ecdc708c3 100644 (file)
@@ -114,10 +114,11 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
  * the buffer count and buffer size
  */
 static int vpif_buffer_queue_setup(struct vb2_queue *vq,
-                               const struct v4l2_format *fmt,
+                               const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct channel_obj *ch = vb2_get_drv_priv(vq);
        struct common_obj *common;
 
index f51518c5b7879b81b628abde01866d13cf7a59b8..fd2780306c1771eae234e74b621c0ac2920ce415 100644 (file)
@@ -109,10 +109,11 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
  * the buffer count and buffer size
  */
 static int vpif_buffer_queue_setup(struct vb2_queue *vq,
-                               const struct v4l2_format *fmt,
+                               const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct channel_obj *ch = vb2_get_drv_priv(vq);
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 
index 59d134d1fa939b8b86addf0f972bf8ca4252d998..d82e717acba7b76e90254afcddd605a7b99c8ca8 100644 (file)
@@ -212,7 +212,7 @@ put_device:
 }
 
 static int gsc_m2m_queue_setup(struct vb2_queue *vq,
-                       const struct v4l2_format *fmt,
+                       const void *parg,
                        unsigned int *num_buffers, unsigned int *num_planes,
                        unsigned int sizes[], void *allocators[])
 {
index fa698e7b916b4982c1514c8556e301fbbc343d25..99e57320e6f7b530984a6655a0152e77bb512ceb 100644 (file)
@@ -338,10 +338,11 @@ int fimc_capture_resume(struct fimc_dev *fimc)
 
 }
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned int *num_buffers, unsigned int *num_planes,
                       unsigned int sizes[], void *allocators[])
 {
+       const struct v4l2_format *pfmt = parg;
        const struct v4l2_pix_format_mplane *pixm = NULL;
        struct fimc_ctx *ctx = vq->drv_priv;
        struct fimc_frame *frame = &ctx->d_frame;
index bacc3a389b7c1ef7c3b0dff885339670f1d94d9e..6e6648446f00130217194a63a60f223d2c83360b 100644 (file)
 #include "fimc-is-param.h"
 
 static int isp_video_capture_queue_setup(struct vb2_queue *vq,
-                       const struct v4l2_format *pfmt,
+                       const void *parg,
                        unsigned int *num_buffers, unsigned int *num_planes,
                        unsigned int sizes[], void *allocators[])
 {
+       const struct v4l2_format *pfmt = parg;
        struct fimc_isp *isp = vb2_get_drv_priv(vq);
        struct v4l2_pix_format_mplane *vid_fmt = &isp->video_capture.pixfmt;
        const struct v4l2_pix_format_mplane *pixm = NULL;
index 1920cfbd0369075f04437aa5afa24213151354a1..60660c3a5de0da466ec0f714f7a5c4a536e1bc09 100644 (file)
@@ -355,10 +355,11 @@ static void stop_streaming(struct vb2_queue *q)
        fimc_lite_stop_capture(fimc, false);
 }
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned int *num_buffers, unsigned int *num_planes,
                       unsigned int sizes[], void *allocators[])
 {
+       const struct v4l2_format *pfmt = parg;
        const struct v4l2_pix_format_mplane *pixm = NULL;
        struct fimc_lite *fimc = vq->drv_priv;
        struct flite_frame *frame = &fimc->out_frame;
index 79b8a3bfbd2bce23911ed77f6b7326558beef12e..4d1d64a46b2155770dead95d8a23c60bd664475f 100644 (file)
@@ -176,7 +176,7 @@ static void fimc_job_abort(void *priv)
        fimc_m2m_shutdown(priv);
 }
 
-static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int fimc_queue_setup(struct vb2_queue *vq, const void *parg,
                            unsigned int *num_buffers, unsigned int *num_planes,
                            unsigned int sizes[], void *allocators[])
 {
index bdd8f11d8fb15e2d9f377d8c8c32cc29fd678dcd..29973f9bf8db5c0fa9eff5840c965b0466b3aa17 100644 (file)
@@ -798,7 +798,7 @@ struct vb2_dc_conf {
 };
 
 static int deinterlace_queue_setup(struct vb2_queue *vq,
-                               const struct v4l2_format *fmt,
+                               const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
index 1d95842e207106916695cf0b26fe762c5bd36e17..aa2b44041d3fac40f6d2242c566032ec074d7338 100644 (file)
@@ -1049,10 +1049,11 @@ static int mcam_read_setup(struct mcam_camera *cam)
  */
 
 static int mcam_vb_queue_setup(struct vb2_queue *vq,
-               const struct v4l2_format *fmt, unsigned int *nbufs,
+               const void *parg, unsigned int *nbufs,
                unsigned int *num_planes, unsigned int sizes[],
                void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct mcam_camera *cam = vb2_get_drv_priv(vq);
        int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2;
 
index b7cea274d7ea178d2c2448bac44b5baf49c291a2..03a1b606655df8cf81cafea470d600107be58e05 100644 (file)
@@ -689,7 +689,7 @@ static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = {
  * Queue operations
  */
 static int emmaprp_queue_setup(struct vb2_queue *vq,
-                               const struct v4l2_format *fmt,
+                               const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
index 786cc8593f9477d7241ed1bc56a84890f3cb5901..f4f591652432df898ea924a1a8f2585b08785a1f 100644 (file)
@@ -320,7 +320,7 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
  */
 
 static int isp_video_queue_setup(struct vb2_queue *queue,
-                                const struct v4l2_format *fmt,
+                                const void *parg,
                                 unsigned int *count, unsigned int *num_planes,
                                 unsigned int sizes[], void *alloc_ctxs[])
 {
index c80395df67bcfa372106400adf2964fef4ceeb11..f8e3e83c52a26328177a0d3a4895e271d2cb1c6a 100644 (file)
@@ -1015,10 +1015,11 @@ error_free:
  * ============================================================================
  */
 static int jpu_queue_setup(struct vb2_queue *vq,
-                          const struct v4l2_format *fmt,
+                          const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct jpu_ctx *ctx = vb2_get_drv_priv(vq);
        struct jpu_q_data *q_data;
        unsigned int i;
index 5666766e2b87723497c380c0691783747393d6aa..537b858cb94a62c36d93cc57c1c1dc0091be1514 100644 (file)
@@ -435,10 +435,11 @@ static void stop_streaming(struct vb2_queue *vq)
        camif_stop_capture(vp);
 }
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned int *num_buffers, unsigned int *num_planes,
                       unsigned int sizes[], void *allocators[])
 {
+       const struct v4l2_format *pfmt = parg;
        const struct v4l2_pix_format *pix = NULL;
        struct camif_vp *vp = vb2_get_drv_priv(vq);
        struct camif_dev *camif = vp->camif;
index 4db507ab6777e9d3fb3451fffcabfbae204392da..e1936d9d27dacd8d9c3d5f0398569266d72493ac 100644 (file)
@@ -101,7 +101,7 @@ static struct g2d_frame *get_frame(struct g2d_ctx *ctx,
        }
 }
 
-static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int g2d_queue_setup(struct vb2_queue *vq, const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index 2ce9fe2fcb285f863b1b73fd8c518d5eb350415b..4a608cbe0fdb4628975db86730b3ba28f3dae24a 100644 (file)
@@ -2430,7 +2430,7 @@ static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
  */
 
 static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
-                          const struct v4l2_format *fmt,
+                          const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index 7b646c2e51cd498959b27e8867f84a242bc25361..3ffe2ecfd5efe37649750c64636c91c042f57a47 100644 (file)
@@ -181,13 +181,6 @@ unlock:
                mutex_unlock(&dev->mfc_mutex);
 }
 
-static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
-{
-       mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
-       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
-       mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
-}
-
 static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
 {
        struct s5p_mfc_buf *dst_buf;
@@ -203,6 +196,7 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
                vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0, 0);
                vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1, 0);
                list_del(&dst_buf->list);
+               dst_buf->flags |= MFC_BUF_FLAG_EOS;
                ctx->dst_queue_cnt--;
                dst_buf->b->sequence = (ctx->sequence++);
 
@@ -579,17 +573,13 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
        }
 }
 
-static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx,
-                                unsigned int reason, unsigned int err)
+static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx)
 {
        struct s5p_mfc_dev *dev = ctx->dev;
        struct s5p_mfc_buf *mb_entry;
 
        mfc_debug(2, "Stream completed\n");
 
-       s5p_mfc_clear_int_flags(dev);
-       ctx->int_type = reason;
-       ctx->int_err = err;
        ctx->state = MFCINST_FINISHED;
 
        spin_lock(&dev->irqlock);
@@ -646,6 +636,13 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
                if (ctx->c_ops->post_frame_start) {
                        if (ctx->c_ops->post_frame_start(ctx))
                                mfc_err("post_frame_start() failed\n");
+
+                       if (ctx->state == MFCINST_FINISHING &&
+                                               list_empty(&ctx->ref_queue)) {
+                               s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
+                               s5p_mfc_handle_stream_complete(ctx);
+                               break;
+                       }
                        s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
                        wake_up_ctx(ctx, reason, err);
                        WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
@@ -691,7 +688,10 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
                break;
 
        case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET:
-               s5p_mfc_handle_stream_complete(ctx, reason, err);
+               s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
+               ctx->int_type = reason;
+               ctx->int_err = err;
+               s5p_mfc_handle_stream_complete(ctx);
                break;
 
        case S5P_MFC_R2H_CMD_DPB_FLUSH_RET:
index 1734775a63e64c9c82b1531f9b9653428f8063f8..8c5060a7534fc88e9ea6e82095ff3fc365b4a02f 100644 (file)
@@ -645,17 +645,22 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
                mfc_err("Call on DQBUF after unrecoverable error\n");
                return -EIO;
        }
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
-       else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+
+       switch (buf->type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
                ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
-               if (ret == 0 && ctx->state == MFCINST_FINISHED &&
-                               list_empty(&ctx->vq_dst.done_list))
+               if (ret)
+                       return ret;
+
+               if (ctx->state == MFCINST_FINISHED &&
+                   (ctx->dst_bufs[buf->index].flags & MFC_BUF_FLAG_EOS))
                        v4l2_event_queue_fh(&ctx->fh, &ev);
-       } else {
-               ret = -EINVAL;
+               return 0;
+       default:
+               return -EINVAL;
        }
-       return ret;
 }
 
 /* Export DMA buffer */
@@ -883,7 +888,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
 };
 
 static int s5p_mfc_queue_setup(struct vb2_queue *vq,
-                       const struct v4l2_format *fmt, unsigned int *buf_count,
+                       const void *parg, unsigned int *buf_count,
                        unsigned int *plane_count, unsigned int psize[],
                        void *allocators[])
 {
index 94868f7214da703f290bf6e5072acb1c65cda8bc..5c678ec9c9f26ad7e4c1025e139b76b8623b6ca8 100644 (file)
@@ -907,9 +907,9 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
                        list_add_tail(&mb_entry->list, &ctx->ref_queue);
                        ctx->ref_queue_cnt++;
                }
-               mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
-                         ctx->src_queue_cnt, ctx->ref_queue_cnt);
        }
+       mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
+                 ctx->src_queue_cnt, ctx->ref_queue_cnt);
        if ((ctx->dst_queue_cnt > 0) && (strm_size > 0)) {
                mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
                                                                        list);
@@ -932,6 +932,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
        spin_unlock_irqrestore(&dev->irqlock, flags);
        if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0))
                clear_work_bit(ctx);
+
        return 0;
 }
 
@@ -1817,7 +1818,7 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
 }
 
 static int s5p_mfc_queue_setup(struct vb2_queue *vq,
-                       const struct v4l2_format *fmt,
+                       const void *parg,
                        unsigned int *buf_count, unsigned int *plane_count,
                        unsigned int psize[], void *allocators[])
 {
@@ -1826,7 +1827,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
 
        if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
                if (ctx->state != MFCINST_GOT_INST) {
-                       mfc_err("inavlid state: %d\n", ctx->state);
+                       mfc_err("invalid state: %d\n", ctx->state);
                        return -EINVAL;
                }
 
@@ -1866,7 +1867,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
                                ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
                }
        } else {
-               mfc_err("inavlid queue type: %d\n", vq->type);
+               mfc_err("invalid queue type: %d\n", vq->type);
                return -EINVAL;
        }
        return 0;
@@ -1901,7 +1902,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
                                        vb2_dma_contig_plane_dma_addr(vb, 1);
                ctx->src_bufs_cnt++;
        } else {
-               mfc_err("inavlid queue type: %d\n", vq->type);
+               mfc_err("invalid queue type: %d\n", vq->type);
                return -EINVAL;
        }
        return 0;
@@ -1937,7 +1938,7 @@ static int s5p_mfc_buf_prepare(struct vb2_buffer *vb)
                        return -EINVAL;
                }
        } else {
-               mfc_err("inavlid queue type: %d\n", vq->type);
+               mfc_err("invalid queue type: %d\n", vq->type);
                return -EINVAL;
        }
        return 0;
index e0924a5233c8d7e742e6ecf2c6c81bc00a706be4..b95845347348a21f33dffe63799108be336f16ed 100644 (file)
@@ -554,7 +554,7 @@ static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
        enc_recon_y_addr = readl(mfc_regs->e_recon_luma_dpb_addr);
        enc_recon_c_addr = readl(mfc_regs->e_recon_chroma_dpb_addr);
 
-       mfc_debug(2, "recon y addr: 0x%08lx\n", enc_recon_y_addr);
+       mfc_debug(2, "recon y addr: 0x%08lx y_addr: 0x%08lx\n", enc_recon_y_addr, *y_addr);
        mfc_debug(2, "recon c addr: 0x%08lx\n", enc_recon_c_addr);
 }
 
@@ -1483,6 +1483,7 @@ static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
 {
        struct s5p_mfc_dev *dev = ctx->dev;
        const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       int cmd;
 
        mfc_debug(2, "++\n");
 
@@ -1493,9 +1494,13 @@ static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
 
        s5p_mfc_set_slice_mode(ctx);
 
+       if (ctx->state != MFCINST_FINISHING)
+               cmd = S5P_FIMV_CH_FRAME_START_V6;
+       else
+               cmd = S5P_FIMV_CH_LAST_FRAME_V6;
+
        writel(ctx->inst_no, mfc_regs->instance_id);
-       s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev,
-                       S5P_FIMV_CH_FRAME_START_V6, NULL);
+       s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, cmd, NULL);
 
        mfc_debug(2, "--\n");
 
@@ -1563,8 +1568,8 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
        temp_vb->flags |= MFC_BUF_FLAG_USED;
        s5p_mfc_set_dec_stream_buffer_v6(ctx,
                vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
-               ctx->consumed_stream,
-               temp_vb->b->vb2_buf.planes[0].bytesused);
+                       ctx->consumed_stream,
+                       temp_vb->b->vb2_buf.planes[0].bytesused);
        spin_unlock_irqrestore(&dev->irqlock, flags);
 
        dev->curr_ctx = ctx->num;
@@ -1592,7 +1597,7 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
 
        spin_lock_irqsave(&dev->irqlock, flags);
 
-       if (list_empty(&ctx->src_queue)) {
+       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
                mfc_debug(2, "no src buffers.\n");
                spin_unlock_irqrestore(&dev->irqlock, flags);
                return -EAGAIN;
@@ -1604,15 +1609,28 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
                return -EAGAIN;
        }
 
-       src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       src_mb->flags |= MFC_BUF_FLAG_USED;
-       src_y_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 0);
-       src_c_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 1);
+       if (list_empty(&ctx->src_queue)) {
+               /* send null frame */
+               s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0);
+               src_mb = NULL;
+       } else {
+               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+               src_mb->flags |= MFC_BUF_FLAG_USED;
+               if (src_mb->b->vb2_buf.planes[0].bytesused == 0) {
+                       s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0);
+                       ctx->state = MFCINST_FINISHING;
+               } else {
+                       src_y_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 0);
+                       src_c_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 1);
 
-       mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr);
-       mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr);
+                       mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr);
+                       mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr);
 
-       s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
+                       s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
+                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
+                               ctx->state = MFCINST_FINISHING;
+               }
+       }
 
        dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
        dst_mb->flags |= MFC_BUF_FLAG_USED;
@@ -1639,11 +1657,10 @@ static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
        spin_lock_irqsave(&dev->irqlock, flags);
        mfc_debug(2, "Preparing to init decoding.\n");
        temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       mfc_debug(2, "Header size: %d\n",
-               temp_vb->b->vb2_buf.planes[0].bytesused);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->vb2_buf.planes[0].bytesused);
        s5p_mfc_set_dec_stream_buffer_v6(ctx,
                vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), 0,
-               temp_vb->b->vb2_buf.planes[0].bytesused);
+                       temp_vb->b->vb2_buf.planes[0].bytesused);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        dev->curr_ctx = ctx->num;
        s5p_mfc_init_decode_v6(ctx);
index dba92b54a588df40f6698a0b710179159b0fd807..dc1c679e136c18456d09697e8d65bd87d67c37c4 100644 (file)
@@ -881,7 +881,7 @@ static const struct v4l2_file_operations mxr_fops = {
        .unlocked_ioctl = video_ioctl2,
 };
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
        unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[],
        void *alloc_ctxs[])
 {
index 6455cb9b3224bb4e373c885f8de9ed00b2571418..d6ab33e7060aa824accddf2e295d77062f37984c 100644 (file)
@@ -865,10 +865,11 @@ static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = {
                /* ========== Queue operations ========== */
 
 static int sh_veu_queue_setup(struct vb2_queue *vq,
-                             const struct v4l2_format *f,
+                             const void *parg,
                              unsigned int *nbuffers, unsigned int *nplanes,
                              unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *f = parg;
        struct sh_veu_dev *veu = vb2_get_drv_priv(vq);
        struct sh_veu_vfmt *vfmt;
        unsigned int size, count = *nbuffers;
index 7967a75fde36731575450535afa0aa624fae48e2..2231f8922df3d0fc0b2a72ac936278e1a39e024d 100644 (file)
@@ -243,10 +243,11 @@ static void sh_vou_stream_config(struct sh_vou_device *vou_dev)
 }
 
 /* Locking: caller holds fop_lock mutex */
-static int sh_vou_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int sh_vou_queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned int *nbuffers, unsigned int *nplanes,
                       unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq);
        struct v4l2_pix_format *pix = &vou_dev->pix;
        int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8;
index 1036f77ab28ab5fb3a6a1137c94c5bfbf20c3261..454f68f0cdad36d56acd1110976d0834771ec0fc 100644 (file)
@@ -245,7 +245,7 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset)
 /* ------------------------------------------------------------------
        Videobuf operations
    ------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
index 9079196708b161929cbfe3f0582340f5be26c76a..1f28d21a3c9a05672081b40abff0f0f368ff32af 100644 (file)
@@ -469,10 +469,11 @@ static void mx2_camera_clock_stop(struct soc_camera_host *ici)
  *  Videobuf operations
  */
 static int mx2_videobuf_setup(struct vb2_queue *vq,
-                       const struct v4l2_format *fmt,
+                       const void *parg,
                        unsigned int *count, unsigned int *num_planes,
                        unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
index 5ea4350ffdd69d42184bc20ab9572fc7252b9863..49c3a257a916e710aa8a2f832dc4030b5c98dbec 100644 (file)
@@ -185,10 +185,11 @@ static void mx3_cam_dma_done(void *arg)
  * Calculate the __buffer__ (not data) size and number of buffers.
  */
 static int mx3_videobuf_setup(struct vb2_queue *vq,
-                       const struct v4l2_format *fmt,
+                       const void *parg,
                        unsigned int *count, unsigned int *num_planes,
                        unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
index a34d1f9682359f328aece2557d742eb36f20c8ff..efe57b23fac15ce5b9d24c1e8cbbf35673d34c50 100644 (file)
@@ -527,11 +527,12 @@ struct rcar_vin_cam {
  * required
  */
 static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
-                                  const struct v4l2_format *fmt,
+                                  const void *parg,
                                   unsigned int *count,
                                   unsigned int *num_planes,
                                   unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct rcar_vin_priv *priv = ici->priv;
index 171994298fdeeafef9d0d3f84046b501ddaa2acd..67a669d826b809aade01b988d29fcf7b4efd9f2f 100644 (file)
@@ -210,11 +210,13 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev)
  *               for the current frame format if required
  */
 static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
-                       const struct v4l2_format *fmt,
+                       const void *parg,
                        unsigned int *count, unsigned int *num_planes,
                        unsigned int sizes[], void *alloc_ctxs[])
 {
-       struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
+       const struct v4l2_format *fmt = parg;
+       struct soc_camera_device *icd = container_of(vq,
+                       struct soc_camera_device, vb2_vidq);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
 
index 62b9842aa633f29eee3abe7a04ffb184d2c81151..a0d267e017f61cfd224e20a49a7f61ff11dbfe57 100644 (file)
@@ -438,10 +438,11 @@ static void bdisp_ctrls_delete(struct bdisp_ctx *ctx)
 }
 
 static int bdisp_queue_setup(struct vb2_queue *vq,
-                            const struct v4l2_format *fmt,
+                            const void *parg,
                             unsigned int *nb_buf, unsigned int *nb_planes,
                             unsigned int sizes[], void *allocators[])
 {
+       const struct v4l2_format *fmt = parg;
        struct bdisp_ctx *ctx = vb2_get_drv_priv(vq);
        struct bdisp_frame *frame = ctx_get_frame(ctx, vq->type);
 
index 641ad8f34956d547eba44776de8e4214c1b7a0ef..7420a50572d347efe374c7b7be7facc6833c7a9f 100644 (file)
@@ -3,7 +3,6 @@ config DVB_C8SECTPFE
        depends on PINCTRL && DVB_CORE && I2C
        depends on ARCH_STI || ARCH_MULTIPLATFORM || COMPILE_TEST
        select FW_LOADER
-       select FW_LOADER_USER_HELPER_FALLBACK
        select DEBUG_FS
        select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
index 4902453aeb611a6f839416d4d376d7b774124e3a..de24effd984fb3a360e269d31c483bf269f4e2b2 100644 (file)
@@ -1796,7 +1796,7 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = {
  * Queue operations
  */
 static int vpe_queue_setup(struct vb2_queue *vq,
-                          const struct v4l2_format *fmt,
+                          const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index 7c3ced045304949363e5c760fdac17b06e4c6cc1..e18fb9f9ed2f7795414f79deed1c19f6cf334374 100644 (file)
@@ -710,10 +710,11 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
  */
 
 static int vim2m_queue_setup(struct vb2_queue *vq,
-                               const struct v4l2_format *fmt,
+                               const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct vim2m_ctx *ctx = vb2_get_drv_priv(vq);
        struct vim2m_q_data *q_data;
        unsigned int size, count = *nbuffers;
index c3090932f06d56cde74f3f2ed409325b3aff1d36..0885e93ad43665b61e668a1eb2909607993371b5 100644 (file)
@@ -20,3 +20,11 @@ config VIDEO_VIVID
 
          Say Y here if you want to test video apps or debug V4L devices.
          When in doubt, say N.
+
+config VIDEO_VIVID_MAX_DEVS
+       int "Maximum number of devices"
+       depends on VIDEO_VIVID
+       default "64"
+       ---help---
+         This allows you to specify the maximum number of devices supported
+         by the vivid driver.
index a047b47167417339bf501286d4ba3d9e3f76894e..ec125becb7af995a85b2810f55424c79a96bf7c3 100644 (file)
@@ -51,7 +51,7 @@
 #define VIVID_MODULE_NAME "vivid"
 
 /* The maximum number of vivid devices */
-#define VIVID_MAX_DEVS 64
+#define VIVID_MAX_DEVS CONFIG_VIDEO_VIVID_MAX_DEVS
 
 MODULE_DESCRIPTION("Virtual Video Test Driver");
 MODULE_AUTHOR("Hans Verkuil");
@@ -1341,8 +1341,11 @@ static int vivid_remove(struct platform_device *pdev)
        struct vivid_dev *dev;
        unsigned i;
 
-       for (i = 0; vivid_devs[i]; i++) {
+
+       for (i = 0; i < n_devs; i++) {
                dev = vivid_devs[i];
+               if (!dev)
+                       continue;
 
                if (dev->has_vid_cap) {
                        v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
index 084d346fb4c4f6f9c84f17f48a11bd5eea10799c..e15eef6a94e5585ad93a0dc81dcde54563f1aff6 100644 (file)
@@ -85,6 +85,7 @@ static int vivid_fb_ioctl(struct fb_info *info, unsigned cmd, unsigned long arg)
        case FBIOGET_VBLANK: {
                struct fb_vblank vblank;
 
+               memset(&vblank, 0, sizeof(vblank));
                vblank.flags = FB_VBLANK_HAVE_COUNT | FB_VBLANK_HAVE_VCOUNT |
                        FB_VBLANK_HAVE_VSYNC;
                vblank.count = 0;
index 536a6259b8473de207a6622204038b9d9146b59f..082c401764ce8ed359df38708d69ee5c649edbf4 100644 (file)
@@ -213,7 +213,7 @@ static int vivid_thread_sdr_cap(void *data)
        return 0;
 }
 
-static int sdr_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int sdr_cap_queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned *nbuffers, unsigned *nplanes,
                       unsigned sizes[], void *alloc_ctxs[])
 {
index 29931497fa0f247cf721aa551918c74a9c69f71d..e903d023e9dfa941c1c627bb683138d6b259b46e 100644 (file)
@@ -137,10 +137,9 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,
        buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
 }
 
-static int vbi_cap_queue_setup(struct vb2_queue *vq,
-                       const struct v4l2_format *fmt,
-                       unsigned *nbuffers, unsigned *nplanes,
-                       unsigned sizes[], void *alloc_ctxs[])
+static int vbi_cap_queue_setup(struct vb2_queue *vq, const void *parg,
+                      unsigned *nbuffers, unsigned *nplanes,
+                      unsigned sizes[], void *alloc_ctxs[])
 {
        struct vivid_dev *dev = vb2_get_drv_priv(vq);
        bool is_60hz = dev->std_cap & V4L2_STD_525_60;
index 91c16884147780cef5f42d7e8988304211b96f24..75c5709f938e989d57d449041c182d2813500533 100644 (file)
@@ -27,7 +27,7 @@
 #include "vivid-vbi-out.h"
 #include "vivid-vbi-cap.h"
 
-static int vbi_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_out_queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned *nbuffers, unsigned *nplanes,
                       unsigned sizes[], void *alloc_ctxs[])
 {
index 2497107e3b98362c03b3005f48bd9a78bf366f5e..ef5412311b2fa057a9dc96f5f0f620ddfaa9f0ce 100644 (file)
@@ -95,10 +95,11 @@ static const struct v4l2_discrete_probe webcam_probe = {
        VIVID_WEBCAM_SIZES
 };
 
-static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vid_cap_queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned *nbuffers, unsigned *nplanes,
                       unsigned sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct vivid_dev *dev = vb2_get_drv_priv(vq);
        unsigned buffers = tpg_g_buffers(&dev->tpg);
        unsigned h = dev->fmt_cap_rect.height;
index 376f865f90b9e75cefdeb74ae96040d717a4f3ca..b77acb6a70138a4f093c783f73e0b4dae8ddddad 100644 (file)
 #include "vivid-kthread-out.h"
 #include "vivid-vid-out.h"
 
-static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vid_out_queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned *nbuffers, unsigned *nplanes,
                       unsigned sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct vivid_dev *dev = vb2_get_drv_priv(vq);
        const struct vivid_fmt *vfmt = dev->fmt_out;
        unsigned planes = vfmt->buffers;
index 13e4fdcd4db0cf96bbd41b60691eb789bcb34cc9..5ce88e1f5d710cea2e8fab573019750b20a7df1f 100644 (file)
@@ -787,10 +787,11 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
  */
 
 static int
-vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+vsp1_video_queue_setup(struct vb2_queue *vq, const void *parg,
                     unsigned int *nbuffers, unsigned int *nplanes,
                     unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct vsp1_video *video = vb2_get_drv_priv(vq);
        const struct v4l2_pix_format_mplane *format;
        struct v4l2_pix_format_mplane pix_mp;
index 5af66c20475bfac19aeaf088bdf77b2e2722774e..d11cc7072cd59d2c873dfe68863676b1e8731f42 100644 (file)
@@ -309,10 +309,11 @@ static void xvip_dma_complete(void *param)
 }
 
 static int
-xvip_dma_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+xvip_dma_queue_setup(struct vb2_queue *vq, const void *parg,
                     unsigned int *nbuffers, unsigned int *nplanes,
                     unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct xvip_dma *dma = vb2_get_drv_priv(vq);
 
        /* Make sure the image size is large enough. */
index 2542af3b94be04b41deed3f793fbf5985d3152b6..fcbb49757614487aa0a88e2740bc0dcd4ff73236 100644 (file)
@@ -488,7 +488,7 @@ static void airspy_disconnect(struct usb_interface *intf)
 
 /* Videobuf2 operations */
 static int airspy_queue_setup(struct vb2_queue *vq,
-               const struct v4l2_format *fmt, unsigned int *nbuffers,
+               const void *parg, unsigned int *nbuffers,
                unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
        struct airspy *s = vb2_get_drv_priv(vq);
index 5ec507e9e66aa41d21d26dda2000c83cd16f5b2e..130c8b49bf7fb56a2ca460c8bbf37ea9faf984c5 100644 (file)
 
 /* ------------------------------------------------------------------ */
 
-static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_queue_setup(struct vb2_queue *vq, const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct au0828_dev *dev = vb2_get_drv_priv(vq);
        unsigned long img_size = dev->vbi_width * dev->vbi_height * 2;
        unsigned long size;
index 065b9c8d2a8e48780565e0724cd64f4fba0e1861..45c622e234f7fb4bade7608cfdda352f908b608e 100644 (file)
@@ -638,10 +638,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
        return rc;
 }
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned int *nbuffers, unsigned int *nplanes,
                       unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct au0828_dev *dev = vb2_get_drv_priv(vq);
        unsigned long img_size = dev->height * dev->bytesperline;
        unsigned long size;
index 9798160698a359ad4c56cdf1f82018a53c0d0d30..d0d8f08e37c8706baf94552ed85a6149491e080a 100644 (file)
@@ -1114,7 +1114,8 @@ int cx231xx_enum_input(struct file *file, void *priv,
        struct cx231xx_fh *fh = priv;
        struct cx231xx *dev = fh->dev;
        u32 gen_stat;
-       unsigned int ret, n;
+       unsigned int n;
+       int ret;
 
        n = i->index;
        if (n >= MAX_CX231XX_INPUT)
index 23a6148101663364d234e4fd362fd4b31dbfd1c1..e23c285b3108f7f687f57b7ec4389ef1195640b2 100644 (file)
 
 /* ------------------------------------------------------------------ */
 
-static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_queue_setup(struct vb2_queue *vq, const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct em28xx *dev = vb2_get_drv_priv(vq);
        struct em28xx_v4l2 *v4l2 = dev->v4l2;
        unsigned long size;
index 262e0325297ea8d8dbbbe5e712094b508b189de0..6a3cf342e087416fc4532a036a3ebcc58b2771bd 100644 (file)
@@ -871,10 +871,11 @@ static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
        Videobuf2 operations
    ------------------------------------------------------------------*/
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned int *nbuffers, unsigned int *nplanes,
                       unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct em28xx *dev = vb2_get_drv_priv(vq);
        struct em28xx_v4l2 *v4l2 = dev->v4l2;
        unsigned long size;
index 63d87a2755aefc65954dd37466a704e86d843948..f3d187db936864d7d8bf713229becc19564c813c 100644 (file)
@@ -369,7 +369,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 }
 
 static int go7007_queue_setup(struct vb2_queue *q,
-               const struct v4l2_format *fmt,
+               const void *parg,
                unsigned int *num_buffers, unsigned int *num_planes,
                unsigned int sizes[], void *alloc_ctxs[])
 {
index e1d4d16ade05d0d1e23bb31ab4891a4ed66417c2..e05bfec90f4608b0d8ebce199351dfe89db11994 100644 (file)
@@ -32,8 +32,10 @@ enum {
        CMD_BOARD_ID_READ                  = 0x0e,
        CMD_VERSION_STRING_READ            = 0x0f,
        CMD_SET_FREQ                       = 0x10,
+       CMD_AMP_ENABLE                     = 0x11,
        CMD_SET_LNA_GAIN                   = 0x13,
        CMD_SET_VGA_GAIN                   = 0x14,
+       CMD_SET_TXVGA_GAIN                 = 0x15,
 };
 
 /*
@@ -44,10 +46,10 @@ enum {
 #define MAX_BULK_BUFS            (6)
 #define BULK_BUFFER_SIZE         (128 * 512)
 
-static const struct v4l2_frequency_band bands_adc[] = {
+static const struct v4l2_frequency_band bands_adc_dac[] = {
        {
                .tuner = 0,
-               .type = V4L2_TUNER_ADC,
+               .type = V4L2_TUNER_SDR,
                .index = 0,
                .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
                .rangelow   =   200000,
@@ -55,7 +57,7 @@ static const struct v4l2_frequency_band bands_adc[] = {
        },
 };
 
-static const struct v4l2_frequency_band bands_rf[] = {
+static const struct v4l2_frequency_band bands_rx_tx[] = {
        {
                .tuner = 1,
                .type = V4L2_TUNER_RF,
@@ -68,7 +70,6 @@ static const struct v4l2_frequency_band bands_rf[] = {
 
 /* stream formats */
 struct hackrf_format {
-       char    *name;
        u32     pixelformat;
        u32     buffersize;
 };
@@ -76,7 +77,6 @@ struct hackrf_format {
 /* format descriptions for capture and preview */
 static struct hackrf_format formats[] = {
        {
-               .name           = "Complex S8",
                .pixelformat    = V4L2_SDR_FMT_CS8,
                .buffersize     = BULK_BUFFER_SIZE,
        },
@@ -85,29 +85,44 @@ static struct hackrf_format formats[] = {
 static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 
 /* intermediate buffers with raw data from the USB device */
-struct hackrf_frame_buf {
-       /* common v4l buffer stuff -- must be first */
+struct hackrf_buffer {
        struct vb2_v4l2_buffer vb;
        struct list_head list;
 };
 
 struct hackrf_dev {
-#define POWER_ON           (1 << 1)
-#define URB_BUF            (1 << 2)
-#define USB_STATE_URB_BUF  (1 << 3)
+#define USB_STATE_URB_BUF                1 /* XXX: set manually */
+#define RX_ON                            4
+#define TX_ON                            5
+#define RX_ADC_FREQUENCY                11
+#define TX_DAC_FREQUENCY                12
+#define RX_BANDWIDTH                    13
+#define TX_BANDWIDTH                    14
+#define RX_RF_FREQUENCY                 15
+#define TX_RF_FREQUENCY                 16
+#define RX_RF_GAIN                      17
+#define TX_RF_GAIN                      18
+#define RX_IF_GAIN                      19
+#define RX_LNA_GAIN                     20
+#define TX_LNA_GAIN                     21
        unsigned long flags;
 
+       struct usb_interface *intf;
        struct device *dev;
        struct usb_device *udev;
-       struct video_device vdev;
+       struct video_device rx_vdev;
+       struct video_device tx_vdev;
        struct v4l2_device v4l2_dev;
 
        /* videobuf2 queue and queued buffers list */
-       struct vb2_queue vb_queue;
-       struct list_head queued_bufs;
-       spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+       struct vb2_queue rx_vb2_queue;
+       struct vb2_queue tx_vb2_queue;
+       struct list_head rx_buffer_list;
+       struct list_head tx_buffer_list;
+       spinlock_t buffer_list_lock; /* Protects buffer_list */
        unsigned sequence;           /* Buffer sequence counter */
        unsigned int vb_full;        /* vb is full and packets dropped */
+       unsigned int vb_empty;       /* vb is empty and packets dropped */
 
        /* Note if taking both locks v4l2_lock must always be locked first! */
        struct mutex v4l2_lock;      /* Protects everything else */
@@ -127,16 +142,24 @@ struct hackrf_dev {
 
        /* Current configuration */
        unsigned int f_adc;
-       unsigned int f_rf;
+       unsigned int f_dac;
+       unsigned int f_rx;
+       unsigned int f_tx;
        u32 pixelformat;
        u32 buffersize;
 
        /* Controls */
-       struct v4l2_ctrl_handler hdl;
-       struct v4l2_ctrl *bandwidth_auto;
-       struct v4l2_ctrl *bandwidth;
-       struct v4l2_ctrl *lna_gain;
-       struct v4l2_ctrl *if_gain;
+       struct v4l2_ctrl_handler rx_ctrl_handler;
+       struct v4l2_ctrl *rx_bandwidth_auto;
+       struct v4l2_ctrl *rx_bandwidth;
+       struct v4l2_ctrl *rx_rf_gain;
+       struct v4l2_ctrl *rx_lna_gain;
+       struct v4l2_ctrl *rx_if_gain;
+       struct v4l2_ctrl_handler tx_ctrl_handler;
+       struct v4l2_ctrl *tx_bandwidth_auto;
+       struct v4l2_ctrl *tx_bandwidth;
+       struct v4l2_ctrl *tx_rf_gain;
+       struct v4l2_ctrl *tx_lna_gain;
 
        /* Sample rate calc */
        unsigned long jiffies_next;
@@ -166,6 +189,7 @@ static int hackrf_ctrl_msg(struct hackrf_dev *dev, u8 request, u16 value,
        switch (request) {
        case CMD_SET_TRANSCEIVER_MODE:
        case CMD_SET_FREQ:
+       case CMD_AMP_ENABLE:
        case CMD_SAMPLE_RATE_SET:
        case CMD_BASEBAND_FILTER_BANDWIDTH_SET:
                pipe = usb_sndctrlpipe(dev->udev, 0);
@@ -175,6 +199,7 @@ static int hackrf_ctrl_msg(struct hackrf_dev *dev, u8 request, u16 value,
        case CMD_VERSION_STRING_READ:
        case CMD_SET_LNA_GAIN:
        case CMD_SET_VGA_GAIN:
+       case CMD_SET_TXVGA_GAIN:
                pipe = usb_rcvctrlpipe(dev->udev, 0);
                requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
                break;
@@ -207,25 +232,227 @@ err:
        return ret;
 }
 
+static int hackrf_set_params(struct hackrf_dev *dev)
+{
+       struct usb_interface *intf = dev->intf;
+       int ret, i;
+       u8 buf[8], u8tmp;
+       unsigned int uitmp, uitmp1, uitmp2;
+       const bool rx = test_bit(RX_ON, &dev->flags);
+       const bool tx = test_bit(TX_ON, &dev->flags);
+       static const struct {
+               u32 freq;
+       } bandwidth_lut[] = {
+               { 1750000}, /*  1.75 MHz */
+               { 2500000}, /*  2.5  MHz */
+               { 3500000}, /*  3.5  MHz */
+               { 5000000}, /*  5    MHz */
+               { 5500000}, /*  5.5  MHz */
+               { 6000000}, /*  6    MHz */
+               { 7000000}, /*  7    MHz */
+               { 8000000}, /*  8    MHz */
+               { 9000000}, /*  9    MHz */
+               {10000000}, /* 10    MHz */
+               {12000000}, /* 12    MHz */
+               {14000000}, /* 14    MHz */
+               {15000000}, /* 15    MHz */
+               {20000000}, /* 20    MHz */
+               {24000000}, /* 24    MHz */
+               {28000000}, /* 28    MHz */
+       };
+
+       if (!rx && !tx) {
+               dev_dbg(&intf->dev, "device is sleeping\n");
+               return 0;
+       }
+
+       /* ADC / DAC frequency */
+       if (rx && test_and_clear_bit(RX_ADC_FREQUENCY, &dev->flags)) {
+               dev_dbg(&intf->dev, "RX ADC frequency=%u Hz\n", dev->f_adc);
+               uitmp1 = dev->f_adc;
+               uitmp2 = 1;
+               set_bit(TX_DAC_FREQUENCY, &dev->flags);
+       } else if (tx && test_and_clear_bit(TX_DAC_FREQUENCY, &dev->flags)) {
+               dev_dbg(&intf->dev, "TX DAC frequency=%u Hz\n", dev->f_dac);
+               uitmp1 = dev->f_dac;
+               uitmp2 = 1;
+               set_bit(RX_ADC_FREQUENCY, &dev->flags);
+       } else {
+               uitmp1 = uitmp2 = 0;
+       }
+       if (uitmp1 || uitmp2) {
+               buf[0] = (uitmp1 >>  0) & 0xff;
+               buf[1] = (uitmp1 >>  8) & 0xff;
+               buf[2] = (uitmp1 >> 16) & 0xff;
+               buf[3] = (uitmp1 >> 24) & 0xff;
+               buf[4] = (uitmp2 >>  0) & 0xff;
+               buf[5] = (uitmp2 >>  8) & 0xff;
+               buf[6] = (uitmp2 >> 16) & 0xff;
+               buf[7] = (uitmp2 >> 24) & 0xff;
+               ret = hackrf_ctrl_msg(dev, CMD_SAMPLE_RATE_SET, 0, 0, buf, 8);
+               if (ret)
+                       goto err;
+       }
+
+       /* bandwidth */
+       if (rx && test_and_clear_bit(RX_BANDWIDTH, &dev->flags)) {
+               if (dev->rx_bandwidth_auto->val == true)
+                       uitmp = dev->f_adc;
+               else
+                       uitmp = dev->rx_bandwidth->val;
+
+               for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
+                       if (uitmp <= bandwidth_lut[i].freq) {
+                               uitmp = bandwidth_lut[i].freq;
+                               break;
+                       }
+               }
+               dev->rx_bandwidth->val = uitmp;
+               dev->rx_bandwidth->cur.val = uitmp;
+               dev_dbg(&intf->dev, "RX bandwidth selected=%u\n", uitmp);
+               set_bit(TX_BANDWIDTH, &dev->flags);
+       } else if (tx && test_and_clear_bit(TX_BANDWIDTH, &dev->flags)) {
+               if (dev->tx_bandwidth_auto->val == true)
+                       uitmp = dev->f_dac;
+               else
+                       uitmp = dev->tx_bandwidth->val;
+
+               for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
+                       if (uitmp <= bandwidth_lut[i].freq) {
+                               uitmp = bandwidth_lut[i].freq;
+                               break;
+                       }
+               }
+               dev->tx_bandwidth->val = uitmp;
+               dev->tx_bandwidth->cur.val = uitmp;
+               dev_dbg(&intf->dev, "TX bandwidth selected=%u\n", uitmp);
+               set_bit(RX_BANDWIDTH, &dev->flags);
+       } else {
+               uitmp = 0;
+       }
+       if (uitmp) {
+               uitmp1 = uitmp2 = 0;
+               uitmp1 |= ((uitmp >>  0) & 0xff) << 0;
+               uitmp1 |= ((uitmp >>  8) & 0xff) << 8;
+               uitmp2 |= ((uitmp >> 16) & 0xff) << 0;
+               uitmp2 |= ((uitmp >> 24) & 0xff) << 8;
+               ret = hackrf_ctrl_msg(dev, CMD_BASEBAND_FILTER_BANDWIDTH_SET,
+                                     uitmp1, uitmp2, NULL, 0);
+               if (ret)
+                       goto err;
+       }
+
+       /* RX / TX RF frequency */
+       if (rx && test_and_clear_bit(RX_RF_FREQUENCY, &dev->flags)) {
+               dev_dbg(&intf->dev, "RX RF frequency=%u Hz\n", dev->f_rx);
+               uitmp1 = dev->f_rx / 1000000;
+               uitmp2 = dev->f_rx % 1000000;
+               set_bit(TX_RF_FREQUENCY, &dev->flags);
+       } else if (tx && test_and_clear_bit(TX_RF_FREQUENCY, &dev->flags)) {
+               dev_dbg(&intf->dev, "TX RF frequency=%u Hz\n", dev->f_tx);
+               uitmp1 = dev->f_tx / 1000000;
+               uitmp2 = dev->f_tx % 1000000;
+               set_bit(RX_RF_FREQUENCY, &dev->flags);
+       } else {
+               uitmp1 = uitmp2 = 0;
+       }
+       if (uitmp1 || uitmp2) {
+               buf[0] = (uitmp1 >>  0) & 0xff;
+               buf[1] = (uitmp1 >>  8) & 0xff;
+               buf[2] = (uitmp1 >> 16) & 0xff;
+               buf[3] = (uitmp1 >> 24) & 0xff;
+               buf[4] = (uitmp2 >>  0) & 0xff;
+               buf[5] = (uitmp2 >>  8) & 0xff;
+               buf[6] = (uitmp2 >> 16) & 0xff;
+               buf[7] = (uitmp2 >> 24) & 0xff;
+               ret = hackrf_ctrl_msg(dev, CMD_SET_FREQ, 0, 0, buf, 8);
+               if (ret)
+                       goto err;
+       }
+
+       /* RX RF gain */
+       if (rx && test_and_clear_bit(RX_RF_GAIN, &dev->flags)) {
+               dev_dbg(&intf->dev, "RX RF gain val=%d->%d\n",
+                       dev->rx_rf_gain->cur.val, dev->rx_rf_gain->val);
+
+               u8tmp = (dev->rx_rf_gain->val) ? 1 : 0;
+               ret = hackrf_ctrl_msg(dev, CMD_AMP_ENABLE, u8tmp, 0, NULL, 0);
+               if (ret)
+                       goto err;
+               set_bit(TX_RF_GAIN, &dev->flags);
+       }
+
+       /* TX RF gain */
+       if (tx && test_and_clear_bit(TX_RF_GAIN, &dev->flags)) {
+               dev_dbg(&intf->dev, "TX RF gain val=%d->%d\n",
+                       dev->tx_rf_gain->cur.val, dev->tx_rf_gain->val);
+
+               u8tmp = (dev->tx_rf_gain->val) ? 1 : 0;
+               ret = hackrf_ctrl_msg(dev, CMD_AMP_ENABLE, u8tmp, 0, NULL, 0);
+               if (ret)
+                       goto err;
+               set_bit(RX_RF_GAIN, &dev->flags);
+       }
+
+       /* RX LNA gain */
+       if (rx && test_and_clear_bit(RX_LNA_GAIN, &dev->flags)) {
+               dev_dbg(dev->dev, "RX LNA gain val=%d->%d\n",
+                       dev->rx_lna_gain->cur.val, dev->rx_lna_gain->val);
+
+               ret = hackrf_ctrl_msg(dev, CMD_SET_LNA_GAIN, 0,
+                                     dev->rx_lna_gain->val, &u8tmp, 1);
+               if (ret)
+                       goto err;
+       }
+
+       /* RX IF gain */
+       if (rx && test_and_clear_bit(RX_IF_GAIN, &dev->flags)) {
+               dev_dbg(&intf->dev, "IF gain val=%d->%d\n",
+                       dev->rx_if_gain->cur.val, dev->rx_if_gain->val);
+
+               ret = hackrf_ctrl_msg(dev, CMD_SET_VGA_GAIN, 0,
+                                     dev->rx_if_gain->val, &u8tmp, 1);
+               if (ret)
+                       goto err;
+       }
+
+       /* TX LNA gain */
+       if (tx && test_and_clear_bit(TX_LNA_GAIN, &dev->flags)) {
+               dev_dbg(&intf->dev, "TX LNA gain val=%d->%d\n",
+                       dev->tx_lna_gain->cur.val, dev->tx_lna_gain->val);
+
+               ret = hackrf_ctrl_msg(dev, CMD_SET_TXVGA_GAIN, 0,
+                                     dev->tx_lna_gain->val, &u8tmp, 1);
+               if (ret)
+                       goto err;
+       }
+
+       return 0;
+err:
+       dev_dbg(&intf->dev, "failed=%d\n", ret);
+       return ret;
+}
+
 /* Private functions */
-static struct hackrf_frame_buf *hackrf_get_next_fill_buf(struct hackrf_dev *dev)
+static struct hackrf_buffer *hackrf_get_next_buffer(struct hackrf_dev *dev,
+                                                   struct list_head *buffer_list)
 {
        unsigned long flags;
-       struct hackrf_frame_buf *buf = NULL;
+       struct hackrf_buffer *buffer = NULL;
 
-       spin_lock_irqsave(&dev->queued_bufs_lock, flags);
-       if (list_empty(&dev->queued_bufs))
+       spin_lock_irqsave(&dev->buffer_list_lock, flags);
+       if (list_empty(buffer_list))
                goto leave;
 
-       buf = list_entry(dev->queued_bufs.next, struct hackrf_frame_buf, list);
-       list_del(&buf->list);
+       buffer = list_entry(buffer_list->next, struct hackrf_buffer, list);
+       list_del(&buffer->list);
 leave:
-       spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
-       return buf;
+       spin_unlock_irqrestore(&dev->buffer_list_lock, flags);
+       return buffer;
 }
 
-static unsigned int hackrf_convert_stream(struct hackrf_dev *dev,
-               void *dst, void *src, unsigned int src_len)
+static void hackrf_copy_stream(struct hackrf_dev *dev, void *dst, void *src,
+                              unsigned int src_len)
 {
        memcpy(dst, src, src_len);
 
@@ -245,22 +472,21 @@ static unsigned int hackrf_convert_stream(struct hackrf_dev *dev,
 
        /* total number of samples */
        dev->sample += src_len / 2;
-
-       return src_len;
 }
 
 /*
  * This gets called for the bulk stream pipe. This is done in interrupt
  * time, so it has to be fast, not crash, and not stall. Neat.
  */
-static void hackrf_urb_complete(struct urb *urb)
+static void hackrf_urb_complete_in(struct urb *urb)
 {
        struct hackrf_dev *dev = urb->context;
-       struct hackrf_frame_buf *fbuf;
+       struct usb_interface *intf = dev->intf;
+       struct hackrf_buffer *buffer;
+       unsigned int len;
 
-       dev_dbg_ratelimited(dev->dev, "status=%d length=%d/%d errors=%d\n",
-                       urb->status, urb->actual_length,
-                       urb->transfer_buffer_length, urb->error_count);
+       dev_dbg_ratelimited(&intf->dev, "status=%d length=%u/%u\n", urb->status,
+                           urb->actual_length, urb->transfer_buffer_length);
 
        switch (urb->status) {
        case 0:             /* success */
@@ -271,33 +497,74 @@ static void hackrf_urb_complete(struct urb *urb)
        case -ESHUTDOWN:
                return;
        default:            /* error */
-               dev_err_ratelimited(dev->dev, "URB failed %d\n", urb->status);
-               break;
+               dev_err_ratelimited(&intf->dev, "URB failed %d\n", urb->status);
+               goto exit_usb_submit_urb;
        }
 
-       if (likely(urb->actual_length > 0)) {
-               void *ptr;
-               unsigned int len;
-               /* get free framebuffer */
-               fbuf = hackrf_get_next_fill_buf(dev);
-               if (unlikely(fbuf == NULL)) {
-                       dev->vb_full++;
-                       dev_notice_ratelimited(dev->dev,
-                                       "videobuf is full, %d packets dropped\n",
-                                       dev->vb_full);
-                       goto skip;
-               }
+       /* get buffer to write */
+       buffer = hackrf_get_next_buffer(dev, &dev->rx_buffer_list);
+       if (unlikely(buffer == NULL)) {
+               dev->vb_full++;
+               dev_notice_ratelimited(&intf->dev,
+                                      "buffer is full - %u packets dropped\n",
+                                      dev->vb_full);
+               goto exit_usb_submit_urb;
+       }
+
+       len = min_t(unsigned long, vb2_plane_size(&buffer->vb.vb2_buf, 0),
+                   urb->actual_length);
+       hackrf_copy_stream(dev, vb2_plane_vaddr(&buffer->vb.vb2_buf, 0),
+                   urb->transfer_buffer, len);
+       vb2_set_plane_payload(&buffer->vb.vb2_buf, 0, len);
+       buffer->vb.sequence = dev->sequence++;
+       v4l2_get_timestamp(&buffer->vb.timestamp);
+       vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE);
+exit_usb_submit_urb:
+       usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static void hackrf_urb_complete_out(struct urb *urb)
+{
+       struct hackrf_dev *dev = urb->context;
+       struct usb_interface *intf = dev->intf;
+       struct hackrf_buffer *buffer;
+       unsigned int len;
+
+       dev_dbg_ratelimited(&intf->dev, "status=%d length=%u/%u\n", urb->status,
+                           urb->actual_length, urb->transfer_buffer_length);
+
+       switch (urb->status) {
+       case 0:             /* success */
+       case -ETIMEDOUT:    /* NAK */
+               break;
+       case -ECONNRESET:   /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:            /* error */
+               dev_err_ratelimited(&intf->dev, "URB failed %d\n", urb->status);
+       }
 
-               /* fill framebuffer */
-               ptr = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0);
-               len = hackrf_convert_stream(dev, ptr, urb->transfer_buffer,
-                               urb->actual_length);
-               vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len);
-               v4l2_get_timestamp(&fbuf->vb.timestamp);
-               fbuf->vb.sequence = dev->sequence++;
-               vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+       /* get buffer to read */
+       buffer = hackrf_get_next_buffer(dev, &dev->tx_buffer_list);
+       if (unlikely(buffer == NULL)) {
+               dev->vb_empty++;
+               dev_notice_ratelimited(&intf->dev,
+                                      "buffer is empty - %u packets dropped\n",
+                                      dev->vb_empty);
+               urb->actual_length = 0;
+               goto exit_usb_submit_urb;
        }
-skip:
+
+       len = min_t(unsigned long, urb->transfer_buffer_length,
+                   vb2_get_plane_payload(&buffer->vb.vb2_buf, 0));
+       hackrf_copy_stream(dev, urb->transfer_buffer,
+                          vb2_plane_vaddr(&buffer->vb.vb2_buf, 0), len);
+       urb->actual_length = len;
+       buffer->vb.sequence = dev->sequence++;
+       v4l2_get_timestamp(&buffer->vb.timestamp);
+       vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_DONE);
+exit_usb_submit_urb:
        usb_submit_urb(urb, GFP_ATOMIC);
 }
 
@@ -396,9 +663,19 @@ static int hackrf_free_urbs(struct hackrf_dev *dev)
        return 0;
 }
 
-static int hackrf_alloc_urbs(struct hackrf_dev *dev)
+static int hackrf_alloc_urbs(struct hackrf_dev *dev, bool rcv)
 {
        int i, j;
+       unsigned int pipe;
+       usb_complete_t complete;
+
+       if (rcv) {
+               pipe = usb_rcvbulkpipe(dev->udev, 0x81);
+               complete = &hackrf_urb_complete_in;
+       } else {
+               pipe = usb_sndbulkpipe(dev->udev, 0x02);
+               complete = &hackrf_urb_complete_out;
+       }
 
        /* allocate the URBs */
        for (i = 0; i < MAX_BULK_BUFS; i++) {
@@ -412,10 +689,10 @@ static int hackrf_alloc_urbs(struct hackrf_dev *dev)
                }
                usb_fill_bulk_urb(dev->urb_list[i],
                                dev->udev,
-                               usb_rcvbulkpipe(dev->udev, 0x81),
+                               pipe,
                                dev->buf_list[i],
                                BULK_BUFFER_SIZE,
-                               hackrf_urb_complete, dev);
+                               complete, dev);
 
                dev->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
                dev->urb_list[i]->transfer_dma = dev->dma_addr[i];
@@ -425,25 +702,6 @@ static int hackrf_alloc_urbs(struct hackrf_dev *dev)
        return 0;
 }
 
-/* Must be called with vb_queue_lock hold */
-static void hackrf_cleanup_queued_bufs(struct hackrf_dev *dev)
-{
-       unsigned long flags;
-
-       dev_dbg(dev->dev, "\n");
-
-       spin_lock_irqsave(&dev->queued_bufs_lock, flags);
-       while (!list_empty(&dev->queued_bufs)) {
-               struct hackrf_frame_buf *buf;
-
-               buf = list_entry(dev->queued_bufs.next,
-                               struct hackrf_frame_buf, list);
-               list_del(&buf->list);
-               vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-       }
-       spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
-}
-
 /* The user yanked out the cable... */
 static void hackrf_disconnect(struct usb_interface *intf)
 {
@@ -457,7 +715,8 @@ static void hackrf_disconnect(struct usb_interface *intf)
        /* No need to keep the urbs around after disconnection */
        dev->udev = NULL;
        v4l2_device_disconnect(&dev->v4l2_dev);
-       video_unregister_device(&dev->vdev);
+       video_unregister_device(&dev->tx_vdev);
+       video_unregister_device(&dev->rx_vdev);
        mutex_unlock(&dev->v4l2_lock);
        mutex_unlock(&dev->vb_queue_lock);
 
@@ -465,8 +724,33 @@ static void hackrf_disconnect(struct usb_interface *intf)
 }
 
 /* Videobuf2 operations */
+static void hackrf_return_all_buffers(struct vb2_queue *vq,
+                                     enum vb2_buffer_state state)
+{
+       struct hackrf_dev *dev = vb2_get_drv_priv(vq);
+       struct usb_interface *intf = dev->intf;
+       struct hackrf_buffer *buffer, *node;
+       struct list_head *buffer_list;
+       unsigned long flags;
+
+       dev_dbg(&intf->dev, "\n");
+
+       if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE)
+               buffer_list = &dev->rx_buffer_list;
+       else
+               buffer_list = &dev->tx_buffer_list;
+
+       spin_lock_irqsave(&dev->buffer_list_lock, flags);
+       list_for_each_entry_safe(buffer, node, buffer_list, list) {
+               dev_dbg(&intf->dev, "list_for_each_entry_safe\n");
+               vb2_buffer_done(&buffer->vb.vb2_buf, state);
+               list_del(&buffer->list);
+       }
+       spin_unlock_irqrestore(&dev->buffer_list_lock, flags);
+}
+
 static int hackrf_queue_setup(struct vb2_queue *vq,
-               const struct v4l2_format *fmt, unsigned int *nbuffers,
+               const void *parg, unsigned int *nbuffers,
                unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
        struct hackrf_dev *dev = vb2_get_drv_priv(vq);
@@ -486,37 +770,61 @@ static int hackrf_queue_setup(struct vb2_queue *vq,
 static void hackrf_buf_queue(struct vb2_buffer *vb)
 {
        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct hackrf_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-       struct hackrf_frame_buf *buf =
-                       container_of(vbuf, struct hackrf_frame_buf, vb);
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct hackrf_dev *dev = vb2_get_drv_priv(vq);
+       struct hackrf_buffer *buffer = container_of(vbuf, struct hackrf_buffer, vb);
+       struct list_head *buffer_list;
        unsigned long flags;
 
-       spin_lock_irqsave(&dev->queued_bufs_lock, flags);
-       list_add_tail(&buf->list, &dev->queued_bufs);
-       spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
+       dev_dbg_ratelimited(&dev->intf->dev, "\n");
+
+       if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE)
+               buffer_list = &dev->rx_buffer_list;
+       else
+               buffer_list = &dev->tx_buffer_list;
+
+       spin_lock_irqsave(&dev->buffer_list_lock, flags);
+       list_add_tail(&buffer->list, buffer_list);
+       spin_unlock_irqrestore(&dev->buffer_list_lock, flags);
 }
 
 static int hackrf_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
        struct hackrf_dev *dev = vb2_get_drv_priv(vq);
+       struct usb_interface *intf = dev->intf;
        int ret;
+       unsigned int mode;
 
-       dev_dbg(dev->dev, "\n");
-
-       if (!dev->udev)
-               return -ENODEV;
+       dev_dbg(&intf->dev, "count=%i\n", count);
 
        mutex_lock(&dev->v4l2_lock);
 
-       dev->sequence = 0;
+       /* Allow only RX or TX, not both same time */
+       if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE) {
+               if (test_bit(TX_ON, &dev->flags)) {
+                       ret = -EBUSY;
+                       goto err_hackrf_return_all_buffers;
+               }
+
+               mode = 1;
+               set_bit(RX_ON, &dev->flags);
+       } else {
+               if (test_bit(RX_ON, &dev->flags)) {
+                       ret = -EBUSY;
+                       goto err_hackrf_return_all_buffers;
+               }
+
+               mode = 2;
+               set_bit(TX_ON, &dev->flags);
+       }
 
-       set_bit(POWER_ON, &dev->flags);
+       dev->sequence = 0;
 
        ret = hackrf_alloc_stream_bufs(dev);
        if (ret)
                goto err;
 
-       ret = hackrf_alloc_urbs(dev);
+       ret = hackrf_alloc_urbs(dev, (mode == 1));
        if (ret)
                goto err;
 
@@ -524,40 +832,37 @@ static int hackrf_start_streaming(struct vb2_queue *vq, unsigned int count)
        if (ret)
                goto err;
 
+       ret = hackrf_set_params(dev);
+       if (ret)
+               goto err;
+
        /* start hardware streaming */
-       ret = hackrf_ctrl_msg(dev, CMD_SET_TRANSCEIVER_MODE, 1, 0, NULL, 0);
+       ret = hackrf_ctrl_msg(dev, CMD_SET_TRANSCEIVER_MODE, mode, 0, NULL, 0);
        if (ret)
                goto err;
 
-       goto exit_mutex_unlock;
+       mutex_unlock(&dev->v4l2_lock);
+
+       return 0;
 err:
        hackrf_kill_urbs(dev);
        hackrf_free_urbs(dev);
        hackrf_free_stream_bufs(dev);
-       clear_bit(POWER_ON, &dev->flags);
-
-       /* return all queued buffers to vb2 */
-       {
-               struct hackrf_frame_buf *buf, *tmp;
-
-               list_for_each_entry_safe(buf, tmp, &dev->queued_bufs, list) {
-                       list_del(&buf->list);
-                       vb2_buffer_done(&buf->vb.vb2_buf,
-                                       VB2_BUF_STATE_QUEUED);
-               }
-       }
-
-exit_mutex_unlock:
+       clear_bit(RX_ON, &dev->flags);
+       clear_bit(TX_ON, &dev->flags);
+err_hackrf_return_all_buffers:
+       hackrf_return_all_buffers(vq, VB2_BUF_STATE_QUEUED);
        mutex_unlock(&dev->v4l2_lock);
-
+       dev_dbg(&intf->dev, "failed=%d\n", ret);
        return ret;
 }
 
 static void hackrf_stop_streaming(struct vb2_queue *vq)
 {
        struct hackrf_dev *dev = vb2_get_drv_priv(vq);
+       struct usb_interface *intf = dev->intf;
 
-       dev_dbg(dev->dev, "\n");
+       dev_dbg(&intf->dev, "\n");
 
        mutex_lock(&dev->v4l2_lock);
 
@@ -568,9 +873,12 @@ static void hackrf_stop_streaming(struct vb2_queue *vq)
        hackrf_free_urbs(dev);
        hackrf_free_stream_bufs(dev);
 
-       hackrf_cleanup_queued_bufs(dev);
+       hackrf_return_all_buffers(vq, VB2_BUF_STATE_ERROR);
 
-       clear_bit(POWER_ON, &dev->flags);
+       if (vq->type == V4L2_BUF_TYPE_SDR_CAPTURE)
+               clear_bit(RX_ON, &dev->flags);
+       else
+               clear_bit(TX_ON, &dev->flags);
 
        mutex_unlock(&dev->v4l2_lock);
 }
@@ -588,29 +896,46 @@ static int hackrf_querycap(struct file *file, void *fh,
                struct v4l2_capability *cap)
 {
        struct hackrf_dev *dev = video_drvdata(file);
+       struct usb_interface *intf = dev->intf;
+       struct video_device *vdev = video_devdata(file);
 
-       dev_dbg(dev->dev, "\n");
+       dev_dbg(&intf->dev, "\n");
+
+       if (vdev->vfl_dir == VFL_DIR_RX)
+               cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
+                                  V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
 
+       else
+               cap->device_caps = V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR |
+                                  V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+
+       cap->capabilities = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
+                           V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR |
+                           V4L2_CAP_STREAMING | V4L2_CAP_READWRITE |
+                           V4L2_CAP_DEVICE_CAPS;
        strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
-       strlcpy(cap->card, dev->vdev.name, sizeof(cap->card));
+       strlcpy(cap->card, dev->rx_vdev.name, sizeof(cap->card));
        usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-       cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
-                       V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
-       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 
        return 0;
 }
 
-static int hackrf_s_fmt_sdr_cap(struct file *file, void *priv,
-               struct v4l2_format *f)
+static int hackrf_s_fmt_sdr(struct file *file, void *priv,
+                           struct v4l2_format *f)
 {
        struct hackrf_dev *dev = video_drvdata(file);
-       struct vb2_queue *q = &dev->vb_queue;
+       struct video_device *vdev = video_devdata(file);
+       struct vb2_queue *q;
        int i;
 
        dev_dbg(dev->dev, "pixelformat fourcc %4.4s\n",
                        (char *)&f->fmt.sdr.pixelformat);
 
+       if (vdev->vfl_dir == VFL_DIR_RX)
+               q = &dev->rx_vb2_queue;
+       else
+               q = &dev->tx_vb2_queue;
+
        if (vb2_is_busy(q))
                return -EBUSY;
 
@@ -632,8 +957,8 @@ static int hackrf_s_fmt_sdr_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int hackrf_g_fmt_sdr_cap(struct file *file, void *priv,
-               struct v4l2_format *f)
+static int hackrf_g_fmt_sdr(struct file *file, void *priv,
+                           struct v4l2_format *f)
 {
        struct hackrf_dev *dev = video_drvdata(file);
 
@@ -647,8 +972,8 @@ static int hackrf_g_fmt_sdr_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int hackrf_try_fmt_sdr_cap(struct file *file, void *priv,
-               struct v4l2_format *f)
+static int hackrf_try_fmt_sdr(struct file *file, void *priv,
+                             struct v4l2_format *f)
 {
        struct hackrf_dev *dev = video_drvdata(file);
        int i;
@@ -670,8 +995,8 @@ static int hackrf_try_fmt_sdr_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int hackrf_enum_fmt_sdr_cap(struct file *file, void *priv,
-               struct v4l2_fmtdesc *f)
+static int hackrf_enum_fmt_sdr(struct file *file, void *priv,
+                              struct v4l2_fmtdesc *f)
 {
        struct hackrf_dev *dev = video_drvdata(file);
 
@@ -680,7 +1005,6 @@ static int hackrf_enum_fmt_sdr_cap(struct file *file, void *priv,
        if (f->index >= NUM_FORMATS)
                return -EINVAL;
 
-       strlcpy(f->description, formats[f->index].name, sizeof(f->description));
        f->pixelformat = formats[f->index].pixelformat;
 
        return 0;
@@ -713,17 +1037,56 @@ static int hackrf_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
 
        if (v->index == 0) {
                strlcpy(v->name, "HackRF ADC", sizeof(v->name));
-               v->type = V4L2_TUNER_ADC;
+               v->type = V4L2_TUNER_SDR;
                v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
-               v->rangelow  = bands_adc[0].rangelow;
-               v->rangehigh = bands_adc[0].rangehigh;
+               v->rangelow  = bands_adc_dac[0].rangelow;
+               v->rangehigh = bands_adc_dac[0].rangehigh;
                ret = 0;
        } else if (v->index == 1) {
                strlcpy(v->name, "HackRF RF", sizeof(v->name));
                v->type = V4L2_TUNER_RF;
                v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
-               v->rangelow  = bands_rf[0].rangelow;
-               v->rangehigh = bands_rf[0].rangehigh;
+               v->rangelow  = bands_rx_tx[0].rangelow;
+               v->rangehigh = bands_rx_tx[0].rangehigh;
+               ret = 0;
+       } else {
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int hackrf_s_modulator(struct file *file, void *fh,
+                             const struct v4l2_modulator *a)
+{
+       struct hackrf_dev *dev = video_drvdata(file);
+
+       dev_dbg(dev->dev, "index=%d\n", a->index);
+
+       return a->index > 1 ? -EINVAL : 0;
+}
+
+static int hackrf_g_modulator(struct file *file, void *fh,
+                             struct v4l2_modulator *a)
+{
+       struct hackrf_dev *dev = video_drvdata(file);
+       int ret;
+
+       dev_dbg(dev->dev, "index=%d\n", a->index);
+
+       if (a->index == 0) {
+               strlcpy(a->name, "HackRF DAC", sizeof(a->name));
+               a->type = V4L2_TUNER_SDR;
+               a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+               a->rangelow  = bands_adc_dac[0].rangelow;
+               a->rangehigh = bands_adc_dac[0].rangehigh;
+               ret = 0;
+       } else if (a->index == 1) {
+               strlcpy(a->name, "HackRF RF", sizeof(a->name));
+               a->type = V4L2_TUNER_RF;
+               a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+               a->rangelow  = bands_rx_tx[0].rangelow;
+               a->rangehigh = bands_rx_tx[0].rangehigh;
                ret = 0;
        } else {
                ret = -EINVAL;
@@ -736,47 +1099,46 @@ static int hackrf_s_frequency(struct file *file, void *priv,
                const struct v4l2_frequency *f)
 {
        struct hackrf_dev *dev = video_drvdata(file);
+       struct usb_interface *intf = dev->intf;
+       struct video_device *vdev = video_devdata(file);
        int ret;
-       unsigned int upper, lower;
-       u8 buf[8];
+       unsigned int uitmp;
 
-       dev_dbg(dev->dev, "tuner=%d type=%d frequency=%u\n",
+       dev_dbg(&intf->dev, "tuner=%d type=%d frequency=%u\n",
                        f->tuner, f->type, f->frequency);
 
        if (f->tuner == 0) {
-               dev->f_adc = clamp_t(unsigned int, f->frequency,
-                               bands_adc[0].rangelow, bands_adc[0].rangehigh);
-               dev_dbg(dev->dev, "ADC frequency=%u Hz\n", dev->f_adc);
-               upper = dev->f_adc;
-               lower = 1;
-               buf[0] = (upper >>  0) & 0xff;
-               buf[1] = (upper >>  8) & 0xff;
-               buf[2] = (upper >> 16) & 0xff;
-               buf[3] = (upper >> 24) & 0xff;
-               buf[4] = (lower >>  0) & 0xff;
-               buf[5] = (lower >>  8) & 0xff;
-               buf[6] = (lower >> 16) & 0xff;
-               buf[7] = (lower >> 24) & 0xff;
-               ret = hackrf_ctrl_msg(dev, CMD_SAMPLE_RATE_SET, 0, 0, buf, 8);
+               uitmp = clamp(f->frequency, bands_adc_dac[0].rangelow,
+                             bands_adc_dac[0].rangehigh);
+               if (vdev->vfl_dir == VFL_DIR_RX) {
+                       dev->f_adc = uitmp;
+                       set_bit(RX_ADC_FREQUENCY, &dev->flags);
+               } else {
+                       dev->f_dac = uitmp;
+                       set_bit(TX_DAC_FREQUENCY, &dev->flags);
+               }
        } else if (f->tuner == 1) {
-               dev->f_rf = clamp_t(unsigned int, f->frequency,
-                               bands_rf[0].rangelow, bands_rf[0].rangehigh);
-               dev_dbg(dev->dev, "RF frequency=%u Hz\n", dev->f_rf);
-               upper = dev->f_rf / 1000000;
-               lower = dev->f_rf % 1000000;
-               buf[0] = (upper >>  0) & 0xff;
-               buf[1] = (upper >>  8) & 0xff;
-               buf[2] = (upper >> 16) & 0xff;
-               buf[3] = (upper >> 24) & 0xff;
-               buf[4] = (lower >>  0) & 0xff;
-               buf[5] = (lower >>  8) & 0xff;
-               buf[6] = (lower >> 16) & 0xff;
-               buf[7] = (lower >> 24) & 0xff;
-               ret = hackrf_ctrl_msg(dev, CMD_SET_FREQ, 0, 0, buf, 8);
+               uitmp = clamp(f->frequency, bands_rx_tx[0].rangelow,
+                             bands_rx_tx[0].rangehigh);
+               if (vdev->vfl_dir == VFL_DIR_RX) {
+                       dev->f_rx = uitmp;
+                       set_bit(RX_RF_FREQUENCY, &dev->flags);
+               } else {
+                       dev->f_tx = uitmp;
+                       set_bit(TX_RF_FREQUENCY, &dev->flags);
+               }
        } else {
                ret = -EINVAL;
+               goto err;
        }
 
+       ret = hackrf_set_params(dev);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       dev_dbg(&intf->dev, "failed=%d\n", ret);
        return ret;
 }
 
@@ -784,22 +1146,32 @@ static int hackrf_g_frequency(struct file *file, void *priv,
                struct v4l2_frequency *f)
 {
        struct hackrf_dev *dev = video_drvdata(file);
+       struct usb_interface *intf = dev->intf;
+       struct video_device *vdev = video_devdata(file);
        int ret;
 
        dev_dbg(dev->dev, "tuner=%d type=%d\n", f->tuner, f->type);
 
        if (f->tuner == 0) {
-               f->type = V4L2_TUNER_ADC;
-               f->frequency = dev->f_adc;
-               ret = 0;
+               f->type = V4L2_TUNER_SDR;
+               if (vdev->vfl_dir == VFL_DIR_RX)
+                       f->frequency = dev->f_adc;
+               else
+                       f->frequency = dev->f_dac;
        } else if (f->tuner == 1) {
                f->type = V4L2_TUNER_RF;
-               f->frequency = dev->f_rf;
-               ret = 0;
+               if (vdev->vfl_dir == VFL_DIR_RX)
+                       f->frequency = dev->f_rx;
+               else
+                       f->frequency = dev->f_tx;
        } else {
                ret = -EINVAL;
+               goto err;
        }
 
+       return 0;
+err:
+       dev_dbg(&intf->dev, "failed=%d\n", ret);
        return ret;
 }
 
@@ -813,17 +1185,17 @@ static int hackrf_enum_freq_bands(struct file *file, void *priv,
                        band->tuner, band->type, band->index);
 
        if (band->tuner == 0) {
-               if (band->index >= ARRAY_SIZE(bands_adc)) {
+               if (band->index >= ARRAY_SIZE(bands_adc_dac)) {
                        ret = -EINVAL;
                } else {
-                       *band = bands_adc[band->index];
+                       *band = bands_adc_dac[band->index];
                        ret = 0;
                }
        } else if (band->tuner == 1) {
-               if (band->index >= ARRAY_SIZE(bands_rf)) {
+               if (band->index >= ARRAY_SIZE(bands_rx_tx)) {
                        ret = -EINVAL;
                } else {
-                       *band = bands_rf[band->index];
+                       *band = bands_rx_tx[band->index];
                        ret = 0;
                }
        } else {
@@ -836,10 +1208,15 @@ static int hackrf_enum_freq_bands(struct file *file, void *priv,
 static const struct v4l2_ioctl_ops hackrf_ioctl_ops = {
        .vidioc_querycap          = hackrf_querycap,
 
-       .vidioc_s_fmt_sdr_cap     = hackrf_s_fmt_sdr_cap,
-       .vidioc_g_fmt_sdr_cap     = hackrf_g_fmt_sdr_cap,
-       .vidioc_enum_fmt_sdr_cap  = hackrf_enum_fmt_sdr_cap,
-       .vidioc_try_fmt_sdr_cap   = hackrf_try_fmt_sdr_cap,
+       .vidioc_s_fmt_sdr_cap     = hackrf_s_fmt_sdr,
+       .vidioc_g_fmt_sdr_cap     = hackrf_g_fmt_sdr,
+       .vidioc_enum_fmt_sdr_cap  = hackrf_enum_fmt_sdr,
+       .vidioc_try_fmt_sdr_cap   = hackrf_try_fmt_sdr,
+
+       .vidioc_s_fmt_sdr_out     = hackrf_s_fmt_sdr,
+       .vidioc_g_fmt_sdr_out     = hackrf_g_fmt_sdr,
+       .vidioc_enum_fmt_sdr_out  = hackrf_enum_fmt_sdr,
+       .vidioc_try_fmt_sdr_out   = hackrf_try_fmt_sdr,
 
        .vidioc_reqbufs           = vb2_ioctl_reqbufs,
        .vidioc_create_bufs       = vb2_ioctl_create_bufs,
@@ -847,6 +1224,7 @@ static const struct v4l2_ioctl_ops hackrf_ioctl_ops = {
        .vidioc_querybuf          = vb2_ioctl_querybuf,
        .vidioc_qbuf              = vb2_ioctl_qbuf,
        .vidioc_dqbuf             = vb2_ioctl_dqbuf,
+       .vidioc_expbuf            = vb2_ioctl_expbuf,
 
        .vidioc_streamon          = vb2_ioctl_streamon,
        .vidioc_streamoff         = vb2_ioctl_streamoff,
@@ -854,6 +1232,9 @@ static const struct v4l2_ioctl_ops hackrf_ioctl_ops = {
        .vidioc_s_tuner           = hackrf_s_tuner,
        .vidioc_g_tuner           = hackrf_g_tuner,
 
+       .vidioc_s_modulator       = hackrf_s_modulator,
+       .vidioc_g_modulator       = hackrf_g_modulator,
+
        .vidioc_s_frequency       = hackrf_s_frequency,
        .vidioc_g_frequency       = hackrf_g_frequency,
        .vidioc_enum_freq_bands   = hackrf_enum_freq_bands,
@@ -868,6 +1249,7 @@ static const struct v4l2_file_operations hackrf_fops = {
        .open                     = v4l2_fh_open,
        .release                  = vb2_fop_release,
        .read                     = vb2_fop_read,
+       .write                    = vb2_fop_write,
        .poll                     = vb2_fop_poll,
        .mmap                     = vb2_fop_mmap,
        .unlocked_ioctl           = video_ioctl2,
@@ -884,135 +1266,93 @@ static void hackrf_video_release(struct v4l2_device *v)
 {
        struct hackrf_dev *dev = container_of(v, struct hackrf_dev, v4l2_dev);
 
-       v4l2_ctrl_handler_free(&dev->hdl);
+       dev_dbg(dev->dev, "\n");
+
+       v4l2_ctrl_handler_free(&dev->rx_ctrl_handler);
+       v4l2_ctrl_handler_free(&dev->tx_ctrl_handler);
        v4l2_device_unregister(&dev->v4l2_dev);
        kfree(dev);
 }
 
-static int hackrf_set_bandwidth(struct hackrf_dev *dev)
-{
-       int ret, i;
-       u16 u16tmp, u16tmp2;
-       unsigned int bandwidth;
-
-       static const struct {
-               u32 freq;
-       } bandwidth_lut[] = {
-               { 1750000}, /*  1.75 MHz */
-               { 2500000}, /*  2.5  MHz */
-               { 3500000}, /*  3.5  MHz */
-               { 5000000}, /*  5    MHz */
-               { 5500000}, /*  5.5  MHz */
-               { 6000000}, /*  6    MHz */
-               { 7000000}, /*  7    MHz */
-               { 8000000}, /*  8    MHz */
-               { 9000000}, /*  9    MHz */
-               {10000000}, /* 10    MHz */
-               {12000000}, /* 12    MHz */
-               {14000000}, /* 14    MHz */
-               {15000000}, /* 15    MHz */
-               {20000000}, /* 20    MHz */
-               {24000000}, /* 24    MHz */
-               {28000000}, /* 28    MHz */
-       };
-
-       dev_dbg(dev->dev, "bandwidth auto=%d->%d val=%d->%d f_adc=%u\n",
-                       dev->bandwidth_auto->cur.val,
-                       dev->bandwidth_auto->val, dev->bandwidth->cur.val,
-                       dev->bandwidth->val, dev->f_adc);
-
-       if (dev->bandwidth_auto->val == true)
-               bandwidth = dev->f_adc;
-       else
-               bandwidth = dev->bandwidth->val;
-
-       for (i = 0; i < ARRAY_SIZE(bandwidth_lut); i++) {
-               if (bandwidth <= bandwidth_lut[i].freq) {
-                       bandwidth = bandwidth_lut[i].freq;
-                       break;
-               }
-       }
-
-       dev->bandwidth->val = bandwidth;
-       dev->bandwidth->cur.val = bandwidth;
-
-       dev_dbg(dev->dev, "bandwidth selected=%d\n", bandwidth);
-
-       u16tmp = 0;
-       u16tmp |= ((bandwidth >> 0) & 0xff) << 0;
-       u16tmp |= ((bandwidth >> 8) & 0xff) << 8;
-       u16tmp2 = 0;
-       u16tmp2 |= ((bandwidth >> 16) & 0xff) << 0;
-       u16tmp2 |= ((bandwidth >> 24) & 0xff) << 8;
-
-       ret = hackrf_ctrl_msg(dev, CMD_BASEBAND_FILTER_BANDWIDTH_SET,
-                               u16tmp, u16tmp2, NULL, 0);
-       if (ret)
-               dev_dbg(dev->dev, "failed=%d\n", ret);
-
-       return ret;
-}
-
-static int hackrf_set_lna_gain(struct hackrf_dev *dev)
-{
-       int ret;
-       u8 u8tmp;
-
-       dev_dbg(dev->dev, "lna val=%d->%d\n",
-                       dev->lna_gain->cur.val, dev->lna_gain->val);
-
-       ret = hackrf_ctrl_msg(dev, CMD_SET_LNA_GAIN, 0, dev->lna_gain->val,
-                       &u8tmp, 1);
-       if (ret)
-               dev_dbg(dev->dev, "failed=%d\n", ret);
-
-       return ret;
-}
-
-static int hackrf_set_if_gain(struct hackrf_dev *dev)
+static int hackrf_s_ctrl_rx(struct v4l2_ctrl *ctrl)
 {
+       struct hackrf_dev *dev = container_of(ctrl->handler,
+                       struct hackrf_dev, rx_ctrl_handler);
+       struct usb_interface *intf = dev->intf;
        int ret;
-       u8 u8tmp;
 
-       dev_dbg(dev->dev, "val=%d->%d\n",
-                       dev->if_gain->cur.val, dev->if_gain->val);
+       switch (ctrl->id) {
+       case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
+       case V4L2_CID_RF_TUNER_BANDWIDTH:
+               set_bit(RX_BANDWIDTH, &dev->flags);
+               break;
+       case  V4L2_CID_RF_TUNER_RF_GAIN:
+               set_bit(RX_RF_GAIN, &dev->flags);
+               break;
+       case  V4L2_CID_RF_TUNER_LNA_GAIN:
+               set_bit(RX_LNA_GAIN, &dev->flags);
+               break;
+       case  V4L2_CID_RF_TUNER_IF_GAIN:
+               set_bit(RX_IF_GAIN, &dev->flags);
+               break;
+       default:
+               dev_dbg(&intf->dev, "unknown ctrl: id=%d name=%s\n",
+                       ctrl->id, ctrl->name);
+               ret = -EINVAL;
+               goto err;
+       }
 
-       ret = hackrf_ctrl_msg(dev, CMD_SET_VGA_GAIN, 0, dev->if_gain->val,
-                       &u8tmp, 1);
+       ret = hackrf_set_params(dev);
        if (ret)
-               dev_dbg(dev->dev, "failed=%d\n", ret);
+               goto err;
 
+       return 0;
+err:
+       dev_dbg(&intf->dev, "failed=%d\n", ret);
        return ret;
 }
 
-static int hackrf_s_ctrl(struct v4l2_ctrl *ctrl)
+static int hackrf_s_ctrl_tx(struct v4l2_ctrl *ctrl)
 {
        struct hackrf_dev *dev = container_of(ctrl->handler,
-                       struct hackrf_dev, hdl);
+                       struct hackrf_dev, tx_ctrl_handler);
+       struct usb_interface *intf = dev->intf;
        int ret;
 
        switch (ctrl->id) {
        case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
        case V4L2_CID_RF_TUNER_BANDWIDTH:
-               ret = hackrf_set_bandwidth(dev);
+               set_bit(TX_BANDWIDTH, &dev->flags);
                break;
        case  V4L2_CID_RF_TUNER_LNA_GAIN:
-               ret = hackrf_set_lna_gain(dev);
+               set_bit(TX_LNA_GAIN, &dev->flags);
                break;
-       case  V4L2_CID_RF_TUNER_IF_GAIN:
-               ret = hackrf_set_if_gain(dev);
+       case  V4L2_CID_RF_TUNER_RF_GAIN:
+               set_bit(TX_RF_GAIN, &dev->flags);
                break;
        default:
-               dev_dbg(dev->dev, "unknown ctrl: id=%d name=%s\n",
-                               ctrl->id, ctrl->name);
+               dev_dbg(&intf->dev, "unknown ctrl: id=%d name=%s\n",
+                       ctrl->id, ctrl->name);
                ret = -EINVAL;
+               goto err;
        }
 
+       ret = hackrf_set_params(dev);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       dev_dbg(&intf->dev, "failed=%d\n", ret);
        return ret;
 }
 
-static const struct v4l2_ctrl_ops hackrf_ctrl_ops = {
-       .s_ctrl = hackrf_s_ctrl,
+static const struct v4l2_ctrl_ops hackrf_ctrl_ops_rx = {
+       .s_ctrl = hackrf_s_ctrl_rx,
+};
+
+static const struct v4l2_ctrl_ops hackrf_ctrl_ops_tx = {
+       .s_ctrl = hackrf_s_ctrl_tx,
 };
 
 static int hackrf_probe(struct usb_interface *intf,
@@ -1023,19 +1363,29 @@ static int hackrf_probe(struct usb_interface *intf,
        u8 u8tmp, buf[BUF_SIZE];
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL)
-               return -ENOMEM;
+       if (!dev) {
+               ret = -ENOMEM;
+               goto err;
+       }
 
        mutex_init(&dev->v4l2_lock);
        mutex_init(&dev->vb_queue_lock);
-       spin_lock_init(&dev->queued_bufs_lock);
-       INIT_LIST_HEAD(&dev->queued_bufs);
+       spin_lock_init(&dev->buffer_list_lock);
+       INIT_LIST_HEAD(&dev->rx_buffer_list);
+       INIT_LIST_HEAD(&dev->tx_buffer_list);
+       dev->intf = intf;
        dev->dev = &intf->dev;
        dev->udev = interface_to_usbdev(intf);
-       dev->f_adc = bands_adc[0].rangelow;
-       dev->f_rf = bands_rf[0].rangelow;
        dev->pixelformat = formats[0].pixelformat;
        dev->buffersize = formats[0].buffersize;
+       dev->f_adc = bands_adc_dac[0].rangelow;
+       dev->f_dac = bands_adc_dac[0].rangelow;
+       dev->f_rx = bands_rx_tx[0].rangelow;
+       dev->f_tx = bands_rx_tx[0].rangelow;
+       set_bit(RX_ADC_FREQUENCY, &dev->flags);
+       set_bit(TX_DAC_FREQUENCY, &dev->flags);
+       set_bit(RX_RF_FREQUENCY, &dev->flags);
+       set_bit(TX_RF_FREQUENCY, &dev->flags);
 
        /* Detect device */
        ret = hackrf_ctrl_msg(dev, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1);
@@ -1044,83 +1394,143 @@ static int hackrf_probe(struct usb_interface *intf,
                                buf, BUF_SIZE);
        if (ret) {
                dev_err(dev->dev, "Could not detect board\n");
-               goto err_free_mem;
+               goto err_kfree;
        }
 
        buf[BUF_SIZE - 1] = '\0';
-
        dev_info(dev->dev, "Board ID: %02x\n", u8tmp);
        dev_info(dev->dev, "Firmware version: %s\n", buf);
 
-       /* Init videobuf2 queue structure */
-       dev->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
-       dev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-       dev->vb_queue.drv_priv = dev;
-       dev->vb_queue.buf_struct_size = sizeof(struct hackrf_frame_buf);
-       dev->vb_queue.ops = &hackrf_vb2_ops;
-       dev->vb_queue.mem_ops = &vb2_vmalloc_memops;
-       dev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-       ret = vb2_queue_init(&dev->vb_queue);
+       /* Init vb2 queue structure for receiver */
+       dev->rx_vb2_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
+       dev->rx_vb2_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF |
+                                    VB2_READ;
+       dev->rx_vb2_queue.ops = &hackrf_vb2_ops;
+       dev->rx_vb2_queue.mem_ops = &vb2_vmalloc_memops;
+       dev->rx_vb2_queue.drv_priv = dev;
+       dev->rx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer);
+       dev->rx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       ret = vb2_queue_init(&dev->rx_vb2_queue);
        if (ret) {
-               dev_err(dev->dev, "Could not initialize vb2 queue\n");
-               goto err_free_mem;
+               dev_err(dev->dev, "Could not initialize rx vb2 queue\n");
+               goto err_kfree;
        }
 
-       /* Init video_device structure */
-       dev->vdev = hackrf_template;
-       dev->vdev.queue = &dev->vb_queue;
-       dev->vdev.queue->lock = &dev->vb_queue_lock;
-       video_set_drvdata(&dev->vdev, dev);
+       /* Init vb2 queue structure for transmitter */
+       dev->tx_vb2_queue.type = V4L2_BUF_TYPE_SDR_OUTPUT;
+       dev->tx_vb2_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF |
+                                    VB2_WRITE;
+       dev->tx_vb2_queue.ops = &hackrf_vb2_ops;
+       dev->tx_vb2_queue.mem_ops = &vb2_vmalloc_memops;
+       dev->tx_vb2_queue.drv_priv = dev;
+       dev->tx_vb2_queue.buf_struct_size = sizeof(struct hackrf_buffer);
+       dev->tx_vb2_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       ret = vb2_queue_init(&dev->tx_vb2_queue);
+       if (ret) {
+               dev_err(dev->dev, "Could not initialize tx vb2 queue\n");
+               goto err_kfree;
+       }
+
+       /* Register controls for receiver */
+       v4l2_ctrl_handler_init(&dev->rx_ctrl_handler, 5);
+       dev->rx_bandwidth_auto = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+               &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+               0, 1, 0, 1);
+       dev->rx_bandwidth = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+               &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_BANDWIDTH,
+               1750000, 28000000, 50000, 1750000);
+       v4l2_ctrl_auto_cluster(2, &dev->rx_bandwidth_auto, 0, false);
+       dev->rx_rf_gain = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+               &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_RF_GAIN, 0, 12, 12, 0);
+       dev->rx_lna_gain = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+               &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_LNA_GAIN, 0, 40, 8, 0);
+       dev->rx_if_gain = v4l2_ctrl_new_std(&dev->rx_ctrl_handler,
+               &hackrf_ctrl_ops_rx, V4L2_CID_RF_TUNER_IF_GAIN, 0, 62, 2, 0);
+       if (dev->rx_ctrl_handler.error) {
+               ret = dev->rx_ctrl_handler.error;
+               dev_err(dev->dev, "Could not initialize controls\n");
+               goto err_v4l2_ctrl_handler_free_rx;
+       }
+       v4l2_ctrl_handler_setup(&dev->rx_ctrl_handler);
+
+       /* Register controls for transmitter */
+       v4l2_ctrl_handler_init(&dev->tx_ctrl_handler, 4);
+       dev->tx_bandwidth_auto = v4l2_ctrl_new_std(&dev->tx_ctrl_handler,
+               &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+               0, 1, 0, 1);
+       dev->tx_bandwidth = v4l2_ctrl_new_std(&dev->tx_ctrl_handler,
+               &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_BANDWIDTH,
+               1750000, 28000000, 50000, 1750000);
+       v4l2_ctrl_auto_cluster(2, &dev->tx_bandwidth_auto, 0, false);
+       dev->tx_lna_gain = v4l2_ctrl_new_std(&dev->tx_ctrl_handler,
+               &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_LNA_GAIN, 0, 47, 1, 0);
+       dev->tx_rf_gain = v4l2_ctrl_new_std(&dev->tx_ctrl_handler,
+               &hackrf_ctrl_ops_tx, V4L2_CID_RF_TUNER_RF_GAIN, 0, 15, 15, 0);
+       if (dev->tx_ctrl_handler.error) {
+               ret = dev->tx_ctrl_handler.error;
+               dev_err(dev->dev, "Could not initialize controls\n");
+               goto err_v4l2_ctrl_handler_free_tx;
+       }
+       v4l2_ctrl_handler_setup(&dev->tx_ctrl_handler);
 
        /* Register the v4l2_device structure */
        dev->v4l2_dev.release = hackrf_video_release;
        ret = v4l2_device_register(&intf->dev, &dev->v4l2_dev);
        if (ret) {
                dev_err(dev->dev, "Failed to register v4l2-device (%d)\n", ret);
-               goto err_free_mem;
+               goto err_v4l2_ctrl_handler_free_tx;
        }
 
-       /* Register controls */
-       v4l2_ctrl_handler_init(&dev->hdl, 4);
-       dev->bandwidth_auto = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops,
-                       V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
-       dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops,
-                       V4L2_CID_RF_TUNER_BANDWIDTH,
-                       1750000, 28000000, 50000, 1750000);
-       v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
-       dev->lna_gain = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops,
-                       V4L2_CID_RF_TUNER_LNA_GAIN, 0, 40, 8, 0);
-       dev->if_gain = v4l2_ctrl_new_std(&dev->hdl, &hackrf_ctrl_ops,
-                       V4L2_CID_RF_TUNER_IF_GAIN, 0, 62, 2, 0);
-       if (dev->hdl.error) {
-               ret = dev->hdl.error;
-               dev_err(dev->dev, "Could not initialize controls\n");
-               goto err_free_controls;
+       /* Init video_device structure for receiver */
+       dev->rx_vdev = hackrf_template;
+       dev->rx_vdev.queue = &dev->rx_vb2_queue;
+       dev->rx_vdev.queue->lock = &dev->vb_queue_lock;
+       dev->rx_vdev.v4l2_dev = &dev->v4l2_dev;
+       dev->rx_vdev.ctrl_handler = &dev->rx_ctrl_handler;
+       dev->rx_vdev.lock = &dev->v4l2_lock;
+       dev->rx_vdev.vfl_dir = VFL_DIR_RX;
+       video_set_drvdata(&dev->rx_vdev, dev);
+       ret = video_register_device(&dev->rx_vdev, VFL_TYPE_SDR, -1);
+       if (ret) {
+               dev_err(dev->dev,
+                       "Failed to register as video device (%d)\n", ret);
+               goto err_v4l2_device_unregister;
        }
-
-       v4l2_ctrl_handler_setup(&dev->hdl);
-
-       dev->v4l2_dev.ctrl_handler = &dev->hdl;
-       dev->vdev.v4l2_dev = &dev->v4l2_dev;
-       dev->vdev.lock = &dev->v4l2_lock;
-
-       ret = video_register_device(&dev->vdev, VFL_TYPE_SDR, -1);
+       dev_info(dev->dev, "Registered as %s\n",
+                video_device_node_name(&dev->rx_vdev));
+
+       /* Init video_device structure for transmitter */
+       dev->tx_vdev = hackrf_template;
+       dev->tx_vdev.queue = &dev->tx_vb2_queue;
+       dev->tx_vdev.queue->lock = &dev->vb_queue_lock;
+       dev->tx_vdev.v4l2_dev = &dev->v4l2_dev;
+       dev->tx_vdev.ctrl_handler = &dev->tx_ctrl_handler;
+       dev->tx_vdev.lock = &dev->v4l2_lock;
+       dev->tx_vdev.vfl_dir = VFL_DIR_TX;
+       video_set_drvdata(&dev->tx_vdev, dev);
+       ret = video_register_device(&dev->tx_vdev, VFL_TYPE_SDR, -1);
        if (ret) {
-               dev_err(dev->dev, "Failed to register as video device (%d)\n",
-                               ret);
-               goto err_unregister_v4l2_dev;
+               dev_err(dev->dev,
+                       "Failed to register as video device (%d)\n", ret);
+               goto err_video_unregister_device_rx;
        }
        dev_info(dev->dev, "Registered as %s\n",
-                       video_device_node_name(&dev->vdev));
+                video_device_node_name(&dev->tx_vdev));
+
        dev_notice(dev->dev, "SDR API is still slightly experimental and functionality changes may follow\n");
        return 0;
-
-err_free_controls:
-       v4l2_ctrl_handler_free(&dev->hdl);
-err_unregister_v4l2_dev:
+err_video_unregister_device_rx:
+       video_unregister_device(&dev->rx_vdev);
+err_v4l2_device_unregister:
        v4l2_device_unregister(&dev->v4l2_dev);
-err_free_mem:
+err_v4l2_ctrl_handler_free_tx:
+       v4l2_ctrl_handler_free(&dev->tx_ctrl_handler);
+err_v4l2_ctrl_handler_free_rx:
+       v4l2_ctrl_handler_free(&dev->rx_ctrl_handler);
+err_kfree:
        kfree(dev);
+err:
+       dev_dbg(dev->dev, "failed=%d\n", ret);
        return ret;
 }
 
index 26a76e0fe3d8acf5c4ab7778aa83c7a842f492f1..e06a21a4fbd9a30bdb3c86f4cfb41f9de3833ddd 100644 (file)
@@ -616,7 +616,7 @@ static int msi2500_querycap(struct file *file, void *fh,
 
 /* Videobuf2 operations */
 static int msi2500_queue_setup(struct vb2_queue *vq,
-                              const struct v4l2_format *fmt,
+                              const void *parg,
                               unsigned int *nbuffers,
                               unsigned int *nplanes, unsigned int sizes[],
                               void *alloc_ctxs[])
index 3f5395a7fafef30bdfdbaf42104f436a24aba446..b79c36fd8cd24c66d441c5b807cb65a65b6673f6 100644 (file)
@@ -571,7 +571,7 @@ static void pwc_video_release(struct v4l2_device *v)
 /***************************************************************************/
 /* Videobuf2 operations */
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
index 32b511510f0d521a2db368d678de2de6277f508d..e7acb12ad21d1e5ae4fe69c4d6eb2cee7b8ddc73 100644 (file)
@@ -660,7 +660,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
    Videobuf operations
    ------------------------------------------------------------------*/
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                       unsigned int *nbuffers, unsigned int *nplanes,
                       unsigned int sizes[], void *alloc_ctxs[])
 {
index 10e35e6479add6fdc755c311f337ccb72a05a1bf..0bd34f1e7fa95f0c7aad7b6e2a1b466cb2ddf27c 100644 (file)
@@ -664,7 +664,7 @@ static const struct v4l2_ioctl_ops stk1160_ioctl_ops = {
 /*
  * Videobuf2 operations
  */
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
                                unsigned int *nbuffers, unsigned int *nplanes,
                                unsigned int sizes[], void *alloc_ctxs[])
 {
index 7c3a7c55d9693b920b565f39f3b380b222ce45d7..a5de46f04247f82178d60366d8148a4140f7780e 100644 (file)
@@ -375,8 +375,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
        struct ttusb_dec *dec = priv;
 
        dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
-                                      &dec->audio_filter->feed->feed.ts,
-                                      DMX_OK);
+                                      &dec->audio_filter->feed->feed.ts);
 
        return 0;
 }
@@ -386,8 +385,7 @@ static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
        struct ttusb_dec *dec = priv;
 
        dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
-                                      &dec->video_filter->feed->feed.ts,
-                                      DMX_OK);
+                                      &dec->video_filter->feed->feed.ts);
 
        return 0;
 }
@@ -439,7 +437,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
 
                if (output_pva) {
                        dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
-                               &dec->video_filter->feed->feed.ts, DMX_OK);
+                               &dec->video_filter->feed->feed.ts);
                        return;
                }
 
@@ -500,7 +498,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
        case 0x02:              /* MainAudioStream */
                if (output_pva) {
                        dec->audio_filter->feed->cb.ts(pva, length, NULL, 0,
-                               &dec->audio_filter->feed->feed.ts, DMX_OK);
+                               &dec->audio_filter->feed->feed.ts);
                        return;
                }
 
@@ -538,7 +536,7 @@ static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet,
 
        if (filter)
                filter->feed->cb.sec(&packet[2], length - 2, NULL, 0,
-                                    &filter->filter, DMX_OK);
+                                    &filter->filter);
 }
 
 static void ttusb_dec_process_packet(struct ttusb_dec *dec)
index ce5d5028e4c2623281597eb17b69296deee122b2..e645c9df2d9401919e82d875f73c37389b09f73b 100644 (file)
@@ -599,9 +599,10 @@ static struct v4l2_file_operations usbtv_fops = {
 };
 
 static int usbtv_queue_setup(struct vb2_queue *vq,
-       const struct v4l2_format *fmt, unsigned int *nbuffers,
+       const void *parg, unsigned int *nbuffers,
        unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct usbtv *usbtv = vb2_get_drv_priv(vq);
        unsigned size = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
 
index b49bcab0c38c466a2aefb704bcfcf6c5412b5e31..cfb868a48b5f02ad4e76c11072b4ce0b33a2890e 100644 (file)
@@ -69,10 +69,11 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue,
  * videobuf2 queue operations
  */
 
-static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
+       const struct v4l2_format *fmt = parg;
        struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
        struct uvc_streaming *stream = uvc_queue_to_stream(queue);
 
index ad0740130aae25b2dea356c81dcfe9103e87d7ed..1dc8bba2b198611d770b06ddcc257901c48372d2 100644 (file)
@@ -14,7 +14,7 @@ ifeq ($(CONFIG_OF),y)
   videodev-objs += v4l2-of.o
 endif
 ifeq ($(CONFIG_TRACEPOINTS),y)
-  videodev-objs += v4l2-trace.o
+  videodev-objs += vb2-trace.o v4l2-trace.o
 endif
 
 obj-$(CONFIG_VIDEO_V4L2) += videodev.o
index d032e9a2b212735a25fac4297b5f51e956bf0b01..327e83ac2469ecad9d7e86aa9ca3c5c0c72cf572 100644 (file)
@@ -214,6 +214,7 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
                return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
        case V4L2_BUF_TYPE_SDR_CAPTURE:
+       case V4L2_BUF_TYPE_SDR_OUTPUT:
                return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
        default:
                pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
@@ -260,6 +261,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
                return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
        case V4L2_BUF_TYPE_SDR_CAPTURE:
+       case V4L2_BUF_TYPE_SDR_OUTPUT:
                return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
        default:
                pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
index 44521a9da66d265152cde2fa47d08d6edc654dbe..4a1d9fdd14bb1595ff86eb7b72d56b9d507b6128 100644 (file)
@@ -888,6 +888,7 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_TUNE_DEEMPHASIS:          return "De-Emphasis";
        case V4L2_CID_RDS_RECEPTION:            return "RDS Reception";
        case V4L2_CID_RF_TUNER_CLASS:           return "RF Tuner Controls";
+       case V4L2_CID_RF_TUNER_RF_GAIN:         return "RF Gain";
        case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:   return "LNA Gain, Auto";
        case V4L2_CID_RF_TUNER_LNA_GAIN:        return "LNA Gain";
        case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO: return "Mixer Gain, Auto";
@@ -1161,6 +1162,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_PILOT_TONE_FREQUENCY:
        case V4L2_CID_TUNE_POWER_LEVEL:
        case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
+       case V4L2_CID_RF_TUNER_RF_GAIN:
        case V4L2_CID_RF_TUNER_LNA_GAIN:
        case V4L2_CID_RF_TUNER_MIXER_GAIN:
        case V4L2_CID_RF_TUNER_IF_GAIN:
@@ -3043,7 +3045,7 @@ static void update_from_auto_cluster(struct v4l2_ctrl *master)
 {
        int i;
 
-       for (i = 0; i < master->ncontrols; i++)
+       for (i = 1; i < master->ncontrols; i++)
                cur_to_new(master->cluster[i]);
        if (!call_op(master, g_volatile_ctrl))
                for (i = 1; i < master->ncontrols; i++)
index 71a1b93b079071b560370bca7cbcf9cdd1d3c820..6b1eaeddbdb3c9d973866ecb28aab9f24f379e41 100644 (file)
@@ -637,8 +637,8 @@ static void determine_valid_ioctls(struct video_device *vdev)
                               ops->vidioc_try_fmt_sliced_vbi_out)))
                        set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
                SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);
-       } else if (is_sdr) {
-               /* SDR specific ioctls */
+       } else if (is_sdr && is_rx) {
+               /* SDR receiver specific ioctls */
                if (ops->vidioc_enum_fmt_sdr_cap)
                        set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
                if (ops->vidioc_g_fmt_sdr_cap)
@@ -647,6 +647,16 @@ static void determine_valid_ioctls(struct video_device *vdev)
                        set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
                if (ops->vidioc_try_fmt_sdr_cap)
                        set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
+       } else if (is_sdr && is_tx) {
+               /* SDR transmitter specific ioctls */
+               if (ops->vidioc_enum_fmt_sdr_out)
+                       set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
+               if (ops->vidioc_g_fmt_sdr_out)
+                       set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
+               if (ops->vidioc_s_fmt_sdr_out)
+                       set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
+               if (ops->vidioc_try_fmt_sdr_out)
+                       set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
        }
 
        if (is_vid || is_vbi || is_sdr) {
index 5dc69086cf847a7722d69416d5375d5b575c136c..7486af2c8ae49241d3aafd3c30f1a90094a63a0f 100644 (file)
@@ -153,6 +153,7 @@ const char *v4l2_type_names[] = {
        [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",
+       [V4L2_BUF_TYPE_SDR_OUTPUT]         = "sdr-out",
 };
 EXPORT_SYMBOL(v4l2_type_names);
 
@@ -326,6 +327,7 @@ static void v4l_print_format(const void *arg, bool write_only)
                                sliced->service_lines[1][i]);
                break;
        case V4L2_BUF_TYPE_SDR_CAPTURE:
+       case V4L2_BUF_TYPE_SDR_OUTPUT:
                sdr = &p->fmt.sdr;
                pr_cont(", pixelformat=%c%c%c%c\n",
                        (sdr->pixelformat >>  0) & 0xff,
@@ -974,6 +976,10 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
                if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap)
                        return 0;
                break;
+       case V4L2_BUF_TYPE_SDR_OUTPUT:
+               if (is_sdr && is_tx && ops->vidioc_g_fmt_sdr_out)
+                       return 0;
+               break;
        default:
                break;
        }
@@ -1324,6 +1330,11 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
                        break;
                ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
                break;
+       case V4L2_BUF_TYPE_SDR_OUTPUT:
+               if (unlikely(!is_tx || !is_sdr || !ops->vidioc_enum_fmt_sdr_out))
+                       break;
+               ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg);
+               break;
        }
        if (ret == 0)
                v4l_fill_fmtdesc(p);
@@ -1418,6 +1429,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap))
                        break;
                return ops->vidioc_g_fmt_sdr_cap(file, fh, arg);
+       case V4L2_BUF_TYPE_SDR_OUTPUT:
+               if (unlikely(!is_tx || !is_sdr || !ops->vidioc_g_fmt_sdr_out))
+                       break;
+               return ops->vidioc_g_fmt_sdr_out(file, fh, arg);
        }
        return -EINVAL;
 }
@@ -1497,6 +1512,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                        break;
                CLEAR_AFTER_FIELD(p, fmt.sdr);
                return ops->vidioc_s_fmt_sdr_cap(file, fh, arg);
+       case V4L2_BUF_TYPE_SDR_OUTPUT:
+               if (unlikely(!is_tx || !is_sdr || !ops->vidioc_s_fmt_sdr_out))
+                       break;
+               CLEAR_AFTER_FIELD(p, fmt.sdr);
+               return ops->vidioc_s_fmt_sdr_out(file, fh, arg);
        }
        return -EINVAL;
 }
@@ -1576,6 +1596,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                        break;
                CLEAR_AFTER_FIELD(p, fmt.sdr);
                return ops->vidioc_try_fmt_sdr_cap(file, fh, arg);
+       case V4L2_BUF_TYPE_SDR_OUTPUT:
+               if (unlikely(!is_tx || !is_sdr || !ops->vidioc_try_fmt_sdr_out))
+                       break;
+               CLEAR_AFTER_FIELD(p, fmt.sdr);
+               return ops->vidioc_try_fmt_sdr_out(file, fh, arg);
        }
        return -EINVAL;
 }
@@ -1621,15 +1646,31 @@ static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,
 static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
+       struct video_device *vfd = video_devdata(file);
        struct v4l2_modulator *p = arg;
        int err;
 
+       if (vfd->vfl_type == VFL_TYPE_RADIO)
+               p->type = V4L2_TUNER_RADIO;
+
        err = ops->vidioc_g_modulator(file, fh, p);
        if (!err)
                p->capability |= V4L2_TUNER_CAP_FREQ_BANDS;
        return err;
 }
 
+static int v4l_s_modulator(const struct v4l2_ioctl_ops *ops,
+                               struct file *file, void *fh, void *arg)
+{
+       struct video_device *vfd = video_devdata(file);
+       struct v4l2_modulator *p = arg;
+
+       if (vfd->vfl_type == VFL_TYPE_RADIO)
+               p->type = V4L2_TUNER_RADIO;
+
+       return ops->vidioc_s_modulator(file, fh, p);
+}
+
 static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
@@ -1637,7 +1678,7 @@ static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
        struct v4l2_frequency *p = arg;
 
        if (vfd->vfl_type == VFL_TYPE_SDR)
-               p->type = V4L2_TUNER_ADC;
+               p->type = V4L2_TUNER_SDR;
        else
                p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
                                V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
@@ -1652,7 +1693,7 @@ static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
        enum v4l2_tuner_type type;
 
        if (vfd->vfl_type == VFL_TYPE_SDR) {
-               if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
+               if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF)
                        return -EINVAL;
        } else {
                type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
@@ -2277,7 +2318,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
        int err;
 
        if (vfd->vfl_type == VFL_TYPE_SDR) {
-               if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
+               if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF)
                        return -EINVAL;
                type = p->type;
        } else {
@@ -2416,7 +2457,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
        IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0),
        IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO),
        IOCTL_INFO_FNC(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)),
-       IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO),
+       IOCTL_INFO_FNC(VIDIOC_S_MODULATOR, v4l_s_modulator, v4l_print_modulator, INFO_FL_PRIO),
        IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)),
        IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO),
        IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)),
index 4004814fab5e5621a2e228a12beaaf5685359560..7416010542c138cbcdb3cac27ee0c076ea69c65c 100644 (file)
@@ -5,7 +5,7 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/v4l2.h>
 
-EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_done);
-EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_queue);
-EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_dqbuf);
-EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_qbuf);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_done);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_queue);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_dqbuf);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_qbuf);
diff --git a/drivers/media/v4l2-core/vb2-trace.c b/drivers/media/v4l2-core/vb2-trace.c
new file mode 100644 (file)
index 0000000..61e74f5
--- /dev/null
@@ -0,0 +1,9 @@
+#include <media/videobuf2-core.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/vb2.h>
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_done);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_buf_queue);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_dqbuf);
+EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_qbuf);
index 926836d1813a0051e41f0b35ebb7f85598ca86cf..6c02989ee33f853aa8d6d485ccde23c41646f7e9 100644 (file)
@@ -576,7 +576,8 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b)
                }
                if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
                    || q->type == V4L2_BUF_TYPE_VBI_OUTPUT
-                   || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
+                   || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
+                   || q->type == V4L2_BUF_TYPE_SDR_OUTPUT) {
                        buf->size = b->bytesused;
                        buf->field = b->field;
                        buf->ts = b->timestamp;
@@ -1154,6 +1155,7 @@ unsigned int videobuf_poll_stream(struct file *file,
                        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
                        case V4L2_BUF_TYPE_VBI_OUTPUT:
                        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+                       case V4L2_BUF_TYPE_SDR_OUTPUT:
                                rc = POLLOUT | POLLWRNORM;
                                break;
                        default:
index 8c456f7b1995ceca2c320b9b6b09c9fdef8f6ec6..33bdd81065e81cd66de55fd533d8bda86b0c678f 100644 (file)
 #include <linux/freezer.h>
 #include <linux/kthread.h>
 
-#include <media/v4l2-dev.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-common.h>
-#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-core.h>
 
-#include <trace/events/v4l2.h>
+#include <trace/events/vb2.h>
 
-static int debug;
-module_param(debug, int, 0644);
+#include "videobuf2-internal.h"
 
-#define dprintk(level, fmt, arg...)                                          \
-       do {                                                                  \
-               if (debug >= level)                                           \
-                       pr_info("vb2: %s: " fmt, __func__, ## arg); \
-       } while (0)
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-
-/*
- * If advanced debugging is on, then count how often each op is called
- * successfully, which can either be per-buffer or per-queue.
- *
- * This makes it easy to check that the 'init' and 'cleanup'
- * (and variations thereof) stay balanced.
- */
-
-#define log_memop(vb, op)                                              \
-       dprintk(2, "call_memop(%p, %d, %s)%s\n",                        \
-               (vb)->vb2_queue, (vb)->index, #op,                      \
-               (vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
-
-#define call_memop(vb, op, args...)                                    \
-({                                                                     \
-       struct vb2_queue *_q = (vb)->vb2_queue;                         \
-       int err;                                                        \
-                                                                       \
-       log_memop(vb, op);                                              \
-       err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;              \
-       if (!err)                                                       \
-               (vb)->cnt_mem_ ## op++;                                 \
-       err;                                                            \
-})
-
-#define call_ptr_memop(vb, op, args...)                                        \
-({                                                                     \
-       struct vb2_queue *_q = (vb)->vb2_queue;                         \
-       void *ptr;                                                      \
-                                                                       \
-       log_memop(vb, op);                                              \
-       ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;           \
-       if (!IS_ERR_OR_NULL(ptr))                                       \
-               (vb)->cnt_mem_ ## op++;                                 \
-       ptr;                                                            \
-})
-
-#define call_void_memop(vb, op, args...)                               \
-({                                                                     \
-       struct vb2_queue *_q = (vb)->vb2_queue;                         \
-                                                                       \
-       log_memop(vb, op);                                              \
-       if (_q->mem_ops->op)                                            \
-               _q->mem_ops->op(args);                                  \
-       (vb)->cnt_mem_ ## op++;                                         \
-})
-
-#define log_qop(q, op)                                                 \
-       dprintk(2, "call_qop(%p, %s)%s\n", q, #op,                      \
-               (q)->ops->op ? "" : " (nop)")
-
-#define call_qop(q, op, args...)                                       \
-({                                                                     \
-       int err;                                                        \
-                                                                       \
-       log_qop(q, op);                                                 \
-       err = (q)->ops->op ? (q)->ops->op(args) : 0;                    \
-       if (!err)                                                       \
-               (q)->cnt_ ## op++;                                      \
-       err;                                                            \
-})
-
-#define call_void_qop(q, op, args...)                                  \
-({                                                                     \
-       log_qop(q, op);                                                 \
-       if ((q)->ops->op)                                               \
-               (q)->ops->op(args);                                     \
-       (q)->cnt_ ## op++;                                              \
-})
-
-#define log_vb_qop(vb, op, args...)                                    \
-       dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",                       \
-               (vb)->vb2_queue, (vb)->index, #op,                      \
-               (vb)->vb2_queue->ops->op ? "" : " (nop)")
-
-#define call_vb_qop(vb, op, args...)                                   \
-({                                                                     \
-       int err;                                                        \
-                                                                       \
-       log_vb_qop(vb, op);                                             \
-       err = (vb)->vb2_queue->ops->op ?                                \
-               (vb)->vb2_queue->ops->op(args) : 0;                     \
-       if (!err)                                                       \
-               (vb)->cnt_ ## op++;                                     \
-       err;                                                            \
-})
-
-#define call_void_vb_qop(vb, op, args...)                              \
-({                                                                     \
-       log_vb_qop(vb, op);                                             \
-       if ((vb)->vb2_queue->ops->op)                                   \
-               (vb)->vb2_queue->ops->op(args);                         \
-       (vb)->cnt_ ## op++;                                             \
-})
-
-#else
-
-#define call_memop(vb, op, args...)                                    \
-       ((vb)->vb2_queue->mem_ops->op ?                                 \
-               (vb)->vb2_queue->mem_ops->op(args) : 0)
-
-#define call_ptr_memop(vb, op, args...)                                        \
-       ((vb)->vb2_queue->mem_ops->op ?                                 \
-               (vb)->vb2_queue->mem_ops->op(args) : NULL)
-
-#define call_void_memop(vb, op, args...)                               \
-       do {                                                            \
-               if ((vb)->vb2_queue->mem_ops->op)                       \
-                       (vb)->vb2_queue->mem_ops->op(args);             \
-       } while (0)
-
-#define call_qop(q, op, args...)                                       \
-       ((q)->ops->op ? (q)->ops->op(args) : 0)
-
-#define call_void_qop(q, op, args...)                                  \
-       do {                                                            \
-               if ((q)->ops->op)                                       \
-                       (q)->ops->op(args);                             \
-       } while (0)
-
-#define call_vb_qop(vb, op, args...)                                   \
-       ((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
-
-#define call_void_vb_qop(vb, op, args...)                              \
-       do {                                                            \
-               if ((vb)->vb2_queue->ops->op)                           \
-                       (vb)->vb2_queue->ops->op(args);                 \
-       } while (0)
-
-#endif
-
-/* Flags that are set by the vb2 core */
-#define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
-                                V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
-                                V4L2_BUF_FLAG_PREPARED | \
-                                V4L2_BUF_FLAG_TIMESTAMP_MASK)
-/* Output buffer flags that should be passed on to the driver */
-#define V4L2_BUFFER_OUT_FLAGS  (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
-                                V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
+int vb2_debug;
+EXPORT_SYMBOL_GPL(vb2_debug);
+module_param_named(debug, vb2_debug, int, 0644);
 
 static void __vb2_queue_cancel(struct vb2_queue *q);
 static void __enqueue_in_driver(struct vb2_buffer *vb);
@@ -193,7 +44,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
        struct vb2_queue *q = vb->vb2_queue;
        enum dma_data_direction dma_dir =
-               V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+               q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
        void *mem_priv;
        int plane;
 
@@ -347,7 +198,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
  *
  * Returns the number of buffers successfully allocated.
  */
-static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
+static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
                             unsigned int num_buffers, unsigned int num_planes)
 {
        unsigned int buffer;
@@ -370,7 +221,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
                vb->memory = memory;
 
                /* Allocate video buffer memory for the MMAP type */
-               if (memory == V4L2_MEMORY_MMAP) {
+               if (memory == VB2_MEMORY_MMAP) {
                        ret = __vb2_buf_mem_alloc(vb);
                        if (ret) {
                                dprintk(1, "failed allocating memory for "
@@ -397,7 +248,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
        }
 
        __setup_lengths(q, buffer);
-       if (memory == V4L2_MEMORY_MMAP)
+       if (memory == VB2_MEMORY_MMAP)
                __setup_offsets(q, buffer);
 
        dprintk(1, "allocated %d buffers, %d plane(s) each\n",
@@ -421,9 +272,9 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
                        continue;
 
                /* Free MMAP buffers or release USERPTR buffers */
-               if (q->memory == V4L2_MEMORY_MMAP)
+               if (q->memory == VB2_MEMORY_MMAP)
                        __vb2_buf_mem_free(vb);
-               else if (q->memory == V4L2_MEMORY_DMABUF)
+               else if (q->memory == VB2_MEMORY_DMABUF)
                        __vb2_buf_dmabuf_put(vb);
                else
                        __vb2_buf_userptr_put(vb);
@@ -479,7 +330,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
                bool unbalanced = q->cnt_start_streaming != q->cnt_stop_streaming ||
                                  q->cnt_wait_prepare != q->cnt_wait_finish;
 
-               if (unbalanced || debug) {
+               if (unbalanced || vb2_debug) {
                        pr_info("vb2: counters for queue %p:%s\n", q,
                                unbalanced ? " UNBALANCED!" : "");
                        pr_info("vb2:     setup: %u start_streaming: %u stop_streaming: %u\n",
@@ -505,7 +356,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
                                  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
                                  vb->cnt_buf_init != vb->cnt_buf_cleanup;
 
-               if (unbalanced || debug) {
+               if (unbalanced || vb2_debug) {
                        pr_info("vb2:   counters for queue %p, buffer %d:%s\n",
                                q, buffer, unbalanced ? " UNBALANCED!" : "");
                        pr_info("vb2:     buf_init: %u buf_cleanup: %u buf_prepare: %u buf_finish: %u\n",
@@ -547,75 +398,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 }
 
 /**
- * __verify_planes_array() - verify that the planes array passed in struct
- * v4l2_buffer from userspace can be safely used
- */
-static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
-{
-       if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
-               return 0;
-
-       /* Is memory for copying plane information present? */
-       if (NULL == b->m.planes) {
-               dprintk(1, "multi-planar buffer passed but "
-                          "planes array not provided\n");
-               return -EINVAL;
-       }
-
-       if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
-               dprintk(1, "incorrect planes array length, "
-                          "expected %d, got %d\n", vb->num_planes, b->length);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/**
- * __verify_length() - Verify that the bytesused value for each plane fits in
- * the plane length and that the data offset doesn't exceed the bytesused value.
- */
-static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
-{
-       unsigned int length;
-       unsigned int bytesused;
-       unsigned int plane;
-
-       if (!V4L2_TYPE_IS_OUTPUT(b->type))
-               return 0;
-
-       if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
-               for (plane = 0; plane < vb->num_planes; ++plane) {
-                       length = (b->memory == V4L2_MEMORY_USERPTR ||
-                                 b->memory == V4L2_MEMORY_DMABUF)
-                              ? b->m.planes[plane].length
-                               : vb->planes[plane].length;
-                       bytesused = b->m.planes[plane].bytesused
-                                 ? b->m.planes[plane].bytesused : length;
-
-                       if (b->m.planes[plane].bytesused > length)
-                               return -EINVAL;
-
-                       if (b->m.planes[plane].data_offset > 0 &&
-                           b->m.planes[plane].data_offset >= bytesused)
-                               return -EINVAL;
-               }
-       } else {
-               length = (b->memory == V4L2_MEMORY_USERPTR)
-                       ? b->length : vb->planes[0].length;
-
-               if (b->bytesused > length)
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-/**
- * __buffer_in_use() - return true if the buffer is in use and
+ * vb2_buffer_in_use() - return true if the buffer is in use and
  * the queue cannot be freed (by the means of REQBUFS(0)) call
  */
-static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
+bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
 {
        unsigned int plane;
        for (plane = 0; plane < vb->num_planes; ++plane) {
@@ -631,6 +417,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
        }
        return false;
 }
+EXPORT_SYMBOL(vb2_buffer_in_use);
 
 /**
  * __buffers_in_use() - return true if any buffers on the queue are in use and
@@ -640,146 +427,30 @@ static bool __buffers_in_use(struct vb2_queue *q)
 {
        unsigned int buffer;
        for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-               if (__buffer_in_use(q, q->bufs[buffer]))
+               if (vb2_buffer_in_use(q, q->bufs[buffer]))
                        return true;
        }
        return false;
 }
 
 /**
- * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
- * returned to userspace
- */
-static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct vb2_queue *q = vb->vb2_queue;
-       unsigned int plane;
-
-       /* Copy back data such as timestamp, flags, etc. */
-       b->index = vb->index;
-       b->type = vb->type;
-       b->memory = vb->memory;
-       b->bytesused = 0;
-
-       b->flags = vbuf->flags;
-       b->field = vbuf->field;
-       b->timestamp = vbuf->timestamp;
-       b->timecode = vbuf->timecode;
-       b->sequence = vbuf->sequence;
-       b->reserved2 = 0;
-       b->reserved = 0;
-
-       if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
-               /*
-                * Fill in plane-related data if userspace provided an array
-                * for it. The caller has already verified memory and size.
-                */
-               b->length = vb->num_planes;
-               for (plane = 0; plane < vb->num_planes; ++plane) {
-                       struct v4l2_plane *pdst = &b->m.planes[plane];
-                       struct vb2_plane *psrc = &vb->planes[plane];
-
-                       pdst->bytesused = psrc->bytesused;
-                       pdst->length = psrc->length;
-                       if (q->memory == V4L2_MEMORY_MMAP)
-                               pdst->m.mem_offset = psrc->m.offset;
-                       else if (q->memory == V4L2_MEMORY_USERPTR)
-                               pdst->m.userptr = psrc->m.userptr;
-                       else if (q->memory == V4L2_MEMORY_DMABUF)
-                               pdst->m.fd = psrc->m.fd;
-                       pdst->data_offset = psrc->data_offset;
-                       memset(pdst->reserved, 0, sizeof(pdst->reserved));
-               }
-       } else {
-               /*
-                * We use length and offset in v4l2_planes array even for
-                * single-planar buffers, but userspace does not.
-                */
-               b->length = vb->planes[0].length;
-               b->bytesused = vb->planes[0].bytesused;
-               if (q->memory == V4L2_MEMORY_MMAP)
-                       b->m.offset = vb->planes[0].m.offset;
-               else if (q->memory == V4L2_MEMORY_USERPTR)
-                       b->m.userptr = vb->planes[0].m.userptr;
-               else if (q->memory == V4L2_MEMORY_DMABUF)
-                       b->m.fd = vb->planes[0].m.fd;
-       }
-
-       /*
-        * Clear any buffer state related flags.
-        */
-       b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
-       b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
-       if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
-           V4L2_BUF_FLAG_TIMESTAMP_COPY) {
-               /*
-                * For non-COPY timestamps, drop timestamp source bits
-                * and obtain the timestamp source from the queue.
-                */
-               b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-               b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-       }
-
-       switch (vb->state) {
-       case VB2_BUF_STATE_QUEUED:
-       case VB2_BUF_STATE_ACTIVE:
-               b->flags |= V4L2_BUF_FLAG_QUEUED;
-               break;
-       case VB2_BUF_STATE_ERROR:
-               b->flags |= V4L2_BUF_FLAG_ERROR;
-               /* fall through */
-       case VB2_BUF_STATE_DONE:
-               b->flags |= V4L2_BUF_FLAG_DONE;
-               break;
-       case VB2_BUF_STATE_PREPARED:
-               b->flags |= V4L2_BUF_FLAG_PREPARED;
-               break;
-       case VB2_BUF_STATE_PREPARING:
-       case VB2_BUF_STATE_DEQUEUED:
-       case VB2_BUF_STATE_REQUEUEING:
-               /* nothing */
-               break;
-       }
-
-       if (__buffer_in_use(q, vb))
-               b->flags |= V4L2_BUF_FLAG_MAPPED;
-}
-
-/**
- * vb2_querybuf() - query video buffer information
+ * vb2_core_querybuf() - query video buffer information
  * @q:         videobuf queue
- * @b:         buffer struct passed from userspace to vidioc_querybuf handler
- *             in driver
+ * @index:     id number of the buffer
+ * @pb:                buffer struct passed from userspace
  *
  * Should be called from vidioc_querybuf ioctl handler in driver.
- * This function will verify the passed v4l2_buffer structure and fill the
- * relevant information for the userspace.
+ * The passed buffer should have been verified.
+ * This function fills the relevant information for the userspace.
  *
  * The return values from this function are intended to be directly returned
  * from vidioc_querybuf handler in driver.
  */
-int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
+int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
 {
-       struct vb2_buffer *vb;
-       int ret;
-
-       if (b->type != q->type) {
-               dprintk(1, "wrong buffer type\n");
-               return -EINVAL;
-       }
-
-       if (b->index >= q->num_buffers) {
-               dprintk(1, "buffer index out of range\n");
-               return -EINVAL;
-       }
-       vb = q->bufs[b->index];
-       ret = __verify_planes_array(vb, b);
-       if (!ret)
-               __fill_v4l2_buffer(vb, b);
-       return ret;
+       return call_bufop(q, fill_user_buffer, q->bufs[index], pb);
 }
-EXPORT_SYMBOL(vb2_querybuf);
+EXPORT_SYMBOL_GPL(vb2_core_querybuf);
 
 /**
  * __verify_userptr_ops() - verify that all memory operations required for
@@ -822,14 +493,14 @@ static int __verify_dmabuf_ops(struct vb2_queue *q)
 }
 
 /**
- * __verify_memory_type() - Check whether the memory type and buffer type
+ * vb2_verify_memory_type() - Check whether the memory type and buffer type
  * passed to a buffer operation are compatible with the queue.
  */
-static int __verify_memory_type(struct vb2_queue *q,
-               enum v4l2_memory memory, enum v4l2_buf_type type)
+int vb2_verify_memory_type(struct vb2_queue *q,
+               enum vb2_memory memory, unsigned int type)
 {
-       if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
-           memory != V4L2_MEMORY_DMABUF) {
+       if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
+           memory != VB2_MEMORY_DMABUF) {
                dprintk(1, "unsupported memory type\n");
                return -EINVAL;
        }
@@ -843,17 +514,17 @@ static int __verify_memory_type(struct vb2_queue *q,
         * Make sure all the required memory ops for given memory type
         * are available.
         */
-       if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
+       if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
                dprintk(1, "MMAP for current setup unsupported\n");
                return -EINVAL;
        }
 
-       if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
+       if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
                dprintk(1, "USERPTR for current setup unsupported\n");
                return -EINVAL;
        }
 
-       if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
+       if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
                dprintk(1, "DMABUF for current setup unsupported\n");
                return -EINVAL;
        }
@@ -869,11 +540,13 @@ static int __verify_memory_type(struct vb2_queue *q,
        }
        return 0;
 }
+EXPORT_SYMBOL(vb2_verify_memory_type);
 
 /**
- * __reqbufs() - Initiate streaming
+ * vb2_core_reqbufs() - Initiate streaming
  * @q:         videobuf2 queue
- * @req:       struct passed from userspace to vidioc_reqbufs handler in driver
+ * @memory: memory type
+ * @count: requested buffer count
  *
  * Should be called from vidioc_reqbufs ioctl handler of a driver.
  * This function:
@@ -893,7 +566,8 @@ static int __verify_memory_type(struct vb2_queue *q,
  * The return values from this function are intended to be directly returned
  * from vidioc_reqbufs handler in driver.
  */
-static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
+int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
+               unsigned int *count)
 {
        unsigned int num_buffers, allocated_buffers, num_planes = 0;
        int ret;
@@ -903,13 +577,13 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
                return -EBUSY;
        }
 
-       if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
+       if (*count == 0 || q->num_buffers != 0 || q->memory != memory) {
                /*
                 * We already have buffers allocated, so first check if they
                 * are not in use and can be freed.
                 */
                mutex_lock(&q->mmap_lock);
-               if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) {
+               if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
                        mutex_unlock(&q->mmap_lock);
                        dprintk(1, "memory in use, cannot free\n");
                        return -EBUSY;
@@ -930,18 +604,18 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
                 * In case of REQBUFS(0) return immediately without calling
                 * driver's queue_setup() callback and allocating resources.
                 */
-               if (req->count == 0)
+               if (*count == 0)
                        return 0;
        }
 
        /*
         * Make sure the requested values and current defaults are sane.
         */
-       num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
+       num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME);
        num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed);
        memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
        memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
-       q->memory = req->memory;
+       q->memory = memory;
 
        /*
         * Ask the driver how many buffers and planes per buffer it requires.
@@ -953,7 +627,8 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
                return ret;
 
        /* Finally, allocate buffers and video memory */
-       allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
+       allocated_buffers =
+               __vb2_queue_alloc(q, memory, num_buffers, num_planes);
        if (allocated_buffers == 0) {
                dprintk(1, "memory allocation failed\n");
                return -ENOMEM;
@@ -1002,31 +677,19 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
         * Return the number of successfully allocated buffers
         * to the userspace.
         */
-       req->count = allocated_buffers;
-       q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
+       *count = allocated_buffers;
+       q->waiting_for_buffers = !q->is_output;
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
 
 /**
- * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and
- * type values.
- * @q:         videobuf2 queue
- * @req:       struct passed from userspace to vidioc_reqbufs handler in driver
- */
-int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
-{
-       int ret = __verify_memory_type(q, req->memory, req->type);
-
-       return ret ? ret : __reqbufs(q, req);
-}
-EXPORT_SYMBOL_GPL(vb2_reqbufs);
-
-/**
- * __create_bufs() - Allocate buffers and any required auxiliary structs
+ * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs
  * @q:         videobuf2 queue
- * @create:    creation parameters, passed from userspace to vidioc_create_bufs
- *             handler in driver
+ * @memory: memory type
+ * @count: requested buffer count
+ * @parg: parameter passed to device driver
  *
  * Should be called from vidioc_create_bufs ioctl handler of a driver.
  * This function:
@@ -1037,12 +700,13 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs);
  * The return values from this function are intended to be directly returned
  * from vidioc_create_bufs handler in driver.
  */
-static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
+int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
+               unsigned int *count, const void *parg)
 {
        unsigned int num_planes = 0, num_buffers, allocated_buffers;
        int ret;
 
-       if (q->num_buffers == VIDEO_MAX_FRAME) {
+       if (q->num_buffers == VB2_MAX_FRAME) {
                dprintk(1, "maximum number of buffers already allocated\n");
                return -ENOBUFS;
        }
@@ -1050,23 +714,23 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
        if (!q->num_buffers) {
                memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
                memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
-               q->memory = create->memory;
-               q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
+               q->memory = memory;
+               q->waiting_for_buffers = !q->is_output;
        }
 
-       num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
+       num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
 
        /*
         * Ask the driver, whether the requested number of buffers, planes per
         * buffer and their sizes are acceptable
         */
-       ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+       ret = call_qop(q, queue_setup, q, parg, &num_buffers,
                       &num_planes, q->plane_sizes, q->alloc_ctx);
        if (ret)
                return ret;
 
        /* Finally, allocate buffers and video memory */
-       allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers,
+       allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
                                num_planes);
        if (allocated_buffers == 0) {
                dprintk(1, "memory allocation failed\n");
@@ -1083,7 +747,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
                 * q->num_buffers contains the total number of buffers, that the
                 * queue driver has set up
                 */
-               ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+               ret = call_qop(q, queue_setup, q, parg, &num_buffers,
                               &num_planes, q->plane_sizes, q->alloc_ctx);
 
                if (!ret && allocated_buffers < num_buffers)
@@ -1113,28 +777,11 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
         * Return the number of successfully allocated buffers
         * to the userspace.
         */
-       create->count = allocated_buffers;
+       *count = allocated_buffers;
 
        return 0;
 }
-
-/**
- * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the
- * memory and type values.
- * @q:         videobuf2 queue
- * @create:    creation parameters, passed from userspace to vidioc_create_bufs
- *             handler in driver
- */
-int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
-{
-       int ret = __verify_memory_type(q, create->memory, create->format.type);
-
-       create->index = q->num_buffers;
-       if (create->count == 0)
-               return ret != -EBUSY ? ret : 0;
-       return ret ? ret : __create_bufs(q, create);
-}
-EXPORT_SYMBOL_GPL(vb2_create_bufs);
+EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
 
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
@@ -1276,177 +923,35 @@ void vb2_discard_done(struct vb2_queue *q)
 }
 EXPORT_SYMBOL_GPL(vb2_discard_done);
 
-static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
-{
-       static bool check_once;
-
-       if (check_once)
-               return;
-
-       check_once = true;
-       WARN_ON(1);
-
-       pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n");
-       if (vb->vb2_queue->allow_zero_bytesused)
-               pr_warn("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n");
-       else
-               pr_warn("use the actual size instead.\n");
-}
-
-/**
- * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
- * v4l2_buffer by the userspace. The caller has already verified that struct
- * v4l2_buffer has a valid number of planes.
- */
-static void __fill_vb2_buffer(struct vb2_buffer *vb,
-               const struct v4l2_buffer *b, struct vb2_plane *planes)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       unsigned int plane;
-
-       if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
-               if (b->memory == V4L2_MEMORY_USERPTR) {
-                       for (plane = 0; plane < vb->num_planes; ++plane) {
-                               planes[plane].m.userptr =
-                                       b->m.planes[plane].m.userptr;
-                               planes[plane].length =
-                                       b->m.planes[plane].length;
-                       }
-               }
-               if (b->memory == V4L2_MEMORY_DMABUF) {
-                       for (plane = 0; plane < vb->num_planes; ++plane) {
-                               planes[plane].m.fd =
-                                       b->m.planes[plane].m.fd;
-                               planes[plane].length =
-                                       b->m.planes[plane].length;
-                       }
-               }
-
-               /* Fill in driver-provided information for OUTPUT types */
-               if (V4L2_TYPE_IS_OUTPUT(b->type)) {
-                       /*
-                        * Will have to go up to b->length when API starts
-                        * accepting variable number of planes.
-                        *
-                        * If bytesused == 0 for the output buffer, then fall
-                        * back to the full buffer size. In that case
-                        * userspace clearly never bothered to set it and
-                        * it's a safe assumption that they really meant to
-                        * use the full plane sizes.
-                        *
-                        * Some drivers, e.g. old codec drivers, use bytesused == 0
-                        * as a way to indicate that streaming is finished.
-                        * In that case, the driver should use the
-                        * allow_zero_bytesused flag to keep old userspace
-                        * applications working.
-                        */
-                       for (plane = 0; plane < vb->num_planes; ++plane) {
-                               struct vb2_plane *pdst = &planes[plane];
-                               struct v4l2_plane *psrc = &b->m.planes[plane];
-
-                               if (psrc->bytesused == 0)
-                                       vb2_warn_zero_bytesused(vb);
-
-                               if (vb->vb2_queue->allow_zero_bytesused)
-                                       pdst->bytesused = psrc->bytesused;
-                               else
-                                       pdst->bytesused = psrc->bytesused ?
-                                               psrc->bytesused : pdst->length;
-                               pdst->data_offset = psrc->data_offset;
-                       }
-               }
-       } else {
-               /*
-                * Single-planar buffers do not use planes array,
-                * so fill in relevant v4l2_buffer struct fields instead.
-                * In videobuf we use our internal V4l2_planes struct for
-                * single-planar buffers as well, for simplicity.
-                *
-                * If bytesused == 0 for the output buffer, then fall back
-                * to the full buffer size as that's a sensible default.
-                *
-                * Some drivers, e.g. old codec drivers, use bytesused == 0 as
-                * a way to indicate that streaming is finished. In that case,
-                * the driver should use the allow_zero_bytesused flag to keep
-                * old userspace applications working.
-                */
-               if (b->memory == V4L2_MEMORY_USERPTR) {
-                       planes[0].m.userptr = b->m.userptr;
-                       planes[0].length = b->length;
-               }
-
-               if (b->memory == V4L2_MEMORY_DMABUF) {
-                       planes[0].m.fd = b->m.fd;
-                       planes[0].length = b->length;
-               }
-
-               if (V4L2_TYPE_IS_OUTPUT(b->type)) {
-                       if (b->bytesused == 0)
-                               vb2_warn_zero_bytesused(vb);
-
-                       if (vb->vb2_queue->allow_zero_bytesused)
-                               planes[0].bytesused = b->bytesused;
-                       else
-                               planes[0].bytesused = b->bytesused ?
-                                       b->bytesused : planes[0].length;
-               } else
-                       planes[0].bytesused = 0;
-
-       }
-
-       /* Zero flags that the vb2 core handles */
-       vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
-       if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
-           V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
-               /*
-                * Non-COPY timestamps and non-OUTPUT queues will get
-                * their timestamp and timestamp source flags from the
-                * queue.
-                */
-               vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-       }
-
-       if (V4L2_TYPE_IS_OUTPUT(b->type)) {
-               /*
-                * For output buffers mask out the timecode flag:
-                * this will be handled later in vb2_internal_qbuf().
-                * The 'field' is valid metadata for this output buffer
-                * and so that needs to be copied here.
-                */
-               vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
-               vbuf->field = b->field;
-       } else {
-               /* Zero any output buffer flags as this is a capture buffer */
-               vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
-       }
-}
-
 /**
  * __qbuf_mmap() - handle qbuf of an MMAP buffer
  */
-static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __qbuf_mmap(struct vb2_buffer *vb, const void *pb)
 {
-       __fill_vb2_buffer(vb, b, vb->planes);
-       return call_vb_qop(vb, buf_prepare, vb);
+       int ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+                       vb, pb, vb->planes);
+       return ret ? ret : call_vb_qop(vb, buf_prepare, vb);
 }
 
 /**
  * __qbuf_userptr() - handle qbuf of a USERPTR buffer
  */
-static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __qbuf_userptr(struct vb2_buffer *vb, const void *pb)
 {
-       struct vb2_plane planes[VIDEO_MAX_PLANES];
+       struct vb2_plane planes[VB2_MAX_PLANES];
        struct vb2_queue *q = vb->vb2_queue;
        void *mem_priv;
        unsigned int plane;
        int ret;
        enum dma_data_direction dma_dir =
-               V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+               q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
        bool reacquired = vb->planes[0].mem_priv == NULL;
 
        memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
        /* Copy relevant information provided by the userspace */
-       __fill_vb2_buffer(vb, b, planes);
+       ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
+       if (ret)
+               return ret;
 
        for (plane = 0; plane < vb->num_planes; ++plane) {
                /* Skip the plane if already verified */
@@ -1545,20 +1050,22 @@ err:
 /**
  * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
  */
-static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb)
 {
-       struct vb2_plane planes[VIDEO_MAX_PLANES];
+       struct vb2_plane planes[VB2_MAX_PLANES];
        struct vb2_queue *q = vb->vb2_queue;
        void *mem_priv;
        unsigned int plane;
        int ret;
        enum dma_data_direction dma_dir =
-               V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+               q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
        bool reacquired = vb->planes[0].mem_priv == NULL;
 
        memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
        /* Copy relevant information provided by the userspace */
-       __fill_vb2_buffer(vb, b, planes);
+       ret = call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
+       if (ret)
+               return ret;
 
        for (plane = 0; plane < vb->num_planes; ++plane) {
                struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
@@ -1689,50 +1196,27 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
        call_void_vb_qop(vb, buf_queue, vb);
 }
 
-static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __buf_prepare(struct vb2_buffer *vb, const void *pb)
 {
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
        struct vb2_queue *q = vb->vb2_queue;
        int ret;
 
-       ret = __verify_length(vb, b);
-       if (ret < 0) {
-               dprintk(1, "plane parameters verification failed: %d\n", ret);
-               return ret;
-       }
-       if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) {
-               /*
-                * If the format's field is ALTERNATE, then the buffer's field
-                * should be either TOP or BOTTOM, not ALTERNATE since that
-                * makes no sense. The driver has to know whether the
-                * buffer represents a top or a bottom field in order to
-                * program any DMA correctly. Using ALTERNATE is wrong, since
-                * that just says that it is either a top or a bottom field,
-                * but not which of the two it is.
-                */
-               dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
-               return -EINVAL;
-       }
-
        if (q->error) {
                dprintk(1, "fatal error occurred on queue\n");
                return -EIO;
        }
 
        vb->state = VB2_BUF_STATE_PREPARING;
-       vbuf->timestamp.tv_sec = 0;
-       vbuf->timestamp.tv_usec = 0;
-       vbuf->sequence = 0;
 
        switch (q->memory) {
-       case V4L2_MEMORY_MMAP:
-               ret = __qbuf_mmap(vb, b);
+       case VB2_MEMORY_MMAP:
+               ret = __qbuf_mmap(vb, pb);
                break;
-       case V4L2_MEMORY_USERPTR:
-               ret = __qbuf_userptr(vb, b);
+       case VB2_MEMORY_USERPTR:
+               ret = __qbuf_userptr(vb, pb);
                break;
-       case V4L2_MEMORY_DMABUF:
-               ret = __qbuf_dmabuf(vb, b);
+       case VB2_MEMORY_DMABUF:
+               ret = __qbuf_dmabuf(vb, pb);
                break;
        default:
                WARN(1, "Invalid queue type\n");
@@ -1746,79 +1230,48 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
        return ret;
 }
 
-static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
-                                   const char *opname)
-{
-       if (b->type != q->type) {
-               dprintk(1, "%s: invalid buffer type\n", opname);
-               return -EINVAL;
-       }
-
-       if (b->index >= q->num_buffers) {
-               dprintk(1, "%s: buffer index out of range\n", opname);
-               return -EINVAL;
-       }
-
-       if (q->bufs[b->index] == NULL) {
-               /* Should never happen */
-               dprintk(1, "%s: buffer is NULL\n", opname);
-               return -EINVAL;
-       }
-
-       if (b->memory != q->memory) {
-               dprintk(1, "%s: invalid memory type\n", opname);
-               return -EINVAL;
-       }
-
-       return __verify_planes_array(q->bufs[b->index], b);
-}
-
 /**
- * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
+ * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace
+ *                     to the kernel
  * @q:         videobuf2 queue
- * @b:         buffer structure passed from userspace to vidioc_prepare_buf
+ * @index:     id number of the buffer
+ * @pb:                buffer structure passed from userspace to vidioc_prepare_buf
  *             handler in driver
  *
  * Should be called from vidioc_prepare_buf ioctl handler of a driver.
- * This function:
- * 1) verifies the passed buffer,
- * 2) calls buf_prepare callback in the driver (if provided), in which
- *    driver-specific buffer initialization can be performed,
+ * The passed buffer should have been verified.
+ * This function calls buf_prepare callback in the driver (if provided),
+ * in which driver-specific buffer initialization can be performed,
  *
  * The return values from this function are intended to be directly returned
  * from vidioc_prepare_buf handler in driver.
  */
-int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 {
        struct vb2_buffer *vb;
        int ret;
 
-       if (vb2_fileio_is_active(q)) {
-               dprintk(1, "file io in progress\n");
-               return -EBUSY;
-       }
-
-       ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
-       if (ret)
-               return ret;
-
-       vb = q->bufs[b->index];
+       vb = q->bufs[index];
        if (vb->state != VB2_BUF_STATE_DEQUEUED) {
                dprintk(1, "invalid buffer state %d\n",
                        vb->state);
                return -EINVAL;
        }
 
-       ret = __buf_prepare(vb, b);
-       if (!ret) {
-               /* Fill buffer information for the userspace */
-               __fill_v4l2_buffer(vb, b);
+       ret = __buf_prepare(vb, pb);
+       if (ret)
+               return ret;
+
+       /* Fill buffer information for the userspace */
+       ret = call_bufop(q, fill_user_buffer, vb, pb);
+       if (ret)
+               return ret;
+
+       dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
 
-               dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
-       }
        return ret;
 }
-EXPORT_SYMBOL_GPL(vb2_prepare_buf);
+EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
 /**
  * vb2_start_streaming() - Attempt to start streaming.
@@ -1883,21 +1336,34 @@ static int vb2_start_streaming(struct vb2_queue *q)
        return ret;
 }
 
-static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+/**
+ * vb2_core_qbuf() - Queue a buffer from userspace
+ * @q:         videobuf2 queue
+ * @index:     id number of the buffer
+ * @pb:                buffer structure passed from userspace to vidioc_qbuf handler
+ *             in driver
+ *
+ * Should be called from vidioc_qbuf ioctl handler of a driver.
+ * The passed buffer should have been verified.
+ * This function:
+ * 1) if necessary, calls buf_prepare callback in the driver (if provided), in
+ *    which driver-specific buffer initialization can be performed,
+ * 2) if streaming is on, queues the buffer in driver by the means of buf_queue
+ *    callback for processing.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_qbuf handler in driver.
+ */
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
 {
-       int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
        struct vb2_buffer *vb;
-       struct vb2_v4l2_buffer *vbuf;
-
-       if (ret)
-               return ret;
+       int ret;
 
-       vb = q->bufs[b->index];
-       vbuf = to_vb2_v4l2_buffer(vb);
+       vb = q->bufs[index];
 
        switch (vb->state) {
        case VB2_BUF_STATE_DEQUEUED:
-               ret = __buf_prepare(vb, b);
+               ret = __buf_prepare(vb, pb);
                if (ret)
                        return ret;
                break;
@@ -1919,18 +1385,8 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
        q->queued_count++;
        q->waiting_for_buffers = false;
        vb->state = VB2_BUF_STATE_QUEUED;
-       if (V4L2_TYPE_IS_OUTPUT(q->type)) {
-               /*
-                * For output buffers copy the timestamp if needed,
-                * and the timecode field and flag if needed.
-                */
-               if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
-                   V4L2_BUF_FLAG_TIMESTAMP_COPY)
-                       vbuf->timestamp = b->timestamp;
-               vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
-               if (b->flags & V4L2_BUF_FLAG_TIMECODE)
-                       vbuf->timecode = b->timecode;
-       }
+
+       call_bufop(q, set_timestamp, vb, pb);
 
        trace_vb2_qbuf(q, vb);
 
@@ -1942,7 +1398,9 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
                __enqueue_in_driver(vb);
 
        /* Fill buffer information for the userspace */
-       __fill_v4l2_buffer(vb, b);
+       ret = call_bufop(q, fill_user_buffer, vb, pb);
+       if (ret)
+               return ret;
 
        /*
         * If streamon has been called, and we haven't yet called
@@ -1960,34 +1418,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
        dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
        return 0;
 }
-
-/**
- * vb2_qbuf() - Queue a buffer from userspace
- * @q:         videobuf2 queue
- * @b:         buffer structure passed from userspace to vidioc_qbuf handler
- *             in driver
- *
- * Should be called from vidioc_qbuf ioctl handler of a driver.
- * This function:
- * 1) verifies the passed buffer,
- * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
- *    which driver-specific buffer initialization can be performed,
- * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
- *    callback for processing.
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_qbuf handler in driver.
- */
-int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
-{
-       if (vb2_fileio_is_active(q)) {
-               dprintk(1, "file io in progress\n");
-               return -EBUSY;
-       }
-
-       return vb2_internal_qbuf(q, b);
-}
-EXPORT_SYMBOL_GPL(vb2_qbuf);
+EXPORT_SYMBOL_GPL(vb2_core_qbuf);
 
 /**
  * __vb2_wait_for_done_vb() - wait for a buffer to become available
@@ -2071,7 +1502,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
  * Will sleep if required for nonblocking == false.
  */
 static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
-                               struct v4l2_buffer *b, int nonblocking)
+                               int nonblocking)
 {
        unsigned long flags;
        int ret;
@@ -2092,10 +1523,10 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
        /*
         * Only remove the buffer from done_list if v4l2_buffer can handle all
         * the planes.
+        * Verifying planes is NOT necessary since it already has been checked
+        * before the buffer is queued/prepared. So it can never fail.
         */
-       ret = __verify_planes_array(*vb, b);
-       if (!ret)
-               list_del(&(*vb)->done_entry);
+       list_del(&(*vb)->done_entry);
        spin_unlock_irqrestore(&q->done_lock, flags);
 
        return ret;
@@ -2138,7 +1569,7 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
        vb->state = VB2_BUF_STATE_DEQUEUED;
 
        /* unmap DMABUF buffer */
-       if (q->memory == V4L2_MEMORY_DMABUF)
+       if (q->memory == VB2_MEMORY_DMABUF)
                for (i = 0; i < vb->num_planes; ++i) {
                        if (!vb->planes[i].dbuf_mapped)
                                continue;
@@ -2147,18 +1578,33 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
                }
 }
 
-static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
-               bool nonblocking)
+/**
+ * vb2_dqbuf() - Dequeue a buffer to the userspace
+ * @q:         videobuf2 queue
+ * @pb:                buffer structure passed from userspace to vidioc_dqbuf handler
+ *             in driver
+ * @nonblocking: if true, this call will not sleep waiting for a buffer if no
+ *              buffers ready for dequeuing are present. Normally the driver
+ *              would be passing (file->f_flags & O_NONBLOCK) here
+ *
+ * Should be called from vidioc_dqbuf ioctl handler of a driver.
+ * The passed buffer should have been verified.
+ * This function:
+ * 1) calls buf_finish callback in the driver (if provided), in which
+ *    driver can perform any additional operations that may be required before
+ *    returning the buffer to userspace, such as cache sync,
+ * 2) the buffer struct members are filled with relevant information for
+ *    the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_dqbuf handler in driver.
+ */
+int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
 {
        struct vb2_buffer *vb = NULL;
-       struct vb2_v4l2_buffer *vbuf = NULL;
        int ret;
 
-       if (b->type != q->type) {
-               dprintk(1, "invalid buffer type\n");
-               return -EINVAL;
-       }
-       ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
+       ret = __vb2_get_done_vb(q, &vb, nonblocking);
        if (ret < 0)
                return ret;
 
@@ -2177,17 +1623,16 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
        call_void_vb_qop(vb, buf_finish, vb);
 
        /* Fill buffer information for the userspace */
-       __fill_v4l2_buffer(vb, b);
-       /* Remove from videobuf queue */
+       ret = call_bufop(q, fill_user_buffer, vb, pb);
+       if (ret)
+               return ret;
+
+       /* Remove from videobuf queue */
        list_del(&vb->queued_entry);
        q->queued_count--;
 
        trace_vb2_dqbuf(q, vb);
 
-       vbuf = to_vb2_v4l2_buffer(vb);
-       if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
-                       vbuf->flags & V4L2_BUF_FLAG_LAST)
-               q->last_buffer_dequeued = true;
        /* go back to dequeued state */
        __vb2_dqbuf(vb);
 
@@ -2195,38 +1640,9 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
                        vb->index, vb->state);
 
        return 0;
-}
 
-/**
- * vb2_dqbuf() - Dequeue a buffer to the userspace
- * @q:         videobuf2 queue
- * @b:         buffer structure passed from userspace to vidioc_dqbuf handler
- *             in driver
- * @nonblocking: if true, this call will not sleep waiting for a buffer if no
- *              buffers ready for dequeuing are present. Normally the driver
- *              would be passing (file->f_flags & O_NONBLOCK) here
- *
- * Should be called from vidioc_dqbuf ioctl handler of a driver.
- * This function:
- * 1) verifies the passed buffer,
- * 2) calls buf_finish callback in the driver (if provided), in which
- *    driver can perform any additional operations that may be required before
- *    returning the buffer to userspace, such as cache sync,
- * 3) the buffer struct members are filled with relevant information for
- *    the userspace.
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_dqbuf handler in driver.
- */
-int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
-{
-       if (vb2_fileio_is_active(q)) {
-               dprintk(1, "file io in progress\n");
-               return -EBUSY;
-       }
-       return vb2_internal_dqbuf(q, b, nonblocking);
 }
-EXPORT_SYMBOL_GPL(vb2_dqbuf);
+EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
 
 /**
  * __vb2_queue_cancel() - cancel and stop (pause) streaming
@@ -2296,7 +1712,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
        }
 }
 
-static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
+int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
 {
        int ret;
 
@@ -2338,6 +1754,7 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
        dprintk(3, "successful\n");
        return 0;
 }
+EXPORT_SYMBOL_GPL(vb2_core_streamon);
 
 /**
  * vb2_queue_error() - signal a fatal error on the queue
@@ -2360,30 +1777,7 @@ void vb2_queue_error(struct vb2_queue *q)
 }
 EXPORT_SYMBOL_GPL(vb2_queue_error);
 
-/**
- * vb2_streamon - start streaming
- * @q:         videobuf2 queue
- * @type:      type argument passed from userspace to vidioc_streamon handler
- *
- * Should be called from vidioc_streamon handler of a driver.
- * This function:
- * 1) verifies current state
- * 2) passes any previously queued buffers to the driver and starts streaming
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_streamon handler in the driver.
- */
-int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
-{
-       if (vb2_fileio_is_active(q)) {
-               dprintk(1, "file io in progress\n");
-               return -EBUSY;
-       }
-       return vb2_internal_streamon(q, type);
-}
-EXPORT_SYMBOL_GPL(vb2_streamon);
-
-static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
+int vb2_core_streamoff(struct vb2_queue *q, unsigned int type)
 {
        if (type != q->type) {
                dprintk(1, "invalid stream type\n");
@@ -2400,37 +1794,13 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
         * their normal dequeued state.
         */
        __vb2_queue_cancel(q);
-       q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
+       q->waiting_for_buffers = !q->is_output;
        q->last_buffer_dequeued = false;
 
        dprintk(3, "successful\n");
        return 0;
 }
-
-/**
- * vb2_streamoff - stop streaming
- * @q:         videobuf2 queue
- * @type:      type argument passed from userspace to vidioc_streamoff handler
- *
- * Should be called from vidioc_streamoff handler of a driver.
- * This function:
- * 1) verifies current state,
- * 2) stop streaming and dequeues any queued buffers, including those previously
- *    passed to the driver (after waiting for the driver to finish).
- *
- * This call can be used for pausing playback.
- * The return values from this function are intended to be directly returned
- * from vidioc_streamoff handler in the driver
- */
-int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
-{
-       if (vb2_fileio_is_active(q)) {
-               dprintk(1, "file io in progress\n");
-               return -EBUSY;
-       }
-       return vb2_internal_streamoff(q, type);
-}
-EXPORT_SYMBOL_GPL(vb2_streamoff);
+EXPORT_SYMBOL_GPL(vb2_core_streamoff);
 
 /**
  * __find_plane_by_offset() - find plane associated with the given offset off
@@ -2462,22 +1832,27 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 }
 
 /**
- * vb2_expbuf() - Export a buffer as a file descriptor
+ * vb2_core_expbuf() - Export a buffer as a file descriptor
  * @q:         videobuf2 queue
- * @eb:                export buffer structure passed from userspace to vidioc_expbuf
- *             handler in driver
+ * @fd:                file descriptor associated with DMABUF (set by driver) *
+ * @type:      buffer type
+ * @index:     id number of the buffer
+ * @plane:     index of the plane to be exported, 0 for single plane queues
+ * @flags:     flags for newly created file, currently only O_CLOEXEC is
+ *             supported, refer to manual of open syscall for more details
  *
  * The return values from this function are intended to be directly returned
  * from vidioc_expbuf handler in driver.
  */
-int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
+               unsigned int index, unsigned int plane, unsigned int flags)
 {
        struct vb2_buffer *vb = NULL;
        struct vb2_plane *vb_plane;
        int ret;
        struct dma_buf *dbuf;
 
-       if (q->memory != V4L2_MEMORY_MMAP) {
+       if (q->memory != VB2_MEMORY_MMAP) {
                dprintk(1, "queue is not currently set up for mmap\n");
                return -EINVAL;
        }
@@ -2487,24 +1862,24 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
                return -EINVAL;
        }
 
-       if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
+       if (flags & ~(O_CLOEXEC | O_ACCMODE)) {
                dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n");
                return -EINVAL;
        }
 
-       if (eb->type != q->type) {
+       if (type != q->type) {
                dprintk(1, "invalid buffer type\n");
                return -EINVAL;
        }
 
-       if (eb->index >= q->num_buffers) {
+       if (index >= q->num_buffers) {
                dprintk(1, "buffer index out of range\n");
                return -EINVAL;
        }
 
-       vb = q->bufs[eb->index];
+       vb = q->bufs[index];
 
-       if (eb->plane >= vb->num_planes) {
+       if (plane >= vb->num_planes) {
                dprintk(1, "buffer plane out of range\n");
                return -EINVAL;
        }
@@ -2514,30 +1889,31 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
                return -EBUSY;
        }
 
-       vb_plane = &vb->planes[eb->plane];
+       vb_plane = &vb->planes[plane];
 
-       dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
+       dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv,
+                               flags & O_ACCMODE);
        if (IS_ERR_OR_NULL(dbuf)) {
                dprintk(1, "failed to export buffer %d, plane %d\n",
-                       eb->index, eb->plane);
+                       index, plane);
                return -EINVAL;
        }
 
-       ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
+       ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
        if (ret < 0) {
                dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
-                       eb->index, eb->plane, ret);
+                       index, plane, ret);
                dma_buf_put(dbuf);
                return ret;
        }
 
        dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
-               eb->index, eb->plane, ret);
-       eb->fd = ret;
+               index, plane, ret);
+       *fd = ret;
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(vb2_expbuf);
+EXPORT_SYMBOL_GPL(vb2_core_expbuf);
 
 /**
  * vb2_mmap() - map video buffers into application address space
@@ -2566,7 +1942,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
        int ret;
        unsigned long length;
 
-       if (q->memory != V4L2_MEMORY_MMAP) {
+       if (q->memory != VB2_MEMORY_MMAP) {
                dprintk(1, "queue is not currently set up for mmap\n");
                return -EINVAL;
        }
@@ -2578,7 +1954,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
                dprintk(1, "invalid vma flags, VM_SHARED needed\n");
                return -EINVAL;
        }
-       if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+       if (q->is_output) {
                if (!(vma->vm_flags & VM_WRITE)) {
                        dprintk(1, "invalid vma flags, VM_WRITE needed\n");
                        return -EINVAL;
@@ -2639,7 +2015,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
        void *vaddr;
        int ret;
 
-       if (q->memory != V4L2_MEMORY_MMAP) {
+       if (q->memory != VB2_MEMORY_MMAP) {
                dprintk(1, "queue is not currently set up for mmap\n");
                return -EINVAL;
        }
@@ -2659,123 +2035,8 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
 #endif
 
-static int __vb2_init_fileio(struct vb2_queue *q, int read);
-static int __vb2_cleanup_fileio(struct vb2_queue *q);
-
-/**
- * vb2_poll() - implements poll userspace operation
- * @q:         videobuf2 queue
- * @file:      file argument passed to the poll file operation handler
- * @wait:      wait argument passed to the poll file operation handler
- *
- * This function implements poll file operation handler for a driver.
- * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
- * be informed that the file descriptor of a video device is available for
- * reading.
- * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
- * will be reported as available for writing.
- *
- * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
- * pending events.
- *
- * The return values from this function are intended to be directly returned
- * from poll handler in driver.
- */
-unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
-{
-       struct video_device *vfd = video_devdata(file);
-       unsigned long req_events = poll_requested_events(wait);
-       struct vb2_buffer *vb = NULL;
-       unsigned int res = 0;
-       unsigned long flags;
-
-       if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
-               struct v4l2_fh *fh = file->private_data;
-
-               if (v4l2_event_pending(fh))
-                       res = POLLPRI;
-               else if (req_events & POLLPRI)
-                       poll_wait(file, &fh->wait, wait);
-       }
-
-       if (!V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLIN | POLLRDNORM)))
-               return res;
-       if (V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLOUT | POLLWRNORM)))
-               return res;
-
-       /*
-        * Start file I/O emulator only if streaming API has not been used yet.
-        */
-       if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
-               if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
-                               (req_events & (POLLIN | POLLRDNORM))) {
-                       if (__vb2_init_fileio(q, 1))
-                               return res | POLLERR;
-               }
-               if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
-                               (req_events & (POLLOUT | POLLWRNORM))) {
-                       if (__vb2_init_fileio(q, 0))
-                               return res | POLLERR;
-                       /*
-                        * Write to OUTPUT queue can be done immediately.
-                        */
-                       return res | POLLOUT | POLLWRNORM;
-               }
-       }
-
-       /*
-        * There is nothing to wait for if the queue isn't streaming, or if the
-        * error flag is set.
-        */
-       if (!vb2_is_streaming(q) || q->error)
-               return res | POLLERR;
-       /*
-        * For compatibility with vb1: if QBUF hasn't been called yet, then
-        * return POLLERR as well. This only affects capture queues, output
-        * queues will always initialize waiting_for_buffers to false.
-        */
-       if (q->waiting_for_buffers)
-               return res | POLLERR;
-
-       /*
-        * For output streams you can write as long as there are fewer buffers
-        * queued than there are buffers available.
-        */
-       if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
-               return res | POLLOUT | POLLWRNORM;
-
-       if (list_empty(&q->done_list)) {
-               /*
-                * If the last buffer was dequeued from a capture queue,
-                * return immediately. DQBUF will return -EPIPE.
-                */
-               if (q->last_buffer_dequeued)
-                       return res | POLLIN | POLLRDNORM;
-
-               poll_wait(file, &q->done_wq, wait);
-       }
-
-       /*
-        * Take first buffer available for dequeuing.
-        */
-       spin_lock_irqsave(&q->done_lock, flags);
-       if (!list_empty(&q->done_list))
-               vb = list_first_entry(&q->done_list, struct vb2_buffer,
-                                       done_entry);
-       spin_unlock_irqrestore(&q->done_lock, flags);
-
-       if (vb && (vb->state == VB2_BUF_STATE_DONE
-                       || vb->state == VB2_BUF_STATE_ERROR)) {
-               return (V4L2_TYPE_IS_OUTPUT(q->type)) ?
-                               res | POLLOUT | POLLWRNORM :
-                               res | POLLIN | POLLRDNORM;
-       }
-       return res;
-}
-EXPORT_SYMBOL_GPL(vb2_poll);
-
 /**
- * vb2_queue_init() - initialize a videobuf2 queue
+ * vb2_core_queue_init() - initialize a videobuf2 queue
  * @q:         videobuf2 queue; this structure should be allocated in driver
  *
  * The vb2_queue structure should be allocated by the driver. The driver is
@@ -2785,7 +2046,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
  * to the struct vb2_queue description in include/media/videobuf2-core.h
  * for more information.
  */
-int vb2_queue_init(struct vb2_queue *q)
+int vb2_core_queue_init(struct vb2_queue *q)
 {
        /*
         * Sanity check
@@ -2796,16 +2057,9 @@ int vb2_queue_init(struct vb2_queue *q)
            WARN_ON(!q->type)             ||
            WARN_ON(!q->io_modes)         ||
            WARN_ON(!q->ops->queue_setup) ||
-           WARN_ON(!q->ops->buf_queue)   ||
-           WARN_ON(q->timestamp_flags &
-                   ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
-                     V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
+           WARN_ON(!q->ops->buf_queue))
                return -EINVAL;
 
-       /* Warn that the driver should choose an appropriate timestamp type */
-       WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
-               V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
-
        INIT_LIST_HEAD(&q->queued_list);
        INIT_LIST_HEAD(&q->done_list);
        spin_lock_init(&q->done_lock);
@@ -2813,823 +2067,28 @@ int vb2_queue_init(struct vb2_queue *q)
        init_waitqueue_head(&q->done_wq);
 
        if (q->buf_struct_size == 0)
-               q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
+               q->buf_struct_size = sizeof(struct vb2_buffer);
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(vb2_queue_init);
+EXPORT_SYMBOL_GPL(vb2_core_queue_init);
 
 /**
- * vb2_queue_release() - stop streaming, release the queue and free memory
+ * vb2_core_queue_release() - stop streaming, release the queue and free memory
  * @q:         videobuf2 queue
  *
  * This function stops streaming and performs necessary clean ups, including
  * freeing video buffer memory. The driver is responsible for freeing
  * the vb2_queue structure itself.
  */
-void vb2_queue_release(struct vb2_queue *q)
+void vb2_core_queue_release(struct vb2_queue *q)
 {
-       __vb2_cleanup_fileio(q);
        __vb2_queue_cancel(q);
        mutex_lock(&q->mmap_lock);
        __vb2_queue_free(q, q->num_buffers);
        mutex_unlock(&q->mmap_lock);
 }
-EXPORT_SYMBOL_GPL(vb2_queue_release);
-
-/**
- * struct vb2_fileio_buf - buffer context used by file io emulator
- *
- * vb2 provides a compatibility layer and emulator of file io (read and
- * write) calls on top of streaming API. This structure is used for
- * tracking context related to the buffers.
- */
-struct vb2_fileio_buf {
-       void *vaddr;
-       unsigned int size;
-       unsigned int pos;
-       unsigned int queued:1;
-};
-
-/**
- * struct vb2_fileio_data - queue context used by file io emulator
- *
- * @cur_index: the index of the buffer currently being read from or
- *             written to. If equal to q->num_buffers then a new buffer
- *             must be dequeued.
- * @initial_index: in the read() case all buffers are queued up immediately
- *             in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
- *             buffers. However, in the write() case no buffers are initially
- *             queued, instead whenever a buffer is full it is queued up by
- *             __vb2_perform_fileio(). Only once all available buffers have
- *             been queued up will __vb2_perform_fileio() start to dequeue
- *             buffers. This means that initially __vb2_perform_fileio()
- *             needs to know what buffer index to use when it is queuing up
- *             the buffers for the first time. That initial index is stored
- *             in this field. Once it is equal to q->num_buffers all
- *             available buffers have been queued and __vb2_perform_fileio()
- *             should start the normal dequeue/queue cycle.
- *
- * vb2 provides a compatibility layer and emulator of file io (read and
- * write) calls on top of streaming API. For proper operation it required
- * this structure to save the driver state between each call of the read
- * or write function.
- */
-struct vb2_fileio_data {
-       struct v4l2_requestbuffers req;
-       struct v4l2_plane p;
-       struct v4l2_buffer b;
-       struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
-       unsigned int cur_index;
-       unsigned int initial_index;
-       unsigned int q_count;
-       unsigned int dq_count;
-       unsigned read_once:1;
-       unsigned write_immediately:1;
-};
-
-/**
- * __vb2_init_fileio() - initialize file io emulator
- * @q:         videobuf2 queue
- * @read:      mode selector (1 means read, 0 means write)
- */
-static int __vb2_init_fileio(struct vb2_queue *q, int read)
-{
-       struct vb2_fileio_data *fileio;
-       int i, ret;
-       unsigned int count = 0;
-
-       /*
-        * Sanity check
-        */
-       if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
-                   (!read && !(q->io_modes & VB2_WRITE))))
-               return -EINVAL;
-
-       /*
-        * Check if device supports mapping buffers to kernel virtual space.
-        */
-       if (!q->mem_ops->vaddr)
-               return -EBUSY;
-
-       /*
-        * Check if streaming api has not been already activated.
-        */
-       if (q->streaming || q->num_buffers > 0)
-               return -EBUSY;
-
-       /*
-        * Start with count 1, driver can increase it in queue_setup()
-        */
-       count = 1;
-
-       dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
-               (read) ? "read" : "write", count, q->fileio_read_once,
-               q->fileio_write_immediately);
-
-       fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
-       if (fileio == NULL)
-               return -ENOMEM;
-
-       fileio->read_once = q->fileio_read_once;
-       fileio->write_immediately = q->fileio_write_immediately;
-
-       /*
-        * Request buffers and use MMAP type to force driver
-        * to allocate buffers by itself.
-        */
-       fileio->req.count = count;
-       fileio->req.memory = V4L2_MEMORY_MMAP;
-       fileio->req.type = q->type;
-       q->fileio = fileio;
-       ret = __reqbufs(q, &fileio->req);
-       if (ret)
-               goto err_kfree;
-
-       /*
-        * Check if plane_count is correct
-        * (multiplane buffers are not supported).
-        */
-       if (q->bufs[0]->num_planes != 1) {
-               ret = -EBUSY;
-               goto err_reqbufs;
-       }
-
-       /*
-        * Get kernel address of each buffer.
-        */
-       for (i = 0; i < q->num_buffers; i++) {
-               fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
-               if (fileio->bufs[i].vaddr == NULL) {
-                       ret = -EINVAL;
-                       goto err_reqbufs;
-               }
-               fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
-       }
-
-       /*
-        * Read mode requires pre queuing of all buffers.
-        */
-       if (read) {
-               bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
-
-               /*
-                * Queue all buffers.
-                */
-               for (i = 0; i < q->num_buffers; i++) {
-                       struct v4l2_buffer *b = &fileio->b;
-
-                       memset(b, 0, sizeof(*b));
-                       b->type = q->type;
-                       if (is_multiplanar) {
-                               memset(&fileio->p, 0, sizeof(fileio->p));
-                               b->m.planes = &fileio->p;
-                               b->length = 1;
-                       }
-                       b->memory = q->memory;
-                       b->index = i;
-                       ret = vb2_internal_qbuf(q, b);
-                       if (ret)
-                               goto err_reqbufs;
-                       fileio->bufs[i].queued = 1;
-               }
-               /*
-                * All buffers have been queued, so mark that by setting
-                * initial_index to q->num_buffers
-                */
-               fileio->initial_index = q->num_buffers;
-               fileio->cur_index = q->num_buffers;
-       }
-
-       /*
-        * Start streaming.
-        */
-       ret = vb2_internal_streamon(q, q->type);
-       if (ret)
-               goto err_reqbufs;
-
-       return ret;
-
-err_reqbufs:
-       fileio->req.count = 0;
-       __reqbufs(q, &fileio->req);
-
-err_kfree:
-       q->fileio = NULL;
-       kfree(fileio);
-       return ret;
-}
-
-/**
- * __vb2_cleanup_fileio() - free resourced used by file io emulator
- * @q:         videobuf2 queue
- */
-static int __vb2_cleanup_fileio(struct vb2_queue *q)
-{
-       struct vb2_fileio_data *fileio = q->fileio;
-
-       if (fileio) {
-               vb2_internal_streamoff(q, q->type);
-               q->fileio = NULL;
-               fileio->req.count = 0;
-               vb2_reqbufs(q, &fileio->req);
-               kfree(fileio);
-               dprintk(3, "file io emulator closed\n");
-       }
-       return 0;
-}
-
-/**
- * __vb2_perform_fileio() - perform a single file io (read or write) operation
- * @q:         videobuf2 queue
- * @data:      pointed to target userspace buffer
- * @count:     number of bytes to read or write
- * @ppos:      file handle position tracking pointer
- * @nonblock:  mode selector (1 means blocking calls, 0 means nonblocking)
- * @read:      access mode selector (1 means read, 0 means write)
- */
-static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
-               loff_t *ppos, int nonblock, int read)
-{
-       struct vb2_fileio_data *fileio;
-       struct vb2_fileio_buf *buf;
-       bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
-       /*
-        * When using write() to write data to an output video node the vb2 core
-        * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
-        * else is able to provide this information with the write() operation.
-        */
-       bool set_timestamp = !read &&
-               (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
-               V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       int ret, index;
-
-       dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
-               read ? "read" : "write", (long)*ppos, count,
-               nonblock ? "non" : "");
-
-       if (!data)
-               return -EINVAL;
-
-       /*
-        * Initialize emulator on first call.
-        */
-       if (!vb2_fileio_is_active(q)) {
-               ret = __vb2_init_fileio(q, read);
-               dprintk(3, "vb2_init_fileio result: %d\n", ret);
-               if (ret)
-                       return ret;
-       }
-       fileio = q->fileio;
-
-       /*
-        * Check if we need to dequeue the buffer.
-        */
-       index = fileio->cur_index;
-       if (index >= q->num_buffers) {
-               /*
-                * Call vb2_dqbuf to get buffer back.
-                */
-               memset(&fileio->b, 0, sizeof(fileio->b));
-               fileio->b.type = q->type;
-               fileio->b.memory = q->memory;
-               if (is_multiplanar) {
-                       memset(&fileio->p, 0, sizeof(fileio->p));
-                       fileio->b.m.planes = &fileio->p;
-                       fileio->b.length = 1;
-               }
-               ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
-               dprintk(5, "vb2_dqbuf result: %d\n", ret);
-               if (ret)
-                       return ret;
-               fileio->dq_count += 1;
-
-               fileio->cur_index = index = fileio->b.index;
-               buf = &fileio->bufs[index];
-
-               /*
-                * Get number of bytes filled by the driver
-                */
-               buf->pos = 0;
-               buf->queued = 0;
-               buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
-                                : vb2_plane_size(q->bufs[index], 0);
-               /* Compensate for data_offset on read in the multiplanar case. */
-               if (is_multiplanar && read &&
-                   fileio->b.m.planes[0].data_offset < buf->size) {
-                       buf->pos = fileio->b.m.planes[0].data_offset;
-                       buf->size -= buf->pos;
-               }
-       } else {
-               buf = &fileio->bufs[index];
-       }
-
-       /*
-        * Limit count on last few bytes of the buffer.
-        */
-       if (buf->pos + count > buf->size) {
-               count = buf->size - buf->pos;
-               dprintk(5, "reducing read count: %zd\n", count);
-       }
-
-       /*
-        * Transfer data to userspace.
-        */
-       dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
-               count, index, buf->pos);
-       if (read)
-               ret = copy_to_user(data, buf->vaddr + buf->pos, count);
-       else
-               ret = copy_from_user(buf->vaddr + buf->pos, data, count);
-       if (ret) {
-               dprintk(3, "error copying data\n");
-               return -EFAULT;
-       }
-
-       /*
-        * Update counters.
-        */
-       buf->pos += count;
-       *ppos += count;
-
-       /*
-        * Queue next buffer if required.
-        */
-       if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
-               /*
-                * Check if this is the last buffer to read.
-                */
-               if (read && fileio->read_once && fileio->dq_count == 1) {
-                       dprintk(3, "read limit reached\n");
-                       return __vb2_cleanup_fileio(q);
-               }
-
-               /*
-                * Call vb2_qbuf and give buffer to the driver.
-                */
-               memset(&fileio->b, 0, sizeof(fileio->b));
-               fileio->b.type = q->type;
-               fileio->b.memory = q->memory;
-               fileio->b.index = index;
-               fileio->b.bytesused = buf->pos;
-               if (is_multiplanar) {
-                       memset(&fileio->p, 0, sizeof(fileio->p));
-                       fileio->p.bytesused = buf->pos;
-                       fileio->b.m.planes = &fileio->p;
-                       fileio->b.length = 1;
-               }
-               if (set_timestamp)
-                       v4l2_get_timestamp(&fileio->b.timestamp);
-               ret = vb2_internal_qbuf(q, &fileio->b);
-               dprintk(5, "vb2_dbuf result: %d\n", ret);
-               if (ret)
-                       return ret;
-
-               /*
-                * Buffer has been queued, update the status
-                */
-               buf->pos = 0;
-               buf->queued = 1;
-               buf->size = vb2_plane_size(q->bufs[index], 0);
-               fileio->q_count += 1;
-               /*
-                * If we are queuing up buffers for the first time, then
-                * increase initial_index by one.
-                */
-               if (fileio->initial_index < q->num_buffers)
-                       fileio->initial_index++;
-               /*
-                * The next buffer to use is either a buffer that's going to be
-                * queued for the first time (initial_index < q->num_buffers)
-                * or it is equal to q->num_buffers, meaning that the next
-                * time we need to dequeue a buffer since we've now queued up
-                * all the 'first time' buffers.
-                */
-               fileio->cur_index = fileio->initial_index;
-       }
-
-       /*
-        * Return proper number of bytes processed.
-        */
-       if (ret == 0)
-               ret = count;
-       return ret;
-}
-
-size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
-               loff_t *ppos, int nonblocking)
-{
-       return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
-}
-EXPORT_SYMBOL_GPL(vb2_read);
-
-size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
-               loff_t *ppos, int nonblocking)
-{
-       return __vb2_perform_fileio(q, (char __user *) data, count,
-                                                       ppos, nonblocking, 0);
-}
-EXPORT_SYMBOL_GPL(vb2_write);
-
-struct vb2_threadio_data {
-       struct task_struct *thread;
-       vb2_thread_fnc fnc;
-       void *priv;
-       bool stop;
-};
-
-static int vb2_thread(void *data)
-{
-       struct vb2_queue *q = data;
-       struct vb2_threadio_data *threadio = q->threadio;
-       struct vb2_fileio_data *fileio = q->fileio;
-       bool set_timestamp = false;
-       int prequeue = 0;
-       int index = 0;
-       int ret = 0;
-
-       if (V4L2_TYPE_IS_OUTPUT(q->type)) {
-               prequeue = q->num_buffers;
-               set_timestamp =
-                       (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
-                       V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       }
-
-       set_freezable();
-
-       for (;;) {
-               struct vb2_buffer *vb;
-
-               /*
-                * Call vb2_dqbuf to get buffer back.
-                */
-               memset(&fileio->b, 0, sizeof(fileio->b));
-               fileio->b.type = q->type;
-               fileio->b.memory = q->memory;
-               if (prequeue) {
-                       fileio->b.index = index++;
-                       prequeue--;
-               } else {
-                       call_void_qop(q, wait_finish, q);
-                       if (!threadio->stop)
-                               ret = vb2_internal_dqbuf(q, &fileio->b, 0);
-                       call_void_qop(q, wait_prepare, q);
-                       dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
-               }
-               if (ret || threadio->stop)
-                       break;
-               try_to_freeze();
-
-               vb = q->bufs[fileio->b.index];
-               if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
-                       if (threadio->fnc(vb, threadio->priv))
-                               break;
-               call_void_qop(q, wait_finish, q);
-               if (set_timestamp)
-                       v4l2_get_timestamp(&fileio->b.timestamp);
-               if (!threadio->stop)
-                       ret = vb2_internal_qbuf(q, &fileio->b);
-               call_void_qop(q, wait_prepare, q);
-               if (ret || threadio->stop)
-                       break;
-       }
-
-       /* Hmm, linux becomes *very* unhappy without this ... */
-       while (!kthread_should_stop()) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-       }
-       return 0;
-}
-
-/*
- * This function should not be used for anything else but the videobuf2-dvb
- * support. If you think you have another good use-case for this, then please
- * contact the linux-media mailinglist first.
- */
-int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
-                    const char *thread_name)
-{
-       struct vb2_threadio_data *threadio;
-       int ret = 0;
-
-       if (q->threadio)
-               return -EBUSY;
-       if (vb2_is_busy(q))
-               return -EBUSY;
-       if (WARN_ON(q->fileio))
-               return -EBUSY;
-
-       threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
-       if (threadio == NULL)
-               return -ENOMEM;
-       threadio->fnc = fnc;
-       threadio->priv = priv;
-
-       ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type));
-       dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
-       if (ret)
-               goto nomem;
-       q->threadio = threadio;
-       threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
-       if (IS_ERR(threadio->thread)) {
-               ret = PTR_ERR(threadio->thread);
-               threadio->thread = NULL;
-               goto nothread;
-       }
-       return 0;
-
-nothread:
-       __vb2_cleanup_fileio(q);
-nomem:
-       kfree(threadio);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(vb2_thread_start);
-
-int vb2_thread_stop(struct vb2_queue *q)
-{
-       struct vb2_threadio_data *threadio = q->threadio;
-       int err;
-
-       if (threadio == NULL)
-               return 0;
-       threadio->stop = true;
-       /* Wake up all pending sleeps in the thread */
-       vb2_queue_error(q);
-       err = kthread_stop(threadio->thread);
-       __vb2_cleanup_fileio(q);
-       threadio->thread = NULL;
-       kfree(threadio);
-       q->threadio = NULL;
-       return err;
-}
-EXPORT_SYMBOL_GPL(vb2_thread_stop);
-
-/*
- * The following functions are not part of the vb2 core API, but are helper
- * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
- * and struct vb2_ops.
- * They contain boilerplate code that most if not all drivers have to do
- * and so they simplify the driver code.
- */
-
-/* The queue is busy if there is a owner and you are not that owner. */
-static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
-{
-       return vdev->queue->owner && vdev->queue->owner != file->private_data;
-}
-
-/* vb2 ioctl helpers */
-
-int vb2_ioctl_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *p)
-{
-       struct video_device *vdev = video_devdata(file);
-       int res = __verify_memory_type(vdev->queue, p->memory, p->type);
-
-       if (res)
-               return res;
-       if (vb2_queue_is_busy(vdev, file))
-               return -EBUSY;
-       res = __reqbufs(vdev->queue, p);
-       /* If count == 0, then the owner has released all buffers and he
-          is no longer owner of the queue. Otherwise we have a new owner. */
-       if (res == 0)
-               vdev->queue->owner = p->count ? file->private_data : NULL;
-       return res;
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
-
-int vb2_ioctl_create_bufs(struct file *file, void *priv,
-                         struct v4l2_create_buffers *p)
-{
-       struct video_device *vdev = video_devdata(file);
-       int res = __verify_memory_type(vdev->queue, p->memory, p->format.type);
-
-       p->index = vdev->queue->num_buffers;
-       /* If count == 0, then just check if memory and type are valid.
-          Any -EBUSY result from __verify_memory_type can be mapped to 0. */
-       if (p->count == 0)
-               return res != -EBUSY ? res : 0;
-       if (res)
-               return res;
-       if (vb2_queue_is_busy(vdev, file))
-               return -EBUSY;
-       res = __create_bufs(vdev->queue, p);
-       if (res == 0)
-               vdev->queue->owner = file->private_data;
-       return res;
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
-
-int vb2_ioctl_prepare_buf(struct file *file, void *priv,
-                         struct v4l2_buffer *p)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       if (vb2_queue_is_busy(vdev, file))
-               return -EBUSY;
-       return vb2_prepare_buf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
-
-int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       /* No need to call vb2_queue_is_busy(), anyone can query buffers. */
-       return vb2_querybuf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
-
-int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       if (vb2_queue_is_busy(vdev, file))
-               return -EBUSY;
-       return vb2_qbuf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
-
-int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       if (vb2_queue_is_busy(vdev, file))
-               return -EBUSY;
-       return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
-
-int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       if (vb2_queue_is_busy(vdev, file))
-               return -EBUSY;
-       return vb2_streamon(vdev->queue, i);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
-
-int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       if (vb2_queue_is_busy(vdev, file))
-               return -EBUSY;
-       return vb2_streamoff(vdev->queue, i);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
-
-int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       if (vb2_queue_is_busy(vdev, file))
-               return -EBUSY;
-       return vb2_expbuf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
-
-/* v4l2_file_operations helpers */
-
-int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       return vb2_mmap(vdev->queue, vma);
-}
-EXPORT_SYMBOL_GPL(vb2_fop_mmap);
-
-int _vb2_fop_release(struct file *file, struct mutex *lock)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       if (lock)
-               mutex_lock(lock);
-       if (file->private_data == vdev->queue->owner) {
-               vb2_queue_release(vdev->queue);
-               vdev->queue->owner = NULL;
-       }
-       if (lock)
-               mutex_unlock(lock);
-       return v4l2_fh_release(file);
-}
-EXPORT_SYMBOL_GPL(_vb2_fop_release);
-
-int vb2_fop_release(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
-
-       return _vb2_fop_release(file, lock);
-}
-EXPORT_SYMBOL_GPL(vb2_fop_release);
-
-ssize_t vb2_fop_write(struct file *file, const char __user *buf,
-               size_t count, loff_t *ppos)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
-       int err = -EBUSY;
-
-       if (!(vdev->queue->io_modes & VB2_WRITE))
-               return -EINVAL;
-       if (lock && mutex_lock_interruptible(lock))
-               return -ERESTARTSYS;
-       if (vb2_queue_is_busy(vdev, file))
-               goto exit;
-       err = vb2_write(vdev->queue, buf, count, ppos,
-                      file->f_flags & O_NONBLOCK);
-       if (vdev->queue->fileio)
-               vdev->queue->owner = file->private_data;
-exit:
-       if (lock)
-               mutex_unlock(lock);
-       return err;
-}
-EXPORT_SYMBOL_GPL(vb2_fop_write);
-
-ssize_t vb2_fop_read(struct file *file, char __user *buf,
-               size_t count, loff_t *ppos)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
-       int err = -EBUSY;
-
-       if (!(vdev->queue->io_modes & VB2_READ))
-               return -EINVAL;
-       if (lock && mutex_lock_interruptible(lock))
-               return -ERESTARTSYS;
-       if (vb2_queue_is_busy(vdev, file))
-               goto exit;
-       err = vb2_read(vdev->queue, buf, count, ppos,
-                      file->f_flags & O_NONBLOCK);
-       if (vdev->queue->fileio)
-               vdev->queue->owner = file->private_data;
-exit:
-       if (lock)
-               mutex_unlock(lock);
-       return err;
-}
-EXPORT_SYMBOL_GPL(vb2_fop_read);
-
-unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct vb2_queue *q = vdev->queue;
-       struct mutex *lock = q->lock ? q->lock : vdev->lock;
-       unsigned res;
-       void *fileio;
-
-       /*
-        * If this helper doesn't know how to lock, then you shouldn't be using
-        * it but you should write your own.
-        */
-       WARN_ON(!lock);
-
-       if (lock && mutex_lock_interruptible(lock))
-               return POLLERR;
-
-       fileio = q->fileio;
-
-       res = vb2_poll(vdev->queue, file, wait);
-
-       /* If fileio was started, then we have a new queue owner. */
-       if (!fileio && q->fileio)
-               q->owner = file->private_data;
-       if (lock)
-               mutex_unlock(lock);
-       return res;
-}
-EXPORT_SYMBOL_GPL(vb2_fop_poll);
-
-#ifndef CONFIG_MMU
-unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
-               unsigned long len, unsigned long pgoff, unsigned long flags)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
-}
-EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
-#endif
-
-/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
-
-void vb2_ops_wait_prepare(struct vb2_queue *vq)
-{
-       mutex_unlock(vq->lock);
-}
-EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
-
-void vb2_ops_wait_finish(struct vb2_queue *vq)
-{
-       mutex_lock(vq->lock);
-}
-EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
+EXPORT_SYMBOL_GPL(vb2_core_queue_release);
 
 MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
 MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
index ea33d69bbed964a64dddf7372adc3bf6fff4e74e..c33127284cfeed93ba4bf9993c49c470b8587802 100644 (file)
@@ -100,7 +100,8 @@ static void vb2_dc_prepare(void *buf_priv)
        if (!sgt || buf->db_attach)
                return;
 
-       dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+       dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->orig_nents,
+                              buf->dma_dir);
 }
 
 static void vb2_dc_finish(void *buf_priv)
@@ -112,7 +113,7 @@ static void vb2_dc_finish(void *buf_priv)
        if (!sgt || buf->db_attach)
                return;
 
-       dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+       dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
 }
 
 /*********************************************/
index 34b67784a9c11392b094540bf980e5b17bae5390..9985c89f0513be0c14e05d1f5dac81a1796fa82f 100644 (file)
@@ -210,7 +210,8 @@ static void vb2_dma_sg_prepare(void *buf_priv)
        if (buf->db_attach)
                return;
 
-       dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+       dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->orig_nents,
+                              buf->dma_dir);
 }
 
 static void vb2_dma_sg_finish(void *buf_priv)
@@ -222,7 +223,7 @@ static void vb2_dma_sg_finish(void *buf_priv)
        if (buf->db_attach)
                return;
 
-       dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+       dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
 }
 
 static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h
new file mode 100644 (file)
index 0000000..79018c7
--- /dev/null
@@ -0,0 +1,161 @@
+#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H
+#define _MEDIA_VIDEOBUF2_INTERNAL_H
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <media/videobuf2-core.h>
+
+extern int vb2_debug;
+
+#define dprintk(level, fmt, arg...)                                          \
+       do {                                                                  \
+               if (vb2_debug >= level)                                       \
+                       pr_info("vb2: %s: " fmt, __func__, ## arg); \
+       } while (0)
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+
+/*
+ * If advanced debugging is on, then count how often each op is called
+ * successfully, which can either be per-buffer or per-queue.
+ *
+ * This makes it easy to check that the 'init' and 'cleanup'
+ * (and variations thereof) stay balanced.
+ */
+
+#define log_memop(vb, op)                                              \
+       dprintk(2, "call_memop(%p, %d, %s)%s\n",                        \
+               (vb)->vb2_queue, (vb)->index, #op,                      \
+               (vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
+
+#define call_memop(vb, op, args...)                                    \
+({                                                                     \
+       struct vb2_queue *_q = (vb)->vb2_queue;                         \
+       int err;                                                        \
+                                                                       \
+       log_memop(vb, op);                                              \
+       err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;              \
+       if (!err)                                                       \
+               (vb)->cnt_mem_ ## op++;                                 \
+       err;                                                            \
+})
+
+#define call_ptr_memop(vb, op, args...)                                        \
+({                                                                     \
+       struct vb2_queue *_q = (vb)->vb2_queue;                         \
+       void *ptr;                                                      \
+                                                                       \
+       log_memop(vb, op);                                              \
+       ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;           \
+       if (!IS_ERR_OR_NULL(ptr))                                       \
+               (vb)->cnt_mem_ ## op++;                                 \
+       ptr;                                                            \
+})
+
+#define call_void_memop(vb, op, args...)                               \
+({                                                                     \
+       struct vb2_queue *_q = (vb)->vb2_queue;                         \
+                                                                       \
+       log_memop(vb, op);                                              \
+       if (_q->mem_ops->op)                                            \
+               _q->mem_ops->op(args);                                  \
+       (vb)->cnt_mem_ ## op++;                                         \
+})
+
+#define log_qop(q, op)                                                 \
+       dprintk(2, "call_qop(%p, %s)%s\n", q, #op,                      \
+               (q)->ops->op ? "" : " (nop)")
+
+#define call_qop(q, op, args...)                                       \
+({                                                                     \
+       int err;                                                        \
+                                                                       \
+       log_qop(q, op);                                                 \
+       err = (q)->ops->op ? (q)->ops->op(args) : 0;                    \
+       if (!err)                                                       \
+               (q)->cnt_ ## op++;                                      \
+       err;                                                            \
+})
+
+#define call_void_qop(q, op, args...)                                  \
+({                                                                     \
+       log_qop(q, op);                                                 \
+       if ((q)->ops->op)                                               \
+               (q)->ops->op(args);                                     \
+       (q)->cnt_ ## op++;                                              \
+})
+
+#define log_vb_qop(vb, op, args...)                                    \
+       dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",                       \
+               (vb)->vb2_queue, (vb)->index, #op,                      \
+               (vb)->vb2_queue->ops->op ? "" : " (nop)")
+
+#define call_vb_qop(vb, op, args...)                                   \
+({                                                                     \
+       int err;                                                        \
+                                                                       \
+       log_vb_qop(vb, op);                                             \
+       err = (vb)->vb2_queue->ops->op ?                                \
+               (vb)->vb2_queue->ops->op(args) : 0;                     \
+       if (!err)                                                       \
+               (vb)->cnt_ ## op++;                                     \
+       err;                                                            \
+})
+
+#define call_void_vb_qop(vb, op, args...)                              \
+({                                                                     \
+       log_vb_qop(vb, op);                                             \
+       if ((vb)->vb2_queue->ops->op)                                   \
+               (vb)->vb2_queue->ops->op(args);                         \
+       (vb)->cnt_ ## op++;                                             \
+})
+
+#else
+
+#define call_memop(vb, op, args...)                                    \
+       ((vb)->vb2_queue->mem_ops->op ?                                 \
+               (vb)->vb2_queue->mem_ops->op(args) : 0)
+
+#define call_ptr_memop(vb, op, args...)                                        \
+       ((vb)->vb2_queue->mem_ops->op ?                                 \
+               (vb)->vb2_queue->mem_ops->op(args) : NULL)
+
+#define call_void_memop(vb, op, args...)                               \
+       do {                                                            \
+               if ((vb)->vb2_queue->mem_ops->op)                       \
+                       (vb)->vb2_queue->mem_ops->op(args);             \
+       } while (0)
+
+#define call_qop(q, op, args...)                                       \
+       ((q)->ops->op ? (q)->ops->op(args) : 0)
+
+#define call_void_qop(q, op, args...)                                  \
+       do {                                                            \
+               if ((q)->ops->op)                                       \
+                       (q)->ops->op(args);                             \
+       } while (0)
+
+#define call_vb_qop(vb, op, args...)                                   \
+       ((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
+
+#define call_void_vb_qop(vb, op, args...)                              \
+       do {                                                            \
+               if ((vb)->vb2_queue->ops->op)                           \
+                       (vb)->vb2_queue->ops->op(args);                 \
+       } while (0)
+
+#endif
+
+#define call_bufop(q, op, args...)                                     \
+({                                                                     \
+       int ret = 0;                                                    \
+       if (q && q->buf_ops && q->buf_ops->op)                          \
+               ret = q->buf_ops->op(args);                             \
+       ret;                                                            \
+})
+
+bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
+int vb2_verify_memory_type(struct vb2_queue *q,
+               enum vb2_memory memory, unsigned int type);
+#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */
index 2f2b73820a9cf8c65ecf325890cc93559eb97175..27b4b9e7c0c2f63c65c0fdaa1f515fc949a4dee2 100644 (file)
 #include <linux/freezer.h>
 #include <linux/kthread.h>
 
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-common.h>
+
 #include <media/videobuf2-v4l2.h>
 
+#include "videobuf2-internal.h"
+
+/* Flags that are set by the vb2 core */
+#define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
+                                V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
+                                V4L2_BUF_FLAG_PREPARED | \
+                                V4L2_BUF_FLAG_TIMESTAMP_MASK)
+/* Output buffer flags that should be passed on to the driver */
+#define V4L2_BUFFER_OUT_FLAGS  (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
+                                V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
+
+/**
+ * __verify_planes_array() - verify that the planes array passed in struct
+ * v4l2_buffer from userspace can be safely used
+ */
+static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+       if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
+               return 0;
+
+       /* Is memory for copying plane information present? */
+       if (NULL == b->m.planes) {
+               dprintk(1, "multi-planar buffer passed but "
+                          "planes array not provided\n");
+               return -EINVAL;
+       }
+
+       if (b->length < vb->num_planes || b->length > VB2_MAX_PLANES) {
+               dprintk(1, "incorrect planes array length, "
+                          "expected %d, got %d\n", vb->num_planes, b->length);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * __verify_length() - Verify that the bytesused value for each plane fits in
+ * the plane length and that the data offset doesn't exceed the bytesused value.
+ */
+static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+       unsigned int length;
+       unsigned int bytesused;
+       unsigned int plane;
+
+       if (!V4L2_TYPE_IS_OUTPUT(b->type))
+               return 0;
+
+       if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+               for (plane = 0; plane < vb->num_planes; ++plane) {
+                       length = (b->memory == VB2_MEMORY_USERPTR ||
+                                 b->memory == VB2_MEMORY_DMABUF)
+                              ? b->m.planes[plane].length
+                               : vb->planes[plane].length;
+                       bytesused = b->m.planes[plane].bytesused
+                                 ? b->m.planes[plane].bytesused : length;
+
+                       if (b->m.planes[plane].bytesused > length)
+                               return -EINVAL;
+
+                       if (b->m.planes[plane].data_offset > 0 &&
+                           b->m.planes[plane].data_offset >= bytesused)
+                               return -EINVAL;
+               }
+       } else {
+               length = (b->memory == VB2_MEMORY_USERPTR)
+                       ? b->length : vb->planes[0].length;
+
+               if (b->bytesused > length)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int __set_timestamp(struct vb2_buffer *vb, const void *pb)
+{
+       const struct v4l2_buffer *b = pb;
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct vb2_queue *q = vb->vb2_queue;
+
+       if (q->is_output) {
+               /*
+                * For output buffers copy the timestamp if needed,
+                * and the timecode field and flag if needed.
+                */
+               if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+                               V4L2_BUF_FLAG_TIMESTAMP_COPY)
+                       vbuf->timestamp = b->timestamp;
+               vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
+               if (b->flags & V4L2_BUF_FLAG_TIMECODE)
+                       vbuf->timecode = b->timecode;
+       }
+       return 0;
+};
+
+static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
+{
+       static bool check_once;
+
+       if (check_once)
+               return;
+
+       check_once = true;
+       WARN_ON(1);
+
+       pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n");
+       if (vb->vb2_queue->allow_zero_bytesused)
+               pr_warn("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n");
+       else
+               pr_warn("use the actual size instead.\n");
+}
+
+static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
+                                   const char *opname)
+{
+       if (b->type != q->type) {
+               dprintk(1, "%s: invalid buffer type\n", opname);
+               return -EINVAL;
+       }
+
+       if (b->index >= q->num_buffers) {
+               dprintk(1, "%s: buffer index out of range\n", opname);
+               return -EINVAL;
+       }
+
+       if (q->bufs[b->index] == NULL) {
+               /* Should never happen */
+               dprintk(1, "%s: buffer is NULL\n", opname);
+               return -EINVAL;
+       }
+
+       if (b->memory != q->memory) {
+               dprintk(1, "%s: invalid memory type\n", opname);
+               return -EINVAL;
+       }
+
+       return __verify_planes_array(q->bufs[b->index], b);
+}
+
+/**
+ * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
+ * returned to userspace
+ */
+static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
+{
+       struct v4l2_buffer *b = pb;
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct vb2_queue *q = vb->vb2_queue;
+       unsigned int plane;
+
+       /* Copy back data such as timestamp, flags, etc. */
+       b->index = vb->index;
+       b->type = vb->type;
+       b->memory = vb->memory;
+       b->bytesused = 0;
+
+       b->flags = vbuf->flags;
+       b->field = vbuf->field;
+       b->timestamp = vbuf->timestamp;
+       b->timecode = vbuf->timecode;
+       b->sequence = vbuf->sequence;
+       b->reserved2 = 0;
+       b->reserved = 0;
+
+       if (q->is_multiplanar) {
+               /*
+                * Fill in plane-related data if userspace provided an array
+                * for it. The caller has already verified memory and size.
+                */
+               b->length = vb->num_planes;
+               for (plane = 0; plane < vb->num_planes; ++plane) {
+                       struct v4l2_plane *pdst = &b->m.planes[plane];
+                       struct vb2_plane *psrc = &vb->planes[plane];
+
+                       pdst->bytesused = psrc->bytesused;
+                       pdst->length = psrc->length;
+                       if (q->memory == VB2_MEMORY_MMAP)
+                               pdst->m.mem_offset = psrc->m.offset;
+                       else if (q->memory == VB2_MEMORY_USERPTR)
+                               pdst->m.userptr = psrc->m.userptr;
+                       else if (q->memory == VB2_MEMORY_DMABUF)
+                               pdst->m.fd = psrc->m.fd;
+                       pdst->data_offset = psrc->data_offset;
+                       memset(pdst->reserved, 0, sizeof(pdst->reserved));
+               }
+       } else {
+               /*
+                * We use length and offset in v4l2_planes array even for
+                * single-planar buffers, but userspace does not.
+                */
+               b->length = vb->planes[0].length;
+               b->bytesused = vb->planes[0].bytesused;
+               if (q->memory == VB2_MEMORY_MMAP)
+                       b->m.offset = vb->planes[0].m.offset;
+               else if (q->memory == VB2_MEMORY_USERPTR)
+                       b->m.userptr = vb->planes[0].m.userptr;
+               else if (q->memory == VB2_MEMORY_DMABUF)
+                       b->m.fd = vb->planes[0].m.fd;
+       }
+
+       /*
+        * Clear any buffer state related flags.
+        */
+       b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
+       b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
+       if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
+           V4L2_BUF_FLAG_TIMESTAMP_COPY) {
+               /*
+                * For non-COPY timestamps, drop timestamp source bits
+                * and obtain the timestamp source from the queue.
+                */
+               b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+               b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+       }
+
+       switch (vb->state) {
+       case VB2_BUF_STATE_QUEUED:
+       case VB2_BUF_STATE_ACTIVE:
+               b->flags |= V4L2_BUF_FLAG_QUEUED;
+               break;
+       case VB2_BUF_STATE_ERROR:
+               b->flags |= V4L2_BUF_FLAG_ERROR;
+               /* fall through */
+       case VB2_BUF_STATE_DONE:
+               b->flags |= V4L2_BUF_FLAG_DONE;
+               break;
+       case VB2_BUF_STATE_PREPARED:
+               b->flags |= V4L2_BUF_FLAG_PREPARED;
+               break;
+       case VB2_BUF_STATE_PREPARING:
+       case VB2_BUF_STATE_DEQUEUED:
+       case VB2_BUF_STATE_REQUEUEING:
+               /* nothing */
+               break;
+       }
+
+       if (vb2_buffer_in_use(q, vb))
+               b->flags |= V4L2_BUF_FLAG_MAPPED;
+
+       return 0;
+}
+
+/**
+ * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
+ * v4l2_buffer by the userspace. It also verifies that struct
+ * v4l2_buffer has a valid number of planes.
+ */
+static int __fill_vb2_buffer(struct vb2_buffer *vb,
+               const void *pb, struct vb2_plane *planes)
+{
+       struct vb2_queue *q = vb->vb2_queue;
+       const struct v4l2_buffer *b = pb;
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       unsigned int plane;
+       int ret;
+
+       ret = __verify_length(vb, b);
+       if (ret < 0) {
+               dprintk(1, "plane parameters verification failed: %d\n", ret);
+               return ret;
+       }
+       if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
+               /*
+                * If the format's field is ALTERNATE, then the buffer's field
+                * should be either TOP or BOTTOM, not ALTERNATE since that
+                * makes no sense. The driver has to know whether the
+                * buffer represents a top or a bottom field in order to
+                * program any DMA correctly. Using ALTERNATE is wrong, since
+                * that just says that it is either a top or a bottom field,
+                * but not which of the two it is.
+                */
+               dprintk(1, "the field is incorrectly set to ALTERNATE "
+                                       "for an output buffer\n");
+               return -EINVAL;
+       }
+       vbuf->timestamp.tv_sec = 0;
+       vbuf->timestamp.tv_usec = 0;
+       vbuf->sequence = 0;
+
+       if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+               if (b->memory == VB2_MEMORY_USERPTR) {
+                       for (plane = 0; plane < vb->num_planes; ++plane) {
+                               planes[plane].m.userptr =
+                                       b->m.planes[plane].m.userptr;
+                               planes[plane].length =
+                                       b->m.planes[plane].length;
+                       }
+               }
+               if (b->memory == VB2_MEMORY_DMABUF) {
+                       for (plane = 0; plane < vb->num_planes; ++plane) {
+                               planes[plane].m.fd =
+                                       b->m.planes[plane].m.fd;
+                               planes[plane].length =
+                                       b->m.planes[plane].length;
+                       }
+               }
+
+               /* Fill in driver-provided information for OUTPUT types */
+               if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+                       /*
+                        * Will have to go up to b->length when API starts
+                        * accepting variable number of planes.
+                        *
+                        * If bytesused == 0 for the output buffer, then fall
+                        * back to the full buffer size. In that case
+                        * userspace clearly never bothered to set it and
+                        * it's a safe assumption that they really meant to
+                        * use the full plane sizes.
+                        *
+                        * Some drivers, e.g. old codec drivers, use bytesused == 0
+                        * as a way to indicate that streaming is finished.
+                        * In that case, the driver should use the
+                        * allow_zero_bytesused flag to keep old userspace
+                        * applications working.
+                        */
+                       for (plane = 0; plane < vb->num_planes; ++plane) {
+                               struct vb2_plane *pdst = &planes[plane];
+                               struct v4l2_plane *psrc = &b->m.planes[plane];
+
+                               if (psrc->bytesused == 0)
+                                       vb2_warn_zero_bytesused(vb);
+
+                               if (vb->vb2_queue->allow_zero_bytesused)
+                                       pdst->bytesused = psrc->bytesused;
+                               else
+                                       pdst->bytesused = psrc->bytesused ?
+                                               psrc->bytesused : pdst->length;
+                               pdst->data_offset = psrc->data_offset;
+                       }
+               }
+       } else {
+               /*
+                * Single-planar buffers do not use planes array,
+                * so fill in relevant v4l2_buffer struct fields instead.
+                * In videobuf we use our internal V4l2_planes struct for
+                * single-planar buffers as well, for simplicity.
+                *
+                * If bytesused == 0 for the output buffer, then fall back
+                * to the full buffer size as that's a sensible default.
+                *
+                * Some drivers, e.g. old codec drivers, use bytesused == 0 as
+                * a way to indicate that streaming is finished. In that case,
+                * the driver should use the allow_zero_bytesused flag to keep
+                * old userspace applications working.
+                */
+               if (b->memory == VB2_MEMORY_USERPTR) {
+                       planes[0].m.userptr = b->m.userptr;
+                       planes[0].length = b->length;
+               }
+
+               if (b->memory == VB2_MEMORY_DMABUF) {
+                       planes[0].m.fd = b->m.fd;
+                       planes[0].length = b->length;
+               }
+
+               if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+                       if (b->bytesused == 0)
+                               vb2_warn_zero_bytesused(vb);
+
+                       if (vb->vb2_queue->allow_zero_bytesused)
+                               planes[0].bytesused = b->bytesused;
+                       else
+                               planes[0].bytesused = b->bytesused ?
+                                       b->bytesused : planes[0].length;
+               } else
+                       planes[0].bytesused = 0;
+
+       }
+
+       /* Zero flags that the vb2 core handles */
+       vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
+       if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
+           V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
+               /*
+                * Non-COPY timestamps and non-OUTPUT queues will get
+                * their timestamp and timestamp source flags from the
+                * queue.
+                */
+               vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+       }
+
+       if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+               /*
+                * For output buffers mask out the timecode flag:
+                * this will be handled later in vb2_internal_qbuf().
+                * The 'field' is valid metadata for this output buffer
+                * and so that needs to be copied here.
+                */
+               vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
+               vbuf->field = b->field;
+       } else {
+               /* Zero any output buffer flags as this is a capture buffer */
+               vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
+       }
+
+       return 0;
+}
+
+static const struct vb2_buf_ops v4l2_buf_ops = {
+       .fill_user_buffer       = __fill_v4l2_buffer,
+       .fill_vb2_buffer        = __fill_vb2_buffer,
+       .set_timestamp          = __set_timestamp,
+};
+
+/**
+ * vb2_querybuf() - query video buffer information
+ * @q:         videobuf queue
+ * @b:         buffer struct passed from userspace to vidioc_querybuf handler
+ *             in driver
+ *
+ * Should be called from vidioc_querybuf ioctl handler in driver.
+ * This function will verify the passed v4l2_buffer structure and fill the
+ * relevant information for the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_querybuf handler in driver.
+ */
+int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+       struct vb2_buffer *vb;
+       int ret;
+
+       if (b->type != q->type) {
+               dprintk(1, "wrong buffer type\n");
+               return -EINVAL;
+       }
+
+       if (b->index >= q->num_buffers) {
+               dprintk(1, "buffer index out of range\n");
+               return -EINVAL;
+       }
+       vb = q->bufs[b->index];
+       ret = __verify_planes_array(vb, b);
+
+       return ret ? ret : vb2_core_querybuf(q, b->index, b);
+}
+EXPORT_SYMBOL(vb2_querybuf);
+
+/**
+ * vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies
+ * the memory and type values.
+ * @q:         videobuf2 queue
+ * @req:       struct passed from userspace to vidioc_reqbufs handler
+ *             in driver
+ */
+int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
+{
+       int ret = vb2_verify_memory_type(q, req->memory, req->type);
+
+       return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count);
+}
+EXPORT_SYMBOL_GPL(vb2_reqbufs);
+
+/**
+ * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
+ * @q:         videobuf2 queue
+ * @b:         buffer structure passed from userspace to vidioc_prepare_buf
+ *             handler in driver
+ *
+ * Should be called from vidioc_prepare_buf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) calls buf_prepare callback in the driver (if provided), in which
+ *    driver-specific buffer initialization can be performed,
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_prepare_buf handler in driver.
+ */
+int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+       int ret;
+
+       if (vb2_fileio_is_active(q)) {
+               dprintk(1, "file io in progress\n");
+               return -EBUSY;
+       }
+
+       ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
+
+       return ret ? ret : vb2_core_prepare_buf(q, b->index, b);
+}
+EXPORT_SYMBOL_GPL(vb2_prepare_buf);
+
+/**
+ * vb2_create_bufs() - Wrapper for vb2_core_create_bufs() that also verifies
+ * the memory and type values.
+ * @q:         videobuf2 queue
+ * @create:    creation parameters, passed from userspace to vidioc_create_bufs
+ *             handler in driver
+ */
+int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
+{
+       int ret = vb2_verify_memory_type(q, create->memory,
+                       create->format.type);
+
+       create->index = q->num_buffers;
+       if (create->count == 0)
+               return ret != -EBUSY ? ret : 0;
+       return ret ? ret : vb2_core_create_bufs(q, create->memory,
+               &create->count, &create->format);
+}
+EXPORT_SYMBOL_GPL(vb2_create_bufs);
+
+static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+       int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
+
+       return ret ? ret : vb2_core_qbuf(q, b->index, b);
+}
+
+/**
+ * vb2_qbuf() - Queue a buffer from userspace
+ * @q:         videobuf2 queue
+ * @b:         buffer structure passed from userspace to vidioc_qbuf handler
+ *             in driver
+ *
+ * Should be called from vidioc_qbuf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
+ *    which driver-specific buffer initialization can be performed,
+ * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
+ *    callback for processing.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_qbuf handler in driver.
+ */
+int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+       if (vb2_fileio_is_active(q)) {
+               dprintk(1, "file io in progress\n");
+               return -EBUSY;
+       }
+
+       return vb2_internal_qbuf(q, b);
+}
+EXPORT_SYMBOL_GPL(vb2_qbuf);
+
+static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
+               bool nonblocking)
+{
+       int ret;
+
+       if (b->type != q->type) {
+               dprintk(1, "invalid buffer type\n");
+               return -EINVAL;
+       }
+
+       ret = vb2_core_dqbuf(q, b, nonblocking);
+
+       if (!ret && !q->is_output &&
+                       b->flags & V4L2_BUF_FLAG_LAST)
+               q->last_buffer_dequeued = true;
+
+       return ret;
+}
+
+/**
+ * vb2_dqbuf() - Dequeue a buffer to the userspace
+ * @q:         videobuf2 queue
+ * @b:         buffer structure passed from userspace to vidioc_dqbuf handler
+ *             in driver
+ * @nonblocking: if true, this call will not sleep waiting for a buffer if no
+ *              buffers ready for dequeuing are present. Normally the driver
+ *              would be passing (file->f_flags & O_NONBLOCK) here
+ *
+ * Should be called from vidioc_dqbuf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) calls buf_finish callback in the driver (if provided), in which
+ *    driver can perform any additional operations that may be required before
+ *    returning the buffer to userspace, such as cache sync,
+ * 3) the buffer struct members are filled with relevant information for
+ *    the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_dqbuf handler in driver.
+ */
+int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
+{
+       if (vb2_fileio_is_active(q)) {
+               dprintk(1, "file io in progress\n");
+               return -EBUSY;
+       }
+       return vb2_internal_dqbuf(q, b, nonblocking);
+}
+EXPORT_SYMBOL_GPL(vb2_dqbuf);
+
+/**
+ * vb2_streamon - start streaming
+ * @q:         videobuf2 queue
+ * @type:      type argument passed from userspace to vidioc_streamon handler
+ *
+ * Should be called from vidioc_streamon handler of a driver.
+ * This function:
+ * 1) verifies current state
+ * 2) passes any previously queued buffers to the driver and starts streaming
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_streamon handler in the driver.
+ */
+int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+       if (vb2_fileio_is_active(q)) {
+               dprintk(1, "file io in progress\n");
+               return -EBUSY;
+       }
+       return vb2_core_streamon(q, type);
+}
+EXPORT_SYMBOL_GPL(vb2_streamon);
+
+/**
+ * vb2_streamoff - stop streaming
+ * @q:         videobuf2 queue
+ * @type:      type argument passed from userspace to vidioc_streamoff handler
+ *
+ * Should be called from vidioc_streamoff handler of a driver.
+ * This function:
+ * 1) verifies current state,
+ * 2) stop streaming and dequeues any queued buffers, including those previously
+ *    passed to the driver (after waiting for the driver to finish).
+ *
+ * This call can be used for pausing playback.
+ * The return values from this function are intended to be directly returned
+ * from vidioc_streamoff handler in the driver
+ */
+int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+       if (vb2_fileio_is_active(q)) {
+               dprintk(1, "file io in progress\n");
+               return -EBUSY;
+       }
+       return vb2_core_streamoff(q, type);
+}
+EXPORT_SYMBOL_GPL(vb2_streamoff);
+
+/**
+ * vb2_expbuf() - Export a buffer as a file descriptor
+ * @q:         videobuf2 queue
+ * @eb:                export buffer structure passed from userspace to vidioc_expbuf
+ *             handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_expbuf handler in driver.
+ */
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+{
+       return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index,
+                               eb->plane, eb->flags);
+}
+EXPORT_SYMBOL_GPL(vb2_expbuf);
+
+/**
+ * vb2_queue_init() - initialize a videobuf2 queue
+ * @q:         videobuf2 queue; this structure should be allocated in driver
+ *
+ * The vb2_queue structure should be allocated by the driver. The driver is
+ * responsible of clearing it's content and setting initial values for some
+ * required entries before calling this function.
+ * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
+ * to the struct vb2_queue description in include/media/videobuf2-core.h
+ * for more information.
+ */
+int vb2_queue_init(struct vb2_queue *q)
+{
+       /*
+        * Sanity check
+        */
+       if (WARN_ON(!q)                   ||
+           WARN_ON(q->timestamp_flags &
+                   ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
+                     V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
+               return -EINVAL;
+
+       /* Warn that the driver should choose an appropriate timestamp type */
+       WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+               V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
+
+       /* Warn that vb2_memory should match with v4l2_memory */
+       if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
+               || WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
+               || WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
+               return -EINVAL;
+
+       if (q->buf_struct_size == 0)
+               q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
+
+       q->buf_ops = &v4l2_buf_ops;
+       q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
+       q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
+
+       return vb2_core_queue_init(q);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_init);
+
+static int __vb2_init_fileio(struct vb2_queue *q, int read);
+static int __vb2_cleanup_fileio(struct vb2_queue *q);
+
+/**
+ * vb2_queue_release() - stop streaming, release the queue and free memory
+ * @q:         videobuf2 queue
+ *
+ * This function stops streaming and performs necessary clean ups, including
+ * freeing video buffer memory. The driver is responsible for freeing
+ * the vb2_queue structure itself.
+ */
+void vb2_queue_release(struct vb2_queue *q)
+{
+       __vb2_cleanup_fileio(q);
+       vb2_core_queue_release(q);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_release);
+
+/**
+ * vb2_poll() - implements poll userspace operation
+ * @q:         videobuf2 queue
+ * @file:      file argument passed to the poll file operation handler
+ * @wait:      wait argument passed to the poll file operation handler
+ *
+ * This function implements poll file operation handler for a driver.
+ * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
+ * be informed that the file descriptor of a video device is available for
+ * reading.
+ * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
+ * will be reported as available for writing.
+ *
+ * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
+ * pending events.
+ *
+ * The return values from this function are intended to be directly returned
+ * from poll handler in driver.
+ */
+unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
+{
+       struct video_device *vfd = video_devdata(file);
+       unsigned long req_events = poll_requested_events(wait);
+       struct vb2_buffer *vb = NULL;
+       unsigned int res = 0;
+       unsigned long flags;
+
+       if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
+               struct v4l2_fh *fh = file->private_data;
+
+               if (v4l2_event_pending(fh))
+                       res = POLLPRI;
+               else if (req_events & POLLPRI)
+                       poll_wait(file, &fh->wait, wait);
+       }
+
+       if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
+               return res;
+       if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
+               return res;
+
+       /*
+        * Start file I/O emulator only if streaming API has not been used yet.
+        */
+       if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
+               if (!q->is_output && (q->io_modes & VB2_READ) &&
+                               (req_events & (POLLIN | POLLRDNORM))) {
+                       if (__vb2_init_fileio(q, 1))
+                               return res | POLLERR;
+               }
+               if (q->is_output && (q->io_modes & VB2_WRITE) &&
+                               (req_events & (POLLOUT | POLLWRNORM))) {
+                       if (__vb2_init_fileio(q, 0))
+                               return res | POLLERR;
+                       /*
+                        * Write to OUTPUT queue can be done immediately.
+                        */
+                       return res | POLLOUT | POLLWRNORM;
+               }
+       }
+
+       /*
+        * There is nothing to wait for if the queue isn't streaming, or if the
+        * error flag is set.
+        */
+       if (!vb2_is_streaming(q) || q->error)
+               return res | POLLERR;
+       /*
+        * For compatibility with vb1: if QBUF hasn't been called yet, then
+        * return POLLERR as well. This only affects capture queues, output
+        * queues will always initialize waiting_for_buffers to false.
+        */
+       if (q->waiting_for_buffers)
+               return res | POLLERR;
+
+       /*
+        * For output streams you can write as long as there are fewer buffers
+        * queued than there are buffers available.
+        */
+       if (q->is_output && q->queued_count < q->num_buffers)
+               return res | POLLOUT | POLLWRNORM;
+
+       if (list_empty(&q->done_list)) {
+               /*
+                * If the last buffer was dequeued from a capture queue,
+                * return immediately. DQBUF will return -EPIPE.
+                */
+               if (q->last_buffer_dequeued)
+                       return res | POLLIN | POLLRDNORM;
+
+               poll_wait(file, &q->done_wq, wait);
+       }
+
+       /*
+        * Take first buffer available for dequeuing.
+        */
+       spin_lock_irqsave(&q->done_lock, flags);
+       if (!list_empty(&q->done_list))
+               vb = list_first_entry(&q->done_list, struct vb2_buffer,
+                                       done_entry);
+       spin_unlock_irqrestore(&q->done_lock, flags);
+
+       if (vb && (vb->state == VB2_BUF_STATE_DONE
+                       || vb->state == VB2_BUF_STATE_ERROR)) {
+               return (q->is_output) ?
+                               res | POLLOUT | POLLWRNORM :
+                               res | POLLIN | POLLRDNORM;
+       }
+       return res;
+}
+EXPORT_SYMBOL_GPL(vb2_poll);
+
+/**
+ * struct vb2_fileio_buf - buffer context used by file io emulator
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. This structure is used for
+ * tracking context related to the buffers.
+ */
+struct vb2_fileio_buf {
+       void *vaddr;
+       unsigned int size;
+       unsigned int pos;
+       unsigned int queued:1;
+};
+
+/**
+ * struct vb2_fileio_data - queue context used by file io emulator
+ *
+ * @cur_index: the index of the buffer currently being read from or
+ *             written to. If equal to q->num_buffers then a new buffer
+ *             must be dequeued.
+ * @initial_index: in the read() case all buffers are queued up immediately
+ *             in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
+ *             buffers. However, in the write() case no buffers are initially
+ *             queued, instead whenever a buffer is full it is queued up by
+ *             __vb2_perform_fileio(). Only once all available buffers have
+ *             been queued up will __vb2_perform_fileio() start to dequeue
+ *             buffers. This means that initially __vb2_perform_fileio()
+ *             needs to know what buffer index to use when it is queuing up
+ *             the buffers for the first time. That initial index is stored
+ *             in this field. Once it is equal to q->num_buffers all
+ *             available buffers have been queued and __vb2_perform_fileio()
+ *             should start the normal dequeue/queue cycle.
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. For proper operation it required
+ * this structure to save the driver state between each call of the read
+ * or write function.
+ */
+struct vb2_fileio_data {
+       struct v4l2_requestbuffers req;
+       struct v4l2_plane p;
+       struct v4l2_buffer b;
+       struct vb2_fileio_buf bufs[VB2_MAX_FRAME];
+       unsigned int cur_index;
+       unsigned int initial_index;
+       unsigned int q_count;
+       unsigned int dq_count;
+       unsigned read_once:1;
+       unsigned write_immediately:1;
+};
+
+/**
+ * __vb2_init_fileio() - initialize file io emulator
+ * @q:         videobuf2 queue
+ * @read:      mode selector (1 means read, 0 means write)
+ */
+static int __vb2_init_fileio(struct vb2_queue *q, int read)
+{
+       struct vb2_fileio_data *fileio;
+       int i, ret;
+       unsigned int count = 0;
+
+       /*
+        * Sanity check
+        */
+       if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
+                   (!read && !(q->io_modes & VB2_WRITE))))
+               return -EINVAL;
+
+       /*
+        * Check if device supports mapping buffers to kernel virtual space.
+        */
+       if (!q->mem_ops->vaddr)
+               return -EBUSY;
+
+       /*
+        * Check if streaming api has not been already activated.
+        */
+       if (q->streaming || q->num_buffers > 0)
+               return -EBUSY;
+
+       /*
+        * Start with count 1, driver can increase it in queue_setup()
+        */
+       count = 1;
+
+       dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
+               (read) ? "read" : "write", count, q->fileio_read_once,
+               q->fileio_write_immediately);
+
+       fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
+       if (fileio == NULL)
+               return -ENOMEM;
+
+       fileio->read_once = q->fileio_read_once;
+       fileio->write_immediately = q->fileio_write_immediately;
+
+       /*
+        * Request buffers and use MMAP type to force driver
+        * to allocate buffers by itself.
+        */
+       fileio->req.count = count;
+       fileio->req.memory = VB2_MEMORY_MMAP;
+       fileio->req.type = q->type;
+       q->fileio = fileio;
+       ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
+       if (ret)
+               goto err_kfree;
+
+       /*
+        * Check if plane_count is correct
+        * (multiplane buffers are not supported).
+        */
+       if (q->bufs[0]->num_planes != 1) {
+               ret = -EBUSY;
+               goto err_reqbufs;
+       }
+
+       /*
+        * Get kernel address of each buffer.
+        */
+       for (i = 0; i < q->num_buffers; i++) {
+               fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+               if (fileio->bufs[i].vaddr == NULL) {
+                       ret = -EINVAL;
+                       goto err_reqbufs;
+               }
+               fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
+       }
+
+       /*
+        * Read mode requires pre queuing of all buffers.
+        */
+       if (read) {
+               bool is_multiplanar = q->is_multiplanar;
+
+               /*
+                * Queue all buffers.
+                */
+               for (i = 0; i < q->num_buffers; i++) {
+                       struct v4l2_buffer *b = &fileio->b;
+
+                       memset(b, 0, sizeof(*b));
+                       b->type = q->type;
+                       if (is_multiplanar) {
+                               memset(&fileio->p, 0, sizeof(fileio->p));
+                               b->m.planes = &fileio->p;
+                               b->length = 1;
+                       }
+                       b->memory = q->memory;
+                       b->index = i;
+                       ret = vb2_internal_qbuf(q, b);
+                       if (ret)
+                               goto err_reqbufs;
+                       fileio->bufs[i].queued = 1;
+               }
+               /*
+                * All buffers have been queued, so mark that by setting
+                * initial_index to q->num_buffers
+                */
+               fileio->initial_index = q->num_buffers;
+               fileio->cur_index = q->num_buffers;
+       }
+
+       /*
+        * Start streaming.
+        */
+       ret = vb2_core_streamon(q, q->type);
+       if (ret)
+               goto err_reqbufs;
+
+       return ret;
+
+err_reqbufs:
+       fileio->req.count = 0;
+       vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
+
+err_kfree:
+       q->fileio = NULL;
+       kfree(fileio);
+       return ret;
+}
+
+/**
+ * __vb2_cleanup_fileio() - free resourced used by file io emulator
+ * @q:         videobuf2 queue
+ */
+static int __vb2_cleanup_fileio(struct vb2_queue *q)
+{
+       struct vb2_fileio_data *fileio = q->fileio;
+
+       if (fileio) {
+               vb2_core_streamoff(q, q->type);
+               q->fileio = NULL;
+               fileio->req.count = 0;
+               vb2_reqbufs(q, &fileio->req);
+               kfree(fileio);
+               dprintk(3, "file io emulator closed\n");
+       }
+       return 0;
+}
+
+/**
+ * __vb2_perform_fileio() - perform a single file io (read or write) operation
+ * @q:         videobuf2 queue
+ * @data:      pointed to target userspace buffer
+ * @count:     number of bytes to read or write
+ * @ppos:      file handle position tracking pointer
+ * @nonblock:  mode selector (1 means blocking calls, 0 means nonblocking)
+ * @read:      access mode selector (1 means read, 0 means write)
+ */
+static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
+               loff_t *ppos, int nonblock, int read)
+{
+       struct vb2_fileio_data *fileio;
+       struct vb2_fileio_buf *buf;
+       bool is_multiplanar = q->is_multiplanar;
+       /*
+        * When using write() to write data to an output video node the vb2 core
+        * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
+        * else is able to provide this information with the write() operation.
+        */
+       bool set_timestamp = !read &&
+               (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+               V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       int ret, index;
+
+       dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
+               read ? "read" : "write", (long)*ppos, count,
+               nonblock ? "non" : "");
+
+       if (!data)
+               return -EINVAL;
+
+       /*
+        * Initialize emulator on first call.
+        */
+       if (!vb2_fileio_is_active(q)) {
+               ret = __vb2_init_fileio(q, read);
+               dprintk(3, "vb2_init_fileio result: %d\n", ret);
+               if (ret)
+                       return ret;
+       }
+       fileio = q->fileio;
+
+       /*
+        * Check if we need to dequeue the buffer.
+        */
+       index = fileio->cur_index;
+       if (index >= q->num_buffers) {
+               /*
+                * Call vb2_dqbuf to get buffer back.
+                */
+               memset(&fileio->b, 0, sizeof(fileio->b));
+               fileio->b.type = q->type;
+               fileio->b.memory = q->memory;
+               if (is_multiplanar) {
+                       memset(&fileio->p, 0, sizeof(fileio->p));
+                       fileio->b.m.planes = &fileio->p;
+                       fileio->b.length = 1;
+               }
+               ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
+               dprintk(5, "vb2_dqbuf result: %d\n", ret);
+               if (ret)
+                       return ret;
+               fileio->dq_count += 1;
+
+               fileio->cur_index = index = fileio->b.index;
+               buf = &fileio->bufs[index];
+
+               /*
+                * Get number of bytes filled by the driver
+                */
+               buf->pos = 0;
+               buf->queued = 0;
+               buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
+                                : vb2_plane_size(q->bufs[index], 0);
+               /* Compensate for data_offset on read in the multiplanar case. */
+               if (is_multiplanar && read &&
+                   fileio->b.m.planes[0].data_offset < buf->size) {
+                       buf->pos = fileio->b.m.planes[0].data_offset;
+                       buf->size -= buf->pos;
+               }
+       } else {
+               buf = &fileio->bufs[index];
+       }
+
+       /*
+        * Limit count on last few bytes of the buffer.
+        */
+       if (buf->pos + count > buf->size) {
+               count = buf->size - buf->pos;
+               dprintk(5, "reducing read count: %zd\n", count);
+       }
+
+       /*
+        * Transfer data to userspace.
+        */
+       dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
+               count, index, buf->pos);
+       if (read)
+               ret = copy_to_user(data, buf->vaddr + buf->pos, count);
+       else
+               ret = copy_from_user(buf->vaddr + buf->pos, data, count);
+       if (ret) {
+               dprintk(3, "error copying data\n");
+               return -EFAULT;
+       }
+
+       /*
+        * Update counters.
+        */
+       buf->pos += count;
+       *ppos += count;
+
+       /*
+        * Queue next buffer if required.
+        */
+       if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
+               /*
+                * Check if this is the last buffer to read.
+                */
+               if (read && fileio->read_once && fileio->dq_count == 1) {
+                       dprintk(3, "read limit reached\n");
+                       return __vb2_cleanup_fileio(q);
+               }
+
+               /*
+                * Call vb2_qbuf and give buffer to the driver.
+                */
+               memset(&fileio->b, 0, sizeof(fileio->b));
+               fileio->b.type = q->type;
+               fileio->b.memory = q->memory;
+               fileio->b.index = index;
+               fileio->b.bytesused = buf->pos;
+               if (is_multiplanar) {
+                       memset(&fileio->p, 0, sizeof(fileio->p));
+                       fileio->p.bytesused = buf->pos;
+                       fileio->b.m.planes = &fileio->p;
+                       fileio->b.length = 1;
+               }
+               if (set_timestamp)
+                       v4l2_get_timestamp(&fileio->b.timestamp);
+               ret = vb2_internal_qbuf(q, &fileio->b);
+               dprintk(5, "vb2_dbuf result: %d\n", ret);
+               if (ret)
+                       return ret;
+
+               /*
+                * Buffer has been queued, update the status
+                */
+               buf->pos = 0;
+               buf->queued = 1;
+               buf->size = vb2_plane_size(q->bufs[index], 0);
+               fileio->q_count += 1;
+               /*
+                * If we are queuing up buffers for the first time, then
+                * increase initial_index by one.
+                */
+               if (fileio->initial_index < q->num_buffers)
+                       fileio->initial_index++;
+               /*
+                * The next buffer to use is either a buffer that's going to be
+                * queued for the first time (initial_index < q->num_buffers)
+                * or it is equal to q->num_buffers, meaning that the next
+                * time we need to dequeue a buffer since we've now queued up
+                * all the 'first time' buffers.
+                */
+               fileio->cur_index = fileio->initial_index;
+       }
+
+       /*
+        * Return proper number of bytes processed.
+        */
+       if (ret == 0)
+               ret = count;
+       return ret;
+}
+
+size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+               loff_t *ppos, int nonblocking)
+{
+       return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
+}
+EXPORT_SYMBOL_GPL(vb2_read);
+
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
+               loff_t *ppos, int nonblocking)
+{
+       return __vb2_perform_fileio(q, (char __user *) data, count,
+                                                       ppos, nonblocking, 0);
+}
+EXPORT_SYMBOL_GPL(vb2_write);
+
+struct vb2_threadio_data {
+       struct task_struct *thread;
+       vb2_thread_fnc fnc;
+       void *priv;
+       bool stop;
+};
+
+static int vb2_thread(void *data)
+{
+       struct vb2_queue *q = data;
+       struct vb2_threadio_data *threadio = q->threadio;
+       struct vb2_fileio_data *fileio = q->fileio;
+       bool set_timestamp = false;
+       int prequeue = 0;
+       int index = 0;
+       int ret = 0;
+
+       if (q->is_output) {
+               prequeue = q->num_buffers;
+               set_timestamp =
+                       (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+                       V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       }
+
+       set_freezable();
+
+       for (;;) {
+               struct vb2_buffer *vb;
+
+               /*
+                * Call vb2_dqbuf to get buffer back.
+                */
+               memset(&fileio->b, 0, sizeof(fileio->b));
+               fileio->b.type = q->type;
+               fileio->b.memory = q->memory;
+               if (prequeue) {
+                       fileio->b.index = index++;
+                       prequeue--;
+               } else {
+                       call_void_qop(q, wait_finish, q);
+                       if (!threadio->stop)
+                               ret = vb2_internal_dqbuf(q, &fileio->b, 0);
+                       call_void_qop(q, wait_prepare, q);
+                       dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
+               }
+               if (ret || threadio->stop)
+                       break;
+               try_to_freeze();
+
+               vb = q->bufs[fileio->b.index];
+               if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
+                       if (threadio->fnc(vb, threadio->priv))
+                               break;
+               call_void_qop(q, wait_finish, q);
+               if (set_timestamp)
+                       v4l2_get_timestamp(&fileio->b.timestamp);
+               if (!threadio->stop)
+                       ret = vb2_internal_qbuf(q, &fileio->b);
+               call_void_qop(q, wait_prepare, q);
+               if (ret || threadio->stop)
+                       break;
+       }
+
+       /* Hmm, linux becomes *very* unhappy without this ... */
+       while (!kthread_should_stop()) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+       }
+       return 0;
+}
+
+/*
+ * This function should not be used for anything else but the videobuf2-dvb
+ * support. If you think you have another good use-case for this, then please
+ * contact the linux-media mailinglist first.
+ */
+int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
+                    const char *thread_name)
+{
+       struct vb2_threadio_data *threadio;
+       int ret = 0;
+
+       if (q->threadio)
+               return -EBUSY;
+       if (vb2_is_busy(q))
+               return -EBUSY;
+       if (WARN_ON(q->fileio))
+               return -EBUSY;
+
+       threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
+       if (threadio == NULL)
+               return -ENOMEM;
+       threadio->fnc = fnc;
+       threadio->priv = priv;
+
+       ret = __vb2_init_fileio(q, !q->is_output);
+       dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
+       if (ret)
+               goto nomem;
+       q->threadio = threadio;
+       threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
+       if (IS_ERR(threadio->thread)) {
+               ret = PTR_ERR(threadio->thread);
+               threadio->thread = NULL;
+               goto nothread;
+       }
+       return 0;
+
+nothread:
+       __vb2_cleanup_fileio(q);
+nomem:
+       kfree(threadio);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_thread_start);
+
+int vb2_thread_stop(struct vb2_queue *q)
+{
+       struct vb2_threadio_data *threadio = q->threadio;
+       int err;
+
+       if (threadio == NULL)
+               return 0;
+       threadio->stop = true;
+       /* Wake up all pending sleeps in the thread */
+       vb2_queue_error(q);
+       err = kthread_stop(threadio->thread);
+       __vb2_cleanup_fileio(q);
+       threadio->thread = NULL;
+       kfree(threadio);
+       q->threadio = NULL;
+       return err;
+}
+EXPORT_SYMBOL_GPL(vb2_thread_stop);
+
+/*
+ * The following functions are not part of the vb2 core API, but are helper
+ * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
+ * and struct vb2_ops.
+ * They contain boilerplate code that most if not all drivers have to do
+ * and so they simplify the driver code.
+ */
+
+/* The queue is busy if there is a owner and you are not that owner. */
+static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
+{
+       return vdev->queue->owner && vdev->queue->owner != file->private_data;
+}
+
+/* vb2 ioctl helpers */
+
+int vb2_ioctl_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *p)
+{
+       struct video_device *vdev = video_devdata(file);
+       int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
+
+       if (res)
+               return res;
+       if (vb2_queue_is_busy(vdev, file))
+               return -EBUSY;
+       res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count);
+       /* If count == 0, then the owner has released all buffers and he
+          is no longer owner of the queue. Otherwise we have a new owner. */
+       if (res == 0)
+               vdev->queue->owner = p->count ? file->private_data : NULL;
+       return res;
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
+
+int vb2_ioctl_create_bufs(struct file *file, void *priv,
+                         struct v4l2_create_buffers *p)
+{
+       struct video_device *vdev = video_devdata(file);
+       int res = vb2_verify_memory_type(vdev->queue, p->memory,
+                       p->format.type);
+
+       p->index = vdev->queue->num_buffers;
+       /*
+        * If count == 0, then just check if memory and type are valid.
+        * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
+        */
+       if (p->count == 0)
+               return res != -EBUSY ? res : 0;
+       if (res)
+               return res;
+       if (vb2_queue_is_busy(vdev, file))
+               return -EBUSY;
+       res = vb2_core_create_bufs(vdev->queue, p->memory, &p->count,
+                       &p->format);
+       if (res == 0)
+               vdev->queue->owner = file->private_data;
+       return res;
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
+
+int vb2_ioctl_prepare_buf(struct file *file, void *priv,
+                         struct v4l2_buffer *p)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       if (vb2_queue_is_busy(vdev, file))
+               return -EBUSY;
+       return vb2_prepare_buf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
+
+int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       /* No need to call vb2_queue_is_busy(), anyone can query buffers. */
+       return vb2_querybuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
+
+int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       if (vb2_queue_is_busy(vdev, file))
+               return -EBUSY;
+       return vb2_qbuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
+
+int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       if (vb2_queue_is_busy(vdev, file))
+               return -EBUSY;
+       return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
+
+int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       if (vb2_queue_is_busy(vdev, file))
+               return -EBUSY;
+       return vb2_streamon(vdev->queue, i);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
+
+int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       if (vb2_queue_is_busy(vdev, file))
+               return -EBUSY;
+       return vb2_streamoff(vdev->queue, i);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
+
+int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       if (vb2_queue_is_busy(vdev, file))
+               return -EBUSY;
+       return vb2_expbuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
+
+/* v4l2_file_operations helpers */
+
+int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       return vb2_mmap(vdev->queue, vma);
+}
+EXPORT_SYMBOL_GPL(vb2_fop_mmap);
+
+int _vb2_fop_release(struct file *file, struct mutex *lock)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       if (lock)
+               mutex_lock(lock);
+       if (file->private_data == vdev->queue->owner) {
+               vb2_queue_release(vdev->queue);
+               vdev->queue->owner = NULL;
+       }
+       if (lock)
+               mutex_unlock(lock);
+       return v4l2_fh_release(file);
+}
+EXPORT_SYMBOL_GPL(_vb2_fop_release);
+
+int vb2_fop_release(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+
+       return _vb2_fop_release(file, lock);
+}
+EXPORT_SYMBOL_GPL(vb2_fop_release);
+
+ssize_t vb2_fop_write(struct file *file, const char __user *buf,
+               size_t count, loff_t *ppos)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+       int err = -EBUSY;
+
+       if (!(vdev->queue->io_modes & VB2_WRITE))
+               return -EINVAL;
+       if (lock && mutex_lock_interruptible(lock))
+               return -ERESTARTSYS;
+       if (vb2_queue_is_busy(vdev, file))
+               goto exit;
+       err = vb2_write(vdev->queue, buf, count, ppos,
+                      file->f_flags & O_NONBLOCK);
+       if (vdev->queue->fileio)
+               vdev->queue->owner = file->private_data;
+exit:
+       if (lock)
+               mutex_unlock(lock);
+       return err;
+}
+EXPORT_SYMBOL_GPL(vb2_fop_write);
+
+ssize_t vb2_fop_read(struct file *file, char __user *buf,
+               size_t count, loff_t *ppos)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+       int err = -EBUSY;
+
+       if (!(vdev->queue->io_modes & VB2_READ))
+               return -EINVAL;
+       if (lock && mutex_lock_interruptible(lock))
+               return -ERESTARTSYS;
+       if (vb2_queue_is_busy(vdev, file))
+               goto exit;
+       err = vb2_read(vdev->queue, buf, count, ppos,
+                      file->f_flags & O_NONBLOCK);
+       if (vdev->queue->fileio)
+               vdev->queue->owner = file->private_data;
+exit:
+       if (lock)
+               mutex_unlock(lock);
+       return err;
+}
+EXPORT_SYMBOL_GPL(vb2_fop_read);
+
+unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct vb2_queue *q = vdev->queue;
+       struct mutex *lock = q->lock ? q->lock : vdev->lock;
+       unsigned res;
+       void *fileio;
+
+       /*
+        * If this helper doesn't know how to lock, then you shouldn't be using
+        * it but you should write your own.
+        */
+       WARN_ON(!lock);
+
+       if (lock && mutex_lock_interruptible(lock))
+               return POLLERR;
+
+       fileio = q->fileio;
+
+       res = vb2_poll(vdev->queue, file, wait);
+
+       /* If fileio was started, then we have a new queue owner. */
+       if (!fileio && q->fileio)
+               q->owner = file->private_data;
+       if (lock)
+               mutex_unlock(lock);
+       return res;
+}
+EXPORT_SYMBOL_GPL(vb2_fop_poll);
+
+#ifndef CONFIG_MMU
+unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
+               unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
+}
+EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
+#endif
+
+/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
+
+void vb2_ops_wait_prepare(struct vb2_queue *vq)
+{
+       mutex_unlock(vq->lock);
+}
+EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
+
+void vb2_ops_wait_finish(struct vb2_queue *vq)
+{
+       mutex_lock(vq->lock);
+}
+EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
+
 MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
 MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
 MODULE_LICENSE("GPL");
index fbcc1c3e91d5d86df416895dd0ca5beb74b62c8c..0fdff91624fd6d649857f1b71e4fb70ad7382d48 100644 (file)
@@ -1078,7 +1078,7 @@ vpfe_g_dv_timings(struct file *file, void *fh,
  * the buffer nbuffers and buffer size
  */
 static int
-vpfe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+vpfe_buffer_queue_setup(struct vb2_queue *vq, const void *parg,
                        unsigned int *nbuffers, unsigned int *nplanes,
                        unsigned int sizes[], void *alloc_ctxs[])
 {
index 9bfb725b9986ccbe86bc3bf9069d2e9dbb5c524e..0b03cb7c59d5c25c06ff1416ef38e62ba1c08e3d 100644 (file)
@@ -1440,12 +1440,13 @@ static int iss_probe(struct platform_device *pdev)
                 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));
 
        /* Interrupt */
-       iss->irq_num = platform_get_irq(pdev, 0);
-       if (iss->irq_num <= 0) {
+       ret = platform_get_irq(pdev, 0);
+       if (ret <= 0) {
                dev_err(iss->dev, "No IRQ resource\n");
                ret = -ENODEV;
                goto error_iss;
        }
+       iss->irq_num = ret;
 
        if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
                             "OMAP4 ISS", iss)) {
index 72b4ca8934f8341dea76d3a9bbcd77d41025103b..28c067decc27d9c3a695505dde8de3c1536580ab 100644 (file)
@@ -288,7 +288,7 @@ iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh)
  */
 
 static int iss_video_queue_setup(struct vb2_queue *vq,
-                                const struct v4l2_format *fmt,
+                                const void *parg,
                                 unsigned int *count, unsigned int *num_planes,
                                 unsigned int sizes[], void *alloc_ctxs[])
 {
index 3628938785ac7e23438b01e4f31eaa87530e5d04..51d4a1703af2721ef4c8079c413fe70d911b7291 100644 (file)
@@ -41,7 +41,7 @@
  * videobuf2 queue operations
  */
 
-static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
 {
index 05e7ad5d2c8b6650f3f69152c3b38252e2b8921d..0ab59a571fee834416883f8d84d685269424489a 100644 (file)
@@ -118,6 +118,71 @@ static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
        return ret;
 }
 
+/**
+ * struct lirc_driver - Defines the parameters on a LIRC driver
+ *
+ * @name:              this string will be used for logs
+ *
+ * @minor:             indicates minor device (/dev/lirc) number for
+ *                     registered driver if caller fills it with negative
+ *                     value, then the first free minor number will be used
+ *                     (if available).
+ *
+ * @code_length:       length of the remote control key code expressed in bits.
+ *
+ * @buffer_size:       Number of FIFO buffers with @chunk_size size. If zero,
+ *                     creates a buffer with BUFLEN size (16 bytes).
+ *
+ * @sample_rate:       if zero, the device will wait for an event with a new
+ *                     code to be parsed. Otherwise, specifies the sample
+ *                     rate for polling. Value should be between 0
+ *                     and HZ. If equal to HZ, it would mean one polling per
+ *                     second.
+ *
+ * @features:          lirc compatible hardware features, like LIRC_MODE_RAW,
+ *                     LIRC_CAN_*, as defined at include/media/lirc.h.
+ *
+ * @chunk_size:                Size of each FIFO buffer.
+ *
+ * @data:              it may point to any driver data and this pointer will
+ *                     be passed to all callback functions.
+ *
+ * @min_timeout:       Minimum timeout for record. Valid only if
+ *                     LIRC_CAN_SET_REC_TIMEOUT is defined.
+ *
+ * @max_timeout:       Maximum timeout for record. Valid only if
+ *                     LIRC_CAN_SET_REC_TIMEOUT is defined.
+ *
+ * @add_to_buf:                add_to_buf will be called after specified period of the
+ *                     time or triggered by the external event, this behavior
+ *                     depends on value of the sample_rate this function will
+ *                     be called in user context. This routine should return
+ *                     0 if data was added to the buffer and -ENODATA if none
+ *                     was available. This should add some number of bits
+ *                     evenly divisible by code_length to the buffer.
+ *
+ * @rbuf:              if not NULL, it will be used as a read buffer, you will
+ *                     have to write to the buffer by other means, like irq's
+ *                     (see also lirc_serial.c).
+ *
+ * @set_use_inc:       set_use_inc will be called after device is opened
+ *
+ * @set_use_dec:       set_use_dec will be called after device is closed
+ *
+ * @rdev:              Pointed to struct rc_dev associated with the LIRC
+ *                     device.
+ *
+ * @fops:              file_operations for drivers which don't fit the current
+ *                     driver model.
+ *                     Some ioctl's can be directly handled by lirc_dev if the
+ *                     driver's ioctl function is NULL or if it returns
+ *                     -ENOIOCTLCMD (see also lirc_serial.c).
+ *
+ * @dev:               pointer to the struct device associated with the LIRC
+ *                     device.
+ *
+ * @owner:             the module owning this struct
+ */
 struct lirc_driver {
        char name[40];
        int minor;
@@ -131,65 +196,16 @@ struct lirc_driver {
        void *data;
        int min_timeout;
        int max_timeout;
-       int (*add_to_buf) (void *data, struct lirc_buffer *buf);
+       int (*add_to_buf)(void *data, struct lirc_buffer *buf);
        struct lirc_buffer *rbuf;
-       int (*set_use_inc) (void *data);
-       void (*set_use_dec) (void *data);
+       int (*set_use_inc)(void *data);
+       void (*set_use_dec)(void *data);
        struct rc_dev *rdev;
        const struct file_operations *fops;
        struct device *dev;
        struct module *owner;
 };
 
-/* name:
- * this string will be used for logs
- *
- * minor:
- * indicates minor device (/dev/lirc) number for registered driver
- * if caller fills it with negative value, then the first free minor
- * number will be used (if available)
- *
- * code_length:
- * length of the remote control key code expressed in bits
- *
- * sample_rate:
- *
- * data:
- * it may point to any driver data and this pointer will be passed to
- * all callback functions
- *
- * add_to_buf:
- * add_to_buf will be called after specified period of the time or
- * triggered by the external event, this behavior depends on value of
- * the sample_rate this function will be called in user context. This
- * routine should return 0 if data was added to the buffer and
- * -ENODATA if none was available. This should add some number of bits
- * evenly divisible by code_length to the buffer
- *
- * rbuf:
- * if not NULL, it will be used as a read buffer, you will have to
- * write to the buffer by other means, like irq's (see also
- * lirc_serial.c).
- *
- * set_use_inc:
- * set_use_inc will be called after device is opened
- *
- * set_use_dec:
- * set_use_dec will be called after device is closed
- *
- * fops:
- * file_operations for drivers which don't fit the current driver model.
- *
- * Some ioctl's can be directly handled by lirc_dev if the driver's
- * ioctl function is NULL or if it returns -ENOIOCTLCMD (see also
- * lirc_serial.c).
- *
- * owner:
- * the module owning this struct
- *
- */
-
-
 /* following functions can be called ONLY from user context
  *
  * returns negative value on error or minor number
index ab03c5344209937818de9200a9f33b678e64c2c5..094e112cc325e4e546d6e64da1ebae2429d9feaa 100644 (file)
@@ -5,6 +5,15 @@
 #ifndef __TUNER_TYPES_H__
 #define __TUNER_TYPES_H__
 
+/**
+ * enum param_type - type of the tuner pameters
+ *
+ * @TUNER_PARAM_TYPE_RADIO:    Tuner params are for FM and/or AM radio
+ * @TUNER_PARAM_TYPE_PAL:      Tuner params are for PAL color TV standard
+ * @TUNER_PARAM_TYPE_SECAM:    Tuner params are for SECAM color TV standard
+ * @TUNER_PARAM_TYPE_NTSC:     Tuner params are for NTSC color TV standard
+ * @TUNER_PARAM_TYPE_DIGITAL:  Tuner params are for digital TV
+ */
 enum param_type {
        TUNER_PARAM_TYPE_RADIO,
        TUNER_PARAM_TYPE_PAL,
@@ -13,97 +22,142 @@ enum param_type {
        TUNER_PARAM_TYPE_DIGITAL,
 };
 
+/**
+ * struct tuner_range - define the frequencies supported by the tuner
+ *
+ * @limit:             Max frequency supported by that range, in 62.5 kHz
+ *                     (TV) or 62.5 Hz (Radio), as defined by
+ *                     V4L2_TUNER_CAP_LOW.
+ * @config:            Value of the band switch byte (BB) to setup this mode.
+ * @cb:                        Value of the CB byte to setup this mode.
+ *
+ * Please notice that digital tuners like xc3028/xc4000/xc5000 don't use
+ * those ranges, as they're defined inside the driver. This is used by
+ * analog tuners that are compatible with the "Philips way" to setup the
+ * tuners. On those devices, the tuner set is done via 4 bytes:
+ *     divider byte1 (DB1), divider byte 2 (DB2), Control byte (CB) and
+ *     band switch byte (BB).
+ * Some tuners also have an additional optional Auxiliary byte (AB).
+ */
 struct tuner_range {
        unsigned short limit;
        unsigned char config;
        unsigned char cb;
 };
 
+/**
+ * struct tuner_params - Parameters to be used to setup the tuner. Those
+ *                      are used by drivers/media/tuners/tuner-types.c in
+ *                      order to specify the tuner properties. Most of
+ *                      the parameters are for tuners based on tda9887 IF-PLL
+ *                      multi-standard analog TV/Radio demodulator, with is
+ *                      very common on legacy analog tuners.
+ *
+ * @type:                      Type of the tuner parameters, as defined at
+ *                             enum param_type. If the tuner supports multiple
+ *                             standards, an array should be used, with one
+ *                             row per different standard.
+ * @cb_first_if_lower_freq:    Many Philips-based tuners have a comment in
+ *                             their datasheet like
+ *                             "For channel selection involving band
+ *                             switching, and to ensure smooth tuning to the
+ *                             desired channel without causing unnecessary
+ *                             charge pump action, it is recommended to
+ *                             consider the difference between wanted channel
+ *                             frequency and the current channel frequency.
+ *                             Unnecessary charge pump action will result
+ *                             in very low tuning voltage which may drive the
+ *                             oscillator to extreme conditions".
+ *                             Set cb_first_if_lower_freq to 1, if this check
+ *                             is required for this tuner. I tested this for
+ *                             PAL by first setting the TV frequency to
+ *                             203 MHz and then switching to 96.6 MHz FM
+ *                             radio. The result was static unless the
+ *                             control byte was sent first.
+ * @has_tda9887:               Set to 1 if this tuner uses a tda9887
+ * @port1_fm_high_sensitivity: Many Philips tuners use tda9887 PORT1 to select
+ *                             the FM radio sensitivity. If this setting is 1,
+ *                             then set PORT1 to 1 to get proper FM reception.
+ * @port2_fm_high_sensitivity: Some Philips tuners use tda9887 PORT2 to select
+ *                             the FM radio sensitivity. If this setting is 1,
+ *                             then set PORT2 to 1 to get proper FM reception.
+ * @fm_gain_normal:            Some Philips tuners use tda9887 cGainNormal to
+ *                             select the FM radio sensitivity. If this
+ *                             setting is 1, e register will use cGainNormal
+ *                             instead of cGainLow.
+ * @intercarrier_mode:         Most tuners with a tda9887 use QSS mode.
+ *                             Some (cheaper) tuners use Intercarrier mode.
+ *                             If this setting is 1, then the tuner needs to
+ *                             be set to intercarrier mode.
+ * @port1_active:              This setting sets the default value for PORT1.
+ *                             0 means inactive, 1 means active. Note: the
+ *                             actual bit value written to the tda9887 is
+ *                             inverted. So a 0 here means a 1 in the B6 bit.
+ * @port2_active:              This setting sets the default value for PORT2.
+ *                             0 means inactive, 1 means active. Note: the
+ *                             actual bit value written to the tda9887 is
+ *                             inverted. So a 0 here means a 1 in the B7 bit.
+ * @port1_invert_for_secam_lc: Sometimes PORT1 is inverted when the SECAM-L'
+ *                             standard is selected. Set this bit to 1 if this
+ *                             is needed.
+ * @port2_invert_for_secam_lc: Sometimes PORT2 is inverted when the SECAM-L'
+ *                             standard is selected. Set this bit to 1 if this
+ *                             is needed.
+ * @port1_set_for_fm_mono:     Some cards require PORT1 to be 1 for mono Radio
+ *                             FM and 0 for stereo.
+ * @default_pll_gating_18:     Select 18% (or according to datasheet 0%)
+ *                             L standard PLL gating, vs the driver default
+ *                             of 36%.
+ * @radio_if:                  IF to use in radio mode.  Tuners with a
+ *                             separate radio IF filter seem to use 10.7,
+ *                             while those without use 33.3 for PAL/SECAM
+ *                             tuners and 41.3 for NTSC tuners.
+ *                             0 = 10.7, 1 = 33.3, 2 = 41.3
+ * @default_top_low:           Default tda9887 TOP value in dB for the low
+ *                             band. Default is 0. Range: -16:+15
+ * @default_top_mid:           Default tda9887 TOP value in dB for the mid
+ *                             band. Default is 0. Range: -16:+15
+ * @default_top_high:          Default tda9887 TOP value in dB for the high
+ *                             band. Default is 0. Range: -16:+15
+ * @default_top_secam_low:     Default tda9887 TOP value in dB for SECAM-L/L'
+ *                             for the low band. Default is 0. Several tuners
+ *                             require a different TOP value for the
+ *                             SECAM-L/L' standards. Range: -16:+15
+ * @default_top_secam_mid:     Default tda9887 TOP value in dB for SECAM-L/L'
+ *                             for the mid band. Default is 0. Several tuners
+ *                             require a different TOP value for the
+ *                             SECAM-L/L' standards. Range: -16:+15
+ * @default_top_secam_high:    Default tda9887 TOP value in dB for SECAM-L/L'
+ *                             for the high band. Default is 0. Several tuners
+ *                             require a different TOP value for the
+ *                             SECAM-L/L' standards. Range: -16:+15
+ * @iffreq:                    Intermediate frequency (IF) used by the tuner
+ *                             on digital mode.
+ * @count:                     Size of the ranges array.
+ * @ranges:                    Array with the frequency ranges supported by
+ *                             the tuner.
+ */
 struct tuner_params {
        enum param_type type;
 
-       /* Many Philips based tuners have a comment like this in their
-        * datasheet:
-        *
-        *   For channel selection involving band switching, and to ensure
-        *   smooth tuning to the desired channel without causing
-        *   unnecessary charge pump action, it is recommended to consider
-        *   the difference between wanted channel frequency and the
-        *   current channel frequency.  Unnecessary charge pump action
-        *   will result in very low tuning voltage which may drive the
-        *   oscillator to extreme conditions.
-        *
-        * Set cb_first_if_lower_freq to 1, if this check is
-        * required for this tuner.
-        *
-        * I tested this for PAL by first setting the TV frequency to
-        * 203 MHz and then switching to 96.6 MHz FM radio. The result was
-        * static unless the control byte was sent first.
-        */
        unsigned int cb_first_if_lower_freq:1;
-       /* Set to 1 if this tuner uses a tda9887 */
        unsigned int has_tda9887:1;
-       /* Many Philips tuners use tda9887 PORT1 to select the FM radio
-          sensitivity. If this setting is 1, then set PORT1 to 1 to
-          get proper FM reception. */
        unsigned int port1_fm_high_sensitivity:1;
-       /* Some Philips tuners use tda9887 PORT2 to select the FM radio
-          sensitivity. If this setting is 1, then set PORT2 to 1 to
-          get proper FM reception. */
        unsigned int port2_fm_high_sensitivity:1;
-       /* Some Philips tuners use tda9887 cGainNormal to select the FM radio
-          sensitivity. If this setting is 1, e register will use cGainNormal
-          instead of cGainLow. */
        unsigned int fm_gain_normal:1;
-       /* Most tuners with a tda9887 use QSS mode. Some (cheaper) tuners
-          use Intercarrier mode. If this setting is 1, then the tuner
-          needs to be set to intercarrier mode. */
        unsigned int intercarrier_mode:1;
-       /* This setting sets the default value for PORT1.
-          0 means inactive, 1 means active. Note: the actual bit
-          value written to the tda9887 is inverted. So a 0 here
-          means a 1 in the B6 bit. */
        unsigned int port1_active:1;
-       /* This setting sets the default value for PORT2.
-          0 means inactive, 1 means active. Note: the actual bit
-          value written to the tda9887 is inverted. So a 0 here
-          means a 1 in the B7 bit. */
        unsigned int port2_active:1;
-       /* Sometimes PORT1 is inverted when the SECAM-L' standard is selected.
-          Set this bit to 1 if this is needed. */
        unsigned int port1_invert_for_secam_lc:1;
-       /* Sometimes PORT2 is inverted when the SECAM-L' standard is selected.
-          Set this bit to 1 if this is needed. */
        unsigned int port2_invert_for_secam_lc:1;
-       /* Some cards require PORT1 to be 1 for mono Radio FM and 0 for stereo. */
        unsigned int port1_set_for_fm_mono:1;
-       /* Select 18% (or according to datasheet 0%) L standard PLL gating,
-          vs the driver default of 36%. */
        unsigned int default_pll_gating_18:1;
-       /* IF to use in radio mode.  Tuners with a separate radio IF filter
-          seem to use 10.7, while those without use 33.3 for PAL/SECAM tuners
-          and 41.3 for NTSC tuners. 0 = 10.7, 1 = 33.3, 2 = 41.3 */
        unsigned int radio_if:2;
-       /* Default tda9887 TOP value in dB for the low band. Default is 0.
-          Range: -16:+15 */
        signed int default_top_low:5;
-       /* Default tda9887 TOP value in dB for the mid band. Default is 0.
-          Range: -16:+15 */
        signed int default_top_mid:5;
-       /* Default tda9887 TOP value in dB for the high band. Default is 0.
-          Range: -16:+15 */
        signed int default_top_high:5;
-       /* Default tda9887 TOP value in dB for SECAM-L/L' for the low band.
-          Default is 0. Several tuners require a different TOP value for
-          the SECAM-L/L' standards. Range: -16:+15 */
        signed int default_top_secam_low:5;
-       /* Default tda9887 TOP value in dB for SECAM-L/L' for the mid band.
-          Default is 0. Several tuners require a different TOP value for
-          the SECAM-L/L' standards. Range: -16:+15 */
        signed int default_top_secam_mid:5;
-       /* Default tda9887 TOP value in dB for SECAM-L/L' for the high band.
-          Default is 0. Several tuners require a different TOP value for
-          the SECAM-L/L' standards. Range: -16:+15 */
        signed int default_top_secam_high:5;
 
        u16 iffreq;
index b46ebb48fe74b8daf0872f3c00d0f3752c7a28d2..486b6a54363b1708c7349914dff127dcd3f86565 100644 (file)
@@ -1,23 +1,19 @@
 /*
-    tuner.h - definition for different tuners
-
-    Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
-    minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de)
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * tuner.h - definition for different tuners
+ *
+ * Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
+ * minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
 #ifndef _TUNER_H
 #define _TUNER_H
 #define TUNER_PHILIPS_FM1236_MK3       43
 
 #define TUNER_PHILIPS_4IN1             44      /* ATI TV Wonder Pro - Conexant */
-/* Microtune merged with Temic 12/31/1999 partially financed by Alps - these may be similar to Temic */
-#define TUNER_MICROTUNE_4049FM5        45
+       /*
+        * Microtune merged with Temic 12/31/1999 partially financed by Alps.
+        * these may be similar to Temic
+        */
+#define TUNER_MICROTUNE_4049FM5                45
 #define TUNER_PANASONIC_VP27           46
 #define TUNER_LG_NTSC_TAPE             47
 
 
 #define TUNER_PHILIPS_TUV1236D         68      /* ATI HDTV Wonder */
 #define TUNER_TNF_5335MF                69     /* Sabrent Bt848   */
-#define TUNER_SAMSUNG_TCPN_2121P30A     70     /* Hauppauge PVR-500MCE NTSC */
+#define TUNER_SAMSUNG_TCPN_2121P30A     70     /* Hauppauge PVR-500MCE NTSC */
 #define TUNER_XC2028                   71
 
 #define TUNER_THOMSON_FE6600           72      /* DViCO FusionHDTV DVB-T Hybrid */
-#define TUNER_SAMSUNG_TCPG_6121P30A     73     /* Hauppauge PVR-500 PAL */
+#define TUNER_SAMSUNG_TCPG_6121P30A     73     /* Hauppauge PVR-500 PAL */
 #define TUNER_TDA9887                   74      /* This tuner should be used only internally */
 #define TUNER_TEA5761                  75      /* Only FM Radio Tuner */
 #define TUNER_XC5000                   76      /* Xceive Silicon Tuner */
 #define TUNER_SONY_BTF_PB463Z          91      /* NTSC */
 
 /* tv card specific */
-#define TDA9887_PRESENT                (1<<0)
-#define TDA9887_PORT1_INACTIVE                 (1<<1)
-#define TDA9887_PORT2_INACTIVE                 (1<<2)
-#define TDA9887_QSS                    (1<<3)
-#define TDA9887_INTERCARRIER           (1<<4)
-#define TDA9887_PORT1_ACTIVE           (1<<5)
-#define TDA9887_PORT2_ACTIVE           (1<<6)
-#define TDA9887_INTERCARRIER_NTSC      (1<<7)
+#define TDA9887_PRESENT                        (1<<0)
+#define TDA9887_PORT1_INACTIVE         (1<<1)
+#define TDA9887_PORT2_INACTIVE         (1<<2)
+#define TDA9887_QSS                    (1<<3)
+#define TDA9887_INTERCARRIER           (1<<4)
+#define TDA9887_PORT1_ACTIVE           (1<<5)
+#define TDA9887_PORT2_ACTIVE           (1<<6)
+#define TDA9887_INTERCARRIER_NTSC      (1<<7)
 /* Tuner takeover point adjustment, in dB, -16 <= top <= 15 */
-#define TDA9887_TOP_MASK               (0x3f << 8)
-#define TDA9887_TOP_SET                (1 << 13)
-#define TDA9887_TOP(top)               (TDA9887_TOP_SET | (((16 + (top)) & 0x1f) << 8))
+#define TDA9887_TOP_MASK               (0x3f << 8)
+#define TDA9887_TOP_SET                        (1 << 13)
+#define TDA9887_TOP(top)               (TDA9887_TOP_SET | \
+                                        (((16 + (top)) & 0x1f) << 8))
 
 /* config options */
-#define TDA9887_DEEMPHASIS_MASK        (3<<16)
-#define TDA9887_DEEMPHASIS_NONE        (1<<16)
-#define TDA9887_DEEMPHASIS_50          (2<<16)
-#define TDA9887_DEEMPHASIS_75          (3<<16)
-#define TDA9887_AUTOMUTE               (1<<18)
+#define TDA9887_DEEMPHASIS_MASK                (3<<16)
+#define TDA9887_DEEMPHASIS_NONE                (1<<16)
+#define TDA9887_DEEMPHASIS_50          (2<<16)
+#define TDA9887_DEEMPHASIS_75          (3<<16)
+#define TDA9887_AUTOMUTE               (1<<18)
 #define TDA9887_GATING_18              (1<<19)
 #define TDA9887_GAIN_NORMAL            (1<<20)
 #define TDA9887_RIF_41_3               (1<<21)  /* radio IF1 41.3 vs 33.3 */
 
+/**
+ * enum tuner_mode      - Mode of the tuner
+ *
+ * @T_RADIO:        Tuner core will work in radio mode
+ * @T_ANALOG_TV:    Tuner core will work in analog TV mode
+ *
+ * Older boards only had a single tuner device, but some devices have a
+ * separate tuner for radio. In any case, the tuner-core needs to know if
+ * the tuner chip(s) will be used in radio mode or analog TV mode, as, on
+ * radio mode, frequencies are specified on a different range than on TV
+ * mode. This enum is used by the tuner core in order to work with the
+ * proper tuner range and eventually use a different tuner chip while in
+ * radio mode.
+ */
 enum tuner_mode {
        T_RADIO         = 1 << V4L2_TUNER_RADIO,
        T_ANALOG_TV     = 1 << V4L2_TUNER_ANALOG_TV,
-       /* Don't need to map V4L2_TUNER_DIGITAL_TV, as tuner-core won't use it */
+       /* Don't map V4L2_TUNER_DIGITAL_TV, as tuner-core won't use it */
 };
 
-/* Older boards only had a single tuner device. Nowadays multiple tuner
-   devices may be present on a single board. Using TUNER_SET_TYPE_ADDR
-   to pass the tuner_setup structure it is possible to setup each tuner
-   device in turn.
-
-   Since multiple devices may be present it is no longer sufficient to
-   send a command to a single i2c device. Instead you should broadcast
-   the command to all i2c devices.
-
-   By setting the mode_mask correctly you can select which commands are
-   accepted by a specific tuner device. For example, set mode_mask to
-   T_RADIO if the device is a radio-only tuner. That specific tuner will
-   only accept commands when the tuner is in radio mode and ignore them
-   when the tuner is set to TV mode.
+/**
+ * struct tuner_setup   - setup the tuner chipsets
+ *
+ * @addr:              I2C address used to control the tuner device/chipset
+ * @type:              Type of the tuner, as defined at the TUNER_* macros.
+ *                     Each different tuner model should have an unique
+ *                     identifier.
+ * @mode_mask:         Mask with the allowed tuner modes: V4L2_TUNER_RADIO,
+ *                     V4L2_TUNER_ANALOG_TV and/or V4L2_TUNER_DIGITAL_TV,
+ *                     describing if the tuner should be used to support
+ *                     Radio, analog TV and/or digital TV.
+ * @config:            Used to send tuner-specific configuration for complex
+ *                     tuners that require extra parameters to be set.
+ *                     Only a very few tuners require it and its usage on
+ *                     newer tuners should be avoided.
+ * @tuner_callback:    Some tuners require to call back the bridge driver,
+ *                     in order to do some tasks like rising a GPIO at the
+ *                     bridge chipset, in order to do things like resetting
+ *                     the device.
+ *
+ * Older boards only had a single tuner device. Nowadays multiple tuner
+ * devices may be present on a single board. Using TUNER_SET_TYPE_ADDR
+ * to pass the tuner_setup structure it is possible to setup each tuner
+ * device in turn.
+ *
+ * Since multiple devices may be present it is no longer sufficient to
+ * send a command to a single i2c device. Instead you should broadcast
+ * the command to all i2c devices.
+ *
+ * By setting the mode_mask correctly you can select which commands are
+ * accepted by a specific tuner device. For example, set mode_mask to
+ * T_RADIO if the device is a radio-only tuner. That specific tuner will
+ * only accept commands when the tuner is in radio mode and ignore them
+ * when the tuner is set to TV mode.
  */
 
 struct tuner_setup {
-       unsigned short  addr;   /* I2C address */
-       unsigned int    type;   /* Tuner type */
-       unsigned int    mode_mask;  /* Allowed tuner modes */
-       void            *config;    /* configuraion for more complex tuners */
-       int (*tuner_callback) (void *dev, int component, int cmd, int arg);
+       unsigned short  addr;
+       unsigned int    type;
+       unsigned int    mode_mask;
+       void            *config;
+       int (*tuner_callback)(void *dev, int component, int cmd, int arg);
 };
 
 #endif /* __KERNEL__ */
index f7119ee3977b22541cb5faa8d0282d62b435fe2c..8be898739e0cd64f3a4ccb384d5e3a661c463e59 100644 (file)
@@ -1,28 +1,63 @@
+
 /*
+ * tveeprom - Contains structures and functions to work with Hauppauge
+ *           eeproms.
  */
 
+#include <linux/if_ether.h>
+
+/**
+ * enum tveeprom_audio_processor - Specifies the type of audio processor
+ *                                used on a Hauppauge device.
+ *
+ * @TVEEPROM_AUDPROC_NONE:     No audio processor present
+ * @TVEEPROM_AUDPROC_INTERNAL: The audio processor is internal to the
+ *                             video processor
+ * @TVEEPROM_AUDPROC_MSP:      The audio processor is a MSPXXXX device
+ * @TVEEPROM_AUDPROC_OTHER:    The audio processor is another device
+ */
 enum tveeprom_audio_processor {
-       /* No audio processor present */
        TVEEPROM_AUDPROC_NONE,
-       /* The audio processor is internal to the video processor */
        TVEEPROM_AUDPROC_INTERNAL,
-       /* The audio processor is a MSPXXXX device */
        TVEEPROM_AUDPROC_MSP,
-       /* The audio processor is another device */
        TVEEPROM_AUDPROC_OTHER,
 };
 
-#include <linux/if_ether.h>
-
+/**
+ * struct tveeprom - Contains the fields parsed from Hauppauge eeproms
+ *
+ * @has_radio:                 1 if the device has radio; 0 otherwise.
+ * @has_ir:                    If has_ir == 0, then it is unknown what the IR
+ *                             capabilities are. Otherwise:
+ *                                     bit 0) 1 (= IR capabilities are known);
+ *                                     bit 1) IR receiver present;
+ *                                     bit 2) IR transmitter (blaster) present.
+ * @has_MAC_address:           0: no MAC, 1: MAC present, 2: unknown.
+ * @tuner_type:                        type of the tuner (TUNER_*, as defined at
+ *                             include/media/tuner.h).
+ * @tuner_formats:             Supported analog TV standards (V4L2_STD_*).
+ * @tuner_hauppauge_model:     Hauppauge's code for the device model number.
+ * @tuner2_type:               type of the second tuner (TUNER_*, as defined
+ *                             at include/media/tuner.h).
+ * @tuner2_formats:            Tuner 2 supported analog TV standards
+ *                             (V4L2_STD_*).
+ * @tuner2_hauppauge_model:    tuner 2 Hauppauge's code for the device model
+ *                             number.
+ * @audio_processor:           analog audio decoder, as defined by enum
+ *                             tveeprom_audio_processor.
+ * @decoder_processor:         Hauppauge's code for the decoder chipset.
+ *                             Unused by the drivers, as they probe the
+ *                             decoder based on the PCI or USB ID.
+ * @model:                     Hauppauge's model number
+ * @revision:                  Card revision number
+ * @serial_number:             Card's serial number
+ * @rev_str:                   Card revision converted to number
+ * @MAC_address:               MAC address for the network interface
+ */
 struct tveeprom {
        u32 has_radio;
-       /* If has_ir == 0, then it is unknown what the IR capabilities are,
-          otherwise:
-          bit 0: 1 (= IR capabilities are known)
-          bit 1: IR receiver present
-          bit 2: IR transmitter (blaster) present */
        u32 has_ir;
-       u32 has_MAC_address; /* 0: no MAC, 1: MAC present, 2: unknown */
+       u32 has_MAC_address;
 
        u32 tuner_type;
        u32 tuner_formats;
@@ -32,9 +67,6 @@ struct tveeprom {
        u32 tuner2_formats;
        u32 tuner2_hauppauge_model;
 
-       u32 digitizer;
-       u32 digitizer_formats;
-
        u32 audio_processor;
        u32 decoder_processor;
 
@@ -45,7 +77,28 @@ struct tveeprom {
        u8 MAC_address[ETH_ALEN];
 };
 
+/**
+ * tveeprom_hauppauge_analog - Fill struct tveeprom using the contents
+ *                            of the eeprom previously filled at
+ *                            @eeprom_data field.
+ *
+ * @c:                 I2C client struct
+ * @tvee:              Struct to where the eeprom parsed data will be filled;
+ * @eeprom_data:       Array with the contents of the eeprom_data. It should
+ *                     contain 256 bytes filled with the contents of the
+ *                     eeprom read from the Hauppauge device.
+ */
 void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                               unsigned char *eeprom_data);
 
+/**
+ * tveeprom_read - Reads the contents of the eeprom found at the Hauppauge
+ *                devices.
+ *
+ * @c:         I2C client struct
+ * @eedata:    Array where the eeprom content will be stored.
+ * @len:       Size of @eedata array. If the eeprom content will be latter
+ *             be parsed by tveeprom_hauppauge_analog(), len should be, at
+ *             least, 256.
+ */
 int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len);
index 8fbbd76d78e84fdea1ecc5e41a195b15bceba8fb..017ffb2220c7c66a808b5d7231350f1fa40a276c 100644 (file)
@@ -36,6 +36,8 @@ struct v4l2_ioctl_ops {
                                              struct v4l2_fmtdesc *f);
        int (*vidioc_enum_fmt_sdr_cap)     (struct file *file, void *fh,
                                            struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_sdr_out)     (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
 
        /* VIDIOC_G_FMT handlers */
        int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
@@ -60,6 +62,8 @@ struct v4l2_ioctl_ops {
                                           struct v4l2_format *f);
        int (*vidioc_g_fmt_sdr_cap)    (struct file *file, void *fh,
                                        struct v4l2_format *f);
+       int (*vidioc_g_fmt_sdr_out)    (struct file *file, void *fh,
+                                       struct v4l2_format *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_sdr_cap)    (struct file *file, void *fh,
                                        struct v4l2_format *f);
+       int (*vidioc_s_fmt_sdr_out)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
 
        /* VIDIOC_TRY_FMT handlers */
        int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
@@ -108,6 +114,8 @@ struct v4l2_ioctl_ops {
                                             struct v4l2_format *f);
        int (*vidioc_try_fmt_sdr_cap)    (struct file *file, void *fh,
                                          struct v4l2_format *f);
+       int (*vidioc_try_fmt_sdr_out)    (struct file *file, void *fh,
+                                         struct v4l2_format *f);
 
        /* Buffer handlers */
        int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
index 128b15ad549788305154aa1771f4b0b013692462..647ebfe5174f623b27723924a521cc3f483329dd 100644 (file)
 #include <linux/mm_types.h>
 #include <linux/mutex.h>
 #include <linux/poll.h>
-#include <linux/videodev2.h>
 #include <linux/dma-buf.h>
 
+#define VB2_MAX_FRAME  (32)
+#define VB2_MAX_PLANES (8)
+
+enum vb2_memory {
+       VB2_MEMORY_UNKNOWN      = 0,
+       VB2_MEMORY_MMAP         = 1,
+       VB2_MEMORY_USERPTR      = 2,
+       VB2_MEMORY_DMABUF       = 4,
+};
+
 struct vb2_alloc_ctx;
 struct vb2_fileio_data;
 struct vb2_threadio_data;
@@ -202,11 +211,6 @@ struct vb2_queue;
  * @num_planes:                number of planes in the buffer
  *                     on an internal driver queue
  * @planes:            private per-plane information; do not change
- * @state:             current buffer state; do not change
- * @queued_entry:      entry on the queued buffers list, which holds all
- *                     buffers queued from userspace
- * @done_entry:                entry on the list that stores all buffers ready to
- *                     be dequeued to userspace
  */
 struct vb2_buffer {
        struct vb2_queue        *vb2_queue;
@@ -214,9 +218,16 @@ struct vb2_buffer {
        unsigned int            type;
        unsigned int            memory;
        unsigned int            num_planes;
-       struct vb2_plane        planes[VIDEO_MAX_PLANES];
-
-       /* Private: internal use only */
+       struct vb2_plane        planes[VB2_MAX_PLANES];
+
+       /* private: internal use only
+        *
+        * state:               current buffer state; do not change
+        * queued_entry:        entry on the queued buffers list, which holds
+        *                      all buffers queued from userspace
+        * done_entry:          entry on the list that stores all buffers ready
+        *                      to be dequeued to userspace
+        */
        enum vb2_buffer_state   state;
 
        struct list_head        queued_entry;
@@ -333,7 +344,7 @@ struct vb2_buffer {
  *                     pre-queued buffers before calling STREAMON.
  */
 struct vb2_ops {
-       int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
+       int (*queue_setup)(struct vb2_queue *q, const void *parg,
                           unsigned int *num_buffers, unsigned int *num_planes,
                           unsigned int sizes[], void *alloc_ctxs[]);
 
@@ -351,12 +362,19 @@ struct vb2_ops {
        void (*buf_queue)(struct vb2_buffer *vb);
 };
 
-struct v4l2_fh;
+struct vb2_buf_ops {
+       int (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
+       int (*fill_vb2_buffer)(struct vb2_buffer *vb, const void *pb,
+                               struct vb2_plane *planes);
+       int (*set_timestamp)(struct vb2_buffer *vb, const void *pb);
+};
 
 /**
  * struct vb2_queue - a videobuf queue
  *
- * @type:      queue type (see V4L2_BUF_TYPE_* in linux/videodev2.h
+ * @type:      private buffer type whose content is defined by the vb2-core
+ *             caller. For example, for V4L2, it should match
+ *             the V4L2_BUF_TYPE_* in include/uapi/linux/videodev2.h
  * @io_modes:  supported io methods (see vb2_io_modes enum)
  * @fileio_read_once:          report EOF after reading the first buffer
  * @fileio_write_immediately:  queue buffer after each write() call
@@ -372,6 +390,8 @@ struct v4l2_fh;
  *             drivers to easily associate an owner filehandle with the queue.
  * @ops:       driver-specific callbacks
  * @mem_ops:   memory allocator specific callbacks
+ * @buf_ops:   callbacks to deliver buffer information
+ *             between user-space and kernel-space
  * @drv_priv:  driver private data
  * @buf_struct_size: size of the driver-specific buffer structure;
  *             "0" indicates the driver doesn't want to use a custom buffer
@@ -407,6 +427,8 @@ struct v4l2_fh;
  * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
  *             buffers. Only set for capture queues if qbuf has not yet been
  *             called since poll() needs to return POLLERR in that situation.
+ * @is_multiplanar: set if buffer type is multiplanar
+ * @is_output: set if buffer type is output
  * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
  *             last decoded buffer was already dequeued. Set for capture queues
  *             when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
@@ -414,17 +436,19 @@ struct v4l2_fh;
  * @threadio:  thread io internal data, used only if thread is active
  */
 struct vb2_queue {
-       enum v4l2_buf_type              type;
+       unsigned int                    type;
        unsigned int                    io_modes;
        unsigned                        fileio_read_once:1;
        unsigned                        fileio_write_immediately:1;
        unsigned                        allow_zero_bytesused:1;
 
        struct mutex                    *lock;
-       struct v4l2_fh                  *owner;
+       void                            *owner;
 
        const struct vb2_ops            *ops;
        const struct vb2_mem_ops        *mem_ops;
+       const struct vb2_buf_ops        *buf_ops;
+
        void                            *drv_priv;
        unsigned int                    buf_struct_size;
        u32                             timestamp_flags;
@@ -433,8 +457,8 @@ struct vb2_queue {
 
        /* private: internal use only */
        struct mutex                    mmap_lock;
-       enum v4l2_memory                memory;
-       struct vb2_buffer               *bufs[VIDEO_MAX_FRAME];
+       unsigned int                    memory;
+       struct vb2_buffer               *bufs[VB2_MAX_FRAME];
        unsigned int                    num_buffers;
 
        struct list_head                queued_list;
@@ -445,13 +469,15 @@ struct vb2_queue {
        spinlock_t                      done_lock;
        wait_queue_head_t               done_wq;
 
-       void                            *alloc_ctx[VIDEO_MAX_PLANES];
-       unsigned int                    plane_sizes[VIDEO_MAX_PLANES];
+       void                            *alloc_ctx[VB2_MAX_PLANES];
+       unsigned int                    plane_sizes[VB2_MAX_PLANES];
 
        unsigned int                    streaming:1;
        unsigned int                    start_streaming_called:1;
        unsigned int                    error:1;
        unsigned int                    waiting_for_buffers:1;
+       unsigned int                    is_multiplanar:1;
+       unsigned int                    is_output:1;
        unsigned int                    last_buffer_dequeued:1;
 
        struct vb2_fileio_data          *fileio;
@@ -477,23 +503,25 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
 void vb2_discard_done(struct vb2_queue *q);
 int vb2_wait_for_all_buffers(struct vb2_queue *q);
 
-int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
-int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
-
-int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
-int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb);
+int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
+               unsigned int *count);
+int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
+               unsigned int *count, const void *parg);
+int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb);
+int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking);
 
-int __must_check vb2_queue_init(struct vb2_queue *q);
+int vb2_core_streamon(struct vb2_queue *q, unsigned int type);
+int vb2_core_streamoff(struct vb2_queue *q, unsigned int type);
 
-void vb2_queue_release(struct vb2_queue *q);
-void vb2_queue_error(struct vb2_queue *q);
+int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
+               unsigned int index, unsigned int plane, unsigned int flags);
 
-int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
-int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
-int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
+int vb2_core_queue_init(struct vb2_queue *q);
+void vb2_core_queue_release(struct vb2_queue *q);
 
-int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
-int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
+void vb2_queue_error(struct vb2_queue *q);
 
 int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
 #ifndef CONFIG_MMU
@@ -503,41 +531,6 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
                                    unsigned long pgoff,
                                    unsigned long flags);
 #endif
-unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
-size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
-               loff_t *ppos, int nonblock);
-size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
-               loff_t *ppos, int nonblock);
-
-/*
- * vb2_thread_fnc - callback function for use with vb2_thread
- *
- * This is called whenever a buffer is dequeued in the thread.
- */
-typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
-
-/**
- * vb2_thread_start() - start a thread for the given queue.
- * @q:         videobuf queue
- * @fnc:       callback function
- * @priv:      priv pointer passed to the callback function
- * @thread_name:the name of the thread. This will be prefixed with "vb2-".
- *
- * This starts a thread that will queue and dequeue until an error occurs
- * or @vb2_thread_stop is called.
- *
- * This function should not be used for anything else but the videobuf2-dvb
- * support. If you think you have another good use-case for this, then please
- * contact the linux-media mailinglist first.
- */
-int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
-                    const char *thread_name);
-
-/**
- * vb2_thread_stop() - stop the thread for the given queue.
- * @q:         videobuf queue
- */
-int vb2_thread_stop(struct vb2_queue *q);
 
 /**
  * vb2_is_streaming() - return streaming status of the queue
@@ -642,48 +635,4 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q)
        q->last_buffer_dequeued = false;
 }
 
-/*
- * The following functions are not part of the vb2 core API, but are simple
- * helper functions that you can use in your struct v4l2_file_operations,
- * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock
- * or video_device->lock is set, and they will set and test vb2_queue->owner
- * to check if the calling filehandle is permitted to do the queuing operation.
- */
-
-/* struct v4l2_ioctl_ops helpers */
-
-int vb2_ioctl_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *p);
-int vb2_ioctl_create_bufs(struct file *file, void *priv,
-                         struct v4l2_create_buffers *p);
-int vb2_ioctl_prepare_buf(struct file *file, void *priv,
-                         struct v4l2_buffer *p);
-int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
-int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
-int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
-int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
-int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
-int vb2_ioctl_expbuf(struct file *file, void *priv,
-       struct v4l2_exportbuffer *p);
-
-/* struct v4l2_file_operations helpers */
-
-int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
-int vb2_fop_release(struct file *file);
-int _vb2_fop_release(struct file *file, struct mutex *lock);
-ssize_t vb2_fop_write(struct file *file, const char __user *buf,
-               size_t count, loff_t *ppos);
-ssize_t vb2_fop_read(struct file *file, char __user *buf,
-               size_t count, loff_t *ppos);
-unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
-#ifndef CONFIG_MMU
-unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
-               unsigned long len, unsigned long pgoff, unsigned long flags);
-#endif
-
-/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
-
-void vb2_ops_wait_prepare(struct vb2_queue *vq);
-void vb2_ops_wait_finish(struct vb2_queue *vq);
-
 #endif /* _MEDIA_VIDEOBUF2_CORE_H */
index 8f61456f1394bdae1a6dd6b259073f5a7923c198..5b64c9eac2c9324191e21f020acdca5fc9f7ce35 100644 (file)
@@ -6,7 +6,13 @@
 #include <dvb_demux.h>
 #include <dvb_net.h>
 #include <dvb_frontend.h>
-#include <media/videobuf2-core.h>
+
+#include <media/videobuf2-v4l2.h>
+/*
+ * TODO: This header file should be replaced with videobuf2-core.h
+ * Currently, vb2_thread is not a stuff of videobuf2-core,
+ * since vb2_thread has many dependencies on videobuf2-v4l2.
+ */
 
 struct vb2_dvb {
        /* filling that the job of the driver */
index 71f7fe2706b31e7b91b6168f3c93eaf2dbaa9f55..5abab1e7c7e869225bd546b363e54400444fc1fe 100644 (file)
 #include <linux/videodev2.h>
 #include <media/videobuf2-core.h>
 
+#if VB2_MAX_FRAME != VIDEO_MAX_FRAME
+#error VB2_MAX_FRAME != VIDEO_MAX_FRAME
+#endif
+
+#if VB2_MAX_PLANES != VIDEO_MAX_PLANES
+#error VB2_MAX_PLANES != VIDEO_MAX_PLANES
+#endif
+
 /**
  * struct vb2_v4l2_buffer - video buffer information for v4l2
  * @vb2_buf:   video buffer 2
@@ -42,4 +50,100 @@ struct vb2_v4l2_buffer {
 #define to_vb2_v4l2_buffer(vb) \
        container_of(vb, struct vb2_v4l2_buffer, vb2_buf)
 
+int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
+
+int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
+int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
+
+int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
+int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
+
+int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
+int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
+
+int __must_check vb2_queue_init(struct vb2_queue *q);
+void vb2_queue_release(struct vb2_queue *q);
+
+unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
+size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+               loff_t *ppos, int nonblock);
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
+               loff_t *ppos, int nonblock);
+
+/*
+ * vb2_thread_fnc - callback function for use with vb2_thread
+ *
+ * This is called whenever a buffer is dequeued in the thread.
+ */
+typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
+
+/**
+ * vb2_thread_start() - start a thread for the given queue.
+ * @q:         videobuf queue
+ * @fnc:       callback function
+ * @priv:      priv pointer passed to the callback function
+ * @thread_name:the name of the thread. This will be prefixed with "vb2-".
+ *
+ * This starts a thread that will queue and dequeue until an error occurs
+ * or @vb2_thread_stop is called.
+ *
+ * This function should not be used for anything else but the videobuf2-dvb
+ * support. If you think you have another good use-case for this, then please
+ * contact the linux-media mailinglist first.
+ */
+int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
+                    const char *thread_name);
+
+/**
+ * vb2_thread_stop() - stop the thread for the given queue.
+ * @q:         videobuf queue
+ */
+int vb2_thread_stop(struct vb2_queue *q);
+
+/*
+ * The following functions are not part of the vb2 core API, but are simple
+ * helper functions that you can use in your struct v4l2_file_operations,
+ * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock
+ * or video_device->lock is set, and they will set and test vb2_queue->owner
+ * to check if the calling filehandle is permitted to do the queuing operation.
+ */
+
+/* struct v4l2_ioctl_ops helpers */
+
+int vb2_ioctl_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *p);
+int vb2_ioctl_create_bufs(struct file *file, void *priv,
+                         struct v4l2_create_buffers *p);
+int vb2_ioctl_prepare_buf(struct file *file, void *priv,
+                         struct v4l2_buffer *p);
+int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
+int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
+int vb2_ioctl_expbuf(struct file *file, void *priv,
+       struct v4l2_exportbuffer *p);
+
+/* struct v4l2_file_operations helpers */
+
+int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
+int vb2_fop_release(struct file *file);
+int _vb2_fop_release(struct file *file, struct mutex *lock);
+ssize_t vb2_fop_write(struct file *file, const char __user *buf,
+               size_t count, loff_t *ppos);
+ssize_t vb2_fop_read(struct file *file, char __user *buf,
+               size_t count, loff_t *ppos);
+unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
+#ifndef CONFIG_MMU
+unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
+               unsigned long len, unsigned long pgoff, unsigned long flags);
+#endif
+
+/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
+
+void vb2_ops_wait_prepare(struct vb2_queue *vq);
+void vb2_ops_wait_finish(struct vb2_queue *vq);
+
 #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
index b015b38a4ddad2abfe91c6aefdd69dc21d0bef59..22afa26e34b2f69f9df1dbf26eb95cd78bfe5986 100644 (file)
@@ -5,6 +5,7 @@
 #define _TRACE_V4L2_H
 
 #include <linux/tracepoint.h>
+#include <media/videobuf2-v4l2.h>
 
 /* Enums require being exported to userspace, for user tool parsing */
 #undef EM
@@ -27,6 +28,7 @@
        EM( V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, "VIDEO_CAPTURE_MPLANE" ) \
        EM( V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,  "VIDEO_OUTPUT_MPLANE" ) \
        EM( V4L2_BUF_TYPE_SDR_CAPTURE,          "SDR_CAPTURE" )         \
+       EM( V4L2_BUF_TYPE_SDR_OUTPUT,           "SDR_OUTPUT" )          \
        EMe(V4L2_BUF_TYPE_PRIVATE,              "PRIVATE" )
 
 SHOW_TYPE
@@ -174,17 +176,12 @@ DEFINE_EVENT(v4l2_event_class, v4l2_qbuf,
        TP_ARGS(minor, buf)
 );
 
-DECLARE_EVENT_CLASS(vb2_event_class,
+DECLARE_EVENT_CLASS(vb2_v4l2_event_class,
        TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
        TP_ARGS(q, vb),
 
        TP_STRUCT__entry(
                __field(int, minor)
-               __field(u32, queued_count)
-               __field(int, owned_by_drv_count)
-               __field(u32, index)
-               __field(u32, type)
-               __field(u32, bytesused)
                __field(u32, flags)
                __field(u32, field)
                __field(s64, timestamp)
@@ -203,13 +200,9 @@ DECLARE_EVENT_CLASS(vb2_event_class,
 
        TP_fast_assign(
                struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-               __entry->minor = q->owner ? q->owner->vdev->minor : -1;
-               __entry->queued_count = q->queued_count;
-               __entry->owned_by_drv_count =
-                       atomic_read(&q->owned_by_drv_count);
-               __entry->index = vb->index;
-               __entry->type = vb->type;
-               __entry->bytesused = vb->planes[0].bytesused;
+               struct v4l2_fh *owner = q->owner;
+
+               __entry->minor = owner ? owner->vdev->minor : -1;
                __entry->flags = vbuf->flags;
                __entry->field = vbuf->field;
                __entry->timestamp = timeval_to_ns(&vbuf->timestamp);
@@ -226,15 +219,10 @@ DECLARE_EVENT_CLASS(vb2_event_class,
                __entry->sequence = vbuf->sequence;
        ),
 
-       TP_printk("minor = %d, queued = %u, owned_by_drv = %d, index = %u, "
-                 "type = %s, bytesused = %u, flags = %s, field = %s, "
+       TP_printk("minor=%d flags = %s, field = %s, "
                  "timestamp = %llu, timecode = { type = %s, flags = %s, "
                  "frames = %u, seconds = %u, minutes = %u, hours = %u, "
                  "userbits = { %u %u %u %u } }, sequence = %u", __entry->minor,
-                 __entry->queued_count,
-                 __entry->owned_by_drv_count,
-                 __entry->index, show_type(__entry->type),
-                 __entry->bytesused,
                  show_flags(__entry->flags),
                  show_field(__entry->field),
                  __entry->timestamp,
@@ -252,22 +240,22 @@ DECLARE_EVENT_CLASS(vb2_event_class,
        )
 )
 
-DEFINE_EVENT(vb2_event_class, vb2_buf_done,
+DEFINE_EVENT(vb2_v4l2_event_class, vb2_v4l2_buf_done,
        TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
        TP_ARGS(q, vb)
 );
 
-DEFINE_EVENT(vb2_event_class, vb2_buf_queue,
+DEFINE_EVENT(vb2_v4l2_event_class, vb2_v4l2_buf_queue,
        TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
        TP_ARGS(q, vb)
 );
 
-DEFINE_EVENT(vb2_event_class, vb2_dqbuf,
+DEFINE_EVENT(vb2_v4l2_event_class, vb2_v4l2_dqbuf,
        TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
        TP_ARGS(q, vb)
 );
 
-DEFINE_EVENT(vb2_event_class, vb2_qbuf,
+DEFINE_EVENT(vb2_v4l2_event_class, vb2_v4l2_qbuf,
        TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
        TP_ARGS(q, vb)
 );
diff --git a/include/trace/events/vb2.h b/include/trace/events/vb2.h
new file mode 100644 (file)
index 0000000..bfeceeb
--- /dev/null
@@ -0,0 +1,65 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM vb2
+
+#if !defined(_TRACE_VB2_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_VB2_H
+
+#include <linux/tracepoint.h>
+#include <media/videobuf2-core.h>
+
+DECLARE_EVENT_CLASS(vb2_event_class,
+       TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
+       TP_ARGS(q, vb),
+
+       TP_STRUCT__entry(
+               __field(void *, owner)
+               __field(u32, queued_count)
+               __field(int, owned_by_drv_count)
+               __field(u32, index)
+               __field(u32, type)
+               __field(u32, bytesused)
+       ),
+
+       TP_fast_assign(
+               __entry->owner = q->owner;
+               __entry->queued_count = q->queued_count;
+               __entry->owned_by_drv_count =
+                       atomic_read(&q->owned_by_drv_count);
+               __entry->index = vb->index;
+               __entry->type = vb->type;
+               __entry->bytesused = vb->planes[0].bytesused;
+       ),
+
+       TP_printk("owner = %p, queued = %u, owned_by_drv = %d, index = %u, "
+                 "type = %u, bytesused = %u", __entry->owner,
+                 __entry->queued_count,
+                 __entry->owned_by_drv_count,
+                 __entry->index, __entry->type,
+                 __entry->bytesused
+       )
+)
+
+DEFINE_EVENT(vb2_event_class, vb2_buf_done,
+       TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
+       TP_ARGS(q, vb)
+);
+
+DEFINE_EVENT(vb2_event_class, vb2_buf_queue,
+       TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
+       TP_ARGS(q, vb)
+);
+
+DEFINE_EVENT(vb2_event_class, vb2_dqbuf,
+       TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
+       TP_ARGS(q, vb)
+);
+
+DEFINE_EVENT(vb2_event_class, vb2_qbuf,
+       TP_PROTO(struct vb2_queue *q, struct vb2_buffer *vb),
+       TP_ARGS(q, vb)
+);
+
+#endif /* if !defined(_TRACE_VB2_H) || defined(TRACE_HEADER_MULTI_READ) */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index d448c536b49d5f782d654caf613aa9a92b456e3a..1bdce501ad6baca443258afc0f8e6210491f9e7d 100644 (file)
@@ -936,6 +936,7 @@ enum v4l2_deemphasis {
 
 #define V4L2_CID_RF_TUNER_BANDWIDTH_AUTO       (V4L2_CID_RF_TUNER_CLASS_BASE + 11)
 #define V4L2_CID_RF_TUNER_BANDWIDTH            (V4L2_CID_RF_TUNER_CLASS_BASE + 12)
+#define V4L2_CID_RF_TUNER_RF_GAIN              (V4L2_CID_RF_TUNER_CLASS_BASE + 32)
 #define V4L2_CID_RF_TUNER_LNA_GAIN_AUTO                (V4L2_CID_RF_TUNER_CLASS_BASE + 41)
 #define V4L2_CID_RF_TUNER_LNA_GAIN             (V4L2_CID_RF_TUNER_CLASS_BASE + 42)
 #define V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO      (V4L2_CID_RF_TUNER_CLASS_BASE + 51)
index 92d65af41631c99e5a8dbff7ae9608b8d05ecd58..a0e87d16b72672d4f7e688a319a08a455824094d 100644 (file)
@@ -145,6 +145,7 @@ enum v4l2_buf_type {
        V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
        V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
        V4L2_BUF_TYPE_SDR_CAPTURE          = 11,
+       V4L2_BUF_TYPE_SDR_OUTPUT           = 12,
        /* Deprecated, do not use */
        V4L2_BUF_TYPE_PRIVATE              = 0x80,
 };
@@ -159,16 +160,20 @@ enum v4l2_buf_type {
         || (type) == V4L2_BUF_TYPE_VIDEO_OVERLAY               \
         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY        \
         || (type) == V4L2_BUF_TYPE_VBI_OUTPUT                  \
-        || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
+        || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT           \
+        || (type) == V4L2_BUF_TYPE_SDR_OUTPUT)
 
 enum v4l2_tuner_type {
        V4L2_TUNER_RADIO             = 1,
        V4L2_TUNER_ANALOG_TV         = 2,
        V4L2_TUNER_DIGITAL_TV        = 3,
-       V4L2_TUNER_ADC               = 4,
+       V4L2_TUNER_SDR               = 4,
        V4L2_TUNER_RF                = 5,
 };
 
+/* Deprecated, do not use */
+#define V4L2_TUNER_ADC  V4L2_TUNER_SDR
+
 enum v4l2_memory {
        V4L2_MEMORY_MMAP             = 1,
        V4L2_MEMORY_USERPTR          = 2,
@@ -432,6 +437,7 @@ struct v4l2_capability {
 
 #define V4L2_CAP_SDR_CAPTURE           0x00100000  /* Is a SDR capture device */
 #define V4L2_CAP_EXT_PIX_FORMAT                0x00200000  /* Supports the extended pixel format */
+#define V4L2_CAP_SDR_OUTPUT            0x00400000  /* Is a SDR output device */
 
 #define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
 #define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
@@ -1587,7 +1593,8 @@ struct v4l2_modulator {
        __u32                   rangelow;
        __u32                   rangehigh;
        __u32                   txsubchans;
-       __u32                   reserved[4];
+       __u32                   type;   /* enum v4l2_tuner_type */
+       __u32                   reserved[3];
 };
 
 /*  Flags for the 'capability' field */
index 9a08fb5c1af640f1f65e5ae6a28cb8b95e6f0ad0..0276d2b5eefe31218adf9475d1f263be6fe979bb 100755 (executable)
@@ -1869,6 +1869,31 @@ sub dump_typedef($$) {
     my $file = shift;
 
     $x =~ s@/\*.*?\*/@@gos;    # strip comments.
+
+    # Parse function prototypes
+    if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/) {
+       # Function typedefs
+       $return_type = $1;
+       $declaration_name = $2;
+       my $args = $3;
+
+       create_parameterlist($args, ',', $file);
+
+       output_declaration($declaration_name,
+                          'function',
+                          {'function' => $declaration_name,
+                           'module' => $modulename,
+                           'functiontype' => $return_type,
+                           'parameterlist' => \@parameterlist,
+                           'parameterdescs' => \%parameterdescs,
+                           'parametertypes' => \%parametertypes,
+                           'sectionlist' => \@sectionlist,
+                           'sections' => \%sections,
+                           'purpose' => $declaration_purpose
+                          });
+       return;
+    }
+
     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
        $x =~ s/\(*.\)\s*;$/;/;
        $x =~ s/\[*.\]\s*;$/;/;