Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (442 commits) [media] videobuf2-dma-contig: make cookie() return a pointer to dma_addr_t [media] sh_mobile_ceu_camera: Do not call vb2's mem_ops directly [media] V4L: soc-camera: explicitly require V4L2_BUF_TYPE_VIDEO_CAPTURE [media] v4l: soc-camera: Store negotiated buffer settings [media] rc: interim support for 32-bit NEC-ish scancodes [media] mceusb: topseed 0x0011 needs gen3 init for tx to work [media] lirc_zilog: error out if buffer read bytes != chunk size [media] lirc: silence some compile warnings [media] hdpvr: use same polling interval as other OS [media] ir-kbd-i2c: pass device code w/key in hauppauge case [media] rc/keymaps: Remove the obsolete rc-rc5-tv keymap [media] remove the old RC_MAP_HAUPPAUGE_NEW RC map [media] rc/keymaps: Rename Hauppauge table as rc-hauppauge [media] rc-rc5-hauppauge-new: Fix Hauppauge Grey mapping [media] rc-rc5-hauppauge-new: Add support for the old Black RC [media] rc-rc5-hauppauge-new: Add the old control to the table [media] rc-winfast: Fix the keycode tables [media] a800: Fix a few wrong IR key assignments [media] opera1: Use multimedia keys instead of an app-specific mapping [media] dw2102: Use multimedia keys instead of an app-specific mapping ... Fix up trivial conflicts (remove/modify and some real conflicts) in: arch/arm/mach-omap2/devices.c drivers/staging/Kconfig drivers/staging/Makefile drivers/staging/dabusb/dabusb.c drivers/staging/dabusb/dabusb.h drivers/staging/easycap/easycap_ioctl.c drivers/staging/usbvideo/usbvideo.c drivers/staging/usbvideo/vicam.c
This commit is contained in:
commit
76d21c5635
|
@ -0,0 +1,6 @@
|
|||
What: /sys/bus/media/devices/.../model
|
||||
Date: January 2011
|
||||
Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
linux-media@vger.kernel.org
|
||||
Description: Contains the device model name in UTF-8. The device version is
|
||||
is not be appended to the model name.
|
|
@ -53,7 +53,10 @@ MAN := $(patsubst %.xml, %.9, $(BOOKS))
|
|||
mandocs: $(MAN)
|
||||
|
||||
build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
|
||||
cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/
|
||||
cp $(srctree)/Documentation/DocBook/dvb/*.png \
|
||||
$(srctree)/Documentation/DocBook/v4l/*.gif \
|
||||
$(srctree)/Documentation/DocBook/v4l/*.png \
|
||||
$(objtree)/Documentation/DocBook/media/
|
||||
|
||||
xmldoclinks:
|
||||
ifneq ($(objtree),$(srctree))
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
<!ENTITY func-select "<link linkend='func-select'><function>select()</function></link>">
|
||||
<!ENTITY func-write "<link linkend='func-write'><function>write()</function></link>">
|
||||
|
||||
<!ENTITY media-func-close "<link linkend='media-func-close'><function>close()</function></link>">
|
||||
<!ENTITY media-func-ioctl "<link linkend='media-func-ioctl'><function>ioctl()</function></link>">
|
||||
<!ENTITY media-func-open "<link linkend='media-func-open'><function>open()</function></link>">
|
||||
|
||||
<!-- Ioctls -->
|
||||
<!ENTITY VIDIOC-CROPCAP "<link linkend='vidioc-cropcap'><constant>VIDIOC_CROPCAP</constant></link>">
|
||||
<!ENTITY VIDIOC-DBG-G-CHIP-IDENT "<link linkend='vidioc-dbg-g-chip-ident'><constant>VIDIOC_DBG_G_CHIP_IDENT</constant></link>">
|
||||
|
@ -82,11 +86,24 @@
|
|||
<!ENTITY VIDIOC-S-PRIORITY "<link linkend='vidioc-g-priority'><constant>VIDIOC_S_PRIORITY</constant></link>">
|
||||
<!ENTITY VIDIOC-S-STD "<link linkend='vidioc-g-std'><constant>VIDIOC_S_STD</constant></link>">
|
||||
<!ENTITY VIDIOC-S-TUNER "<link linkend='vidioc-g-tuner'><constant>VIDIOC_S_TUNER</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-ENUM-FRAME-SIZE "<link linkend='vidioc-subdev-enum-frame-size'><constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-ENUM-MBUS-CODE "<link linkend='vidioc-subdev-enum-mbus-code'><constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-G-CROP "<link linkend='vidioc-subdev-g-crop'><constant>VIDIOC_SUBDEV_G_CROP</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-G-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_G_FMT</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-G-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-S-CROP "<link linkend='vidioc-subdev-g-crop'><constant>VIDIOC_SUBDEV_S_CROP</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-S-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_S_FMT</constant></link>">
|
||||
<!ENTITY VIDIOC-SUBDEV-S-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></link>">
|
||||
<!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>">
|
||||
<!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>">
|
||||
<!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>">
|
||||
<!ENTITY VIDIOC-UNSUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_UNSUBSCRIBE_EVENT</constant></link>">
|
||||
|
||||
<!ENTITY MEDIA-IOC-DEVICE-INFO "<link linkend='media-ioc-device-info'><constant>MEDIA_IOC_DEVICE_INFO</constant></link>">
|
||||
<!ENTITY MEDIA-IOC-ENUM-ENTITIES "<link linkend='media-ioc-enum-entities'><constant>MEDIA_IOC_ENUM_ENTITIES</constant></link>">
|
||||
<!ENTITY MEDIA-IOC-ENUM-LINKS "<link linkend='media-ioc-enum-links'><constant>MEDIA_IOC_ENUM_LINKS</constant></link>">
|
||||
<!ENTITY MEDIA-IOC-SETUP-LINK "<link linkend='media-ioc-setup-link'><constant>MEDIA_IOC_SETUP_LINK</constant></link>">
|
||||
|
||||
<!-- Types -->
|
||||
<!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>">
|
||||
|
||||
|
@ -98,6 +115,7 @@
|
|||
<!ENTITY v4l2-field "enum <link linkend='v4l2-field'>v4l2_field</link>">
|
||||
<!ENTITY v4l2-frmivaltypes "enum <link linkend='v4l2-frmivaltypes'>v4l2_frmivaltypes</link>">
|
||||
<!ENTITY v4l2-frmsizetypes "enum <link linkend='v4l2-frmsizetypes'>v4l2_frmsizetypes</link>">
|
||||
<!ENTITY v4l2-mbus-pixelcode "enum <link linkend='v4l2-mbus-pixelcode'>v4l2_mbus_pixelcode</link>">
|
||||
<!ENTITY v4l2-memory "enum <link linkend='v4l2-memory'>v4l2_memory</link>">
|
||||
<!ENTITY v4l2-mpeg-audio-ac3-bitrate "enum <link linkend='v4l2-mpeg-audio-ac3-bitrate'>v4l2_mpeg_audio_ac3_bitrate</link>">
|
||||
<!ENTITY v4l2-mpeg-audio-crc "enum <link linkend='v4l2-mpeg-audio-crc'>v4l2_mpeg_audio_crc</link>">
|
||||
|
@ -121,6 +139,7 @@
|
|||
<!ENTITY v4l2-mpeg-video-encoding "enum <link linkend='v4l2-mpeg-video-encoding'>v4l2_mpeg_video_encoding</link>">
|
||||
<!ENTITY v4l2-power-line-frequency "enum <link linkend='v4l2-power-line-frequency'>v4l2_power_line_frequency</link>">
|
||||
<!ENTITY v4l2-priority "enum <link linkend='v4l2-priority'>v4l2_priority</link>">
|
||||
<!ENTITY v4l2-subdev-format-whence "enum <link linkend='v4l2-subdev-format-whence'>v4l2_subdev_format_whence</link>">
|
||||
<!ENTITY v4l2-tuner-type "enum <link linkend='v4l2-tuner-type'>v4l2_tuner_type</link>">
|
||||
<!ENTITY v4l2-preemphasis "enum <link linkend='v4l2-preemphasis'>v4l2_preemphasis</link>">
|
||||
|
||||
|
@ -129,6 +148,7 @@
|
|||
<!ENTITY v4l2-audioout "struct <link linkend='v4l2-audioout'>v4l2_audioout</link>">
|
||||
<!ENTITY v4l2-bt-timings "struct <link linkend='v4l2-bt-timings'>v4l2_bt_timings</link>">
|
||||
<!ENTITY v4l2-buffer "struct <link linkend='v4l2-buffer'>v4l2_buffer</link>">
|
||||
<!ENTITY v4l2-plane "struct <link linkend='v4l2-plane'>v4l2_plane</link>">
|
||||
<!ENTITY v4l2-capability "struct <link linkend='v4l2-capability'>v4l2_capability</link>">
|
||||
<!ENTITY v4l2-captureparm "struct <link linkend='v4l2-captureparm'>v4l2_captureparm</link>">
|
||||
<!ENTITY v4l2-clip "struct <link linkend='v4l2-clip'>v4l2_clip</link>">
|
||||
|
@ -162,11 +182,14 @@
|
|||
<!ENTITY v4l2-hw-freq-seek "struct <link linkend='v4l2-hw-freq-seek'>v4l2_hw_freq_seek</link>">
|
||||
<!ENTITY v4l2-input "struct <link linkend='v4l2-input'>v4l2_input</link>">
|
||||
<!ENTITY v4l2-jpegcompression "struct <link linkend='v4l2-jpegcompression'>v4l2_jpegcompression</link>">
|
||||
<!ENTITY v4l2-mbus-framefmt "struct <link linkend='v4l2-mbus-framefmt'>v4l2_mbus_framefmt</link>">
|
||||
<!ENTITY v4l2-modulator "struct <link linkend='v4l2-modulator'>v4l2_modulator</link>">
|
||||
<!ENTITY v4l2-mpeg-vbi-fmt-ivtv "struct <link linkend='v4l2-mpeg-vbi-fmt-ivtv'>v4l2_mpeg_vbi_fmt_ivtv</link>">
|
||||
<!ENTITY v4l2-output "struct <link linkend='v4l2-output'>v4l2_output</link>">
|
||||
<!ENTITY v4l2-outputparm "struct <link linkend='v4l2-outputparm'>v4l2_outputparm</link>">
|
||||
<!ENTITY v4l2-pix-format "struct <link linkend='v4l2-pix-format'>v4l2_pix_format</link>">
|
||||
<!ENTITY v4l2-pix-format-mplane "struct <link linkend='v4l2-pix-format-mplane'>v4l2_pix_format_mplane</link>">
|
||||
<!ENTITY v4l2-plane-pix-format "struct <link linkend='v4l2-plane-pix-format'>v4l2_plane_pix_format</link>">
|
||||
<!ENTITY v4l2-queryctrl "struct <link linkend='v4l2-queryctrl'>v4l2_queryctrl</link>">
|
||||
<!ENTITY v4l2-querymenu "struct <link linkend='v4l2-querymenu'>v4l2_querymenu</link>">
|
||||
<!ENTITY v4l2-rect "struct <link linkend='v4l2-rect'>v4l2_rect</link>">
|
||||
|
@ -174,6 +197,12 @@
|
|||
<!ENTITY v4l2-sliced-vbi-cap "struct <link linkend='v4l2-sliced-vbi-cap'>v4l2_sliced_vbi_cap</link>">
|
||||
<!ENTITY v4l2-sliced-vbi-data "struct <link linkend='v4l2-sliced-vbi-data'>v4l2_sliced_vbi_data</link>">
|
||||
<!ENTITY v4l2-sliced-vbi-format "struct <link linkend='v4l2-sliced-vbi-format'>v4l2_sliced_vbi_format</link>">
|
||||
<!ENTITY v4l2-subdev-frame-interval "struct <link linkend='v4l2-subdev-frame-interval'>v4l2_subdev_frame_interval</link>">
|
||||
<!ENTITY v4l2-subdev-frame-interval-enum "struct <link linkend='v4l2-subdev-frame-interval-enum'>v4l2_subdev_frame_interval_enum</link>">
|
||||
<!ENTITY v4l2-subdev-frame-size-enum "struct <link linkend='v4l2-subdev-frame-size-enum'>v4l2_subdev_frame_size_enum</link>">
|
||||
<!ENTITY v4l2-subdev-crop "struct <link linkend='v4l2-subdev-crop'>v4l2_subdev_crop</link>">
|
||||
<!ENTITY v4l2-subdev-format "struct <link linkend='v4l2-subdev-format'>v4l2_subdev_format</link>">
|
||||
<!ENTITY v4l2-subdev-mbus-code-enum "struct <link linkend='v4l2-subdev-mbus-code-enum'>v4l2_subdev_mbus_code_enum</link>">
|
||||
<!ENTITY v4l2-standard "struct <link linkend='v4l2-standard'>v4l2_standard</link>">
|
||||
<!ENTITY v4l2-streamparm "struct <link linkend='v4l2-streamparm'>v4l2_streamparm</link>">
|
||||
<!ENTITY v4l2-timecode "struct <link linkend='v4l2-timecode'>v4l2_timecode</link>">
|
||||
|
@ -181,6 +210,12 @@
|
|||
<!ENTITY v4l2-vbi-format "struct <link linkend='v4l2-vbi-format'>v4l2_vbi_format</link>">
|
||||
<!ENTITY v4l2-window "struct <link linkend='v4l2-window'>v4l2_window</link>">
|
||||
|
||||
<!ENTITY media-device-info "struct <link linkend='media-device-info'>media_device_info</link>">
|
||||
<!ENTITY media-entity-desc "struct <link linkend='media-entity-desc'>media_entity_desc</link>">
|
||||
<!ENTITY media-links-enum "struct <link linkend='media-links-enum'>media_links_enum</link>">
|
||||
<!ENTITY media-pad-desc "struct <link linkend='media-pad-desc'>media_pad_desc</link>">
|
||||
<!ENTITY media-link-desc "struct <link linkend='media-link-desc'>media_link_desc</link>">
|
||||
|
||||
<!-- Error Codes -->
|
||||
<!ENTITY EACCES "<errorcode>EACCES</errorcode> error code">
|
||||
<!ENTITY EAGAIN "<errorcode>EAGAIN</errorcode> error code">
|
||||
|
@ -197,11 +232,13 @@
|
|||
<!ENTITY ENXIO "<errorcode>ENXIO</errorcode> error code">
|
||||
<!ENTITY EMFILE "<errorcode>EMFILE</errorcode> error code">
|
||||
<!ENTITY EPERM "<errorcode>EPERM</errorcode> error code">
|
||||
<!ENTITY EPIPE "<errorcode>EPIPE</errorcode> error code">
|
||||
<!ENTITY ERANGE "<errorcode>ERANGE</errorcode> error code">
|
||||
|
||||
<!-- Subsections -->
|
||||
<!ENTITY sub-biblio SYSTEM "v4l/biblio.xml">
|
||||
<!ENTITY sub-common SYSTEM "v4l/common.xml">
|
||||
<!ENTITY sub-planar-apis SYSTEM "v4l/planar-apis.xml">
|
||||
<!ENTITY sub-compat SYSTEM "v4l/compat.xml">
|
||||
<!ENTITY sub-controls SYSTEM "v4l/controls.xml">
|
||||
<!ENTITY sub-dev-capture SYSTEM "v4l/dev-capture.xml">
|
||||
|
@ -215,6 +252,7 @@
|
|||
<!ENTITY sub-dev-raw-vbi SYSTEM "v4l/dev-raw-vbi.xml">
|
||||
<!ENTITY sub-dev-rds SYSTEM "v4l/dev-rds.xml">
|
||||
<!ENTITY sub-dev-sliced-vbi SYSTEM "v4l/dev-sliced-vbi.xml">
|
||||
<!ENTITY sub-dev-subdev SYSTEM "v4l/dev-subdev.xml">
|
||||
<!ENTITY sub-dev-teletext SYSTEM "v4l/dev-teletext.xml">
|
||||
<!ENTITY sub-driver SYSTEM "v4l/driver.xml">
|
||||
<!ENTITY sub-libv4l SYSTEM "v4l/libv4l.xml">
|
||||
|
@ -233,6 +271,8 @@
|
|||
<!ENTITY sub-io SYSTEM "v4l/io.xml">
|
||||
<!ENTITY sub-grey SYSTEM "v4l/pixfmt-grey.xml">
|
||||
<!ENTITY sub-nv12 SYSTEM "v4l/pixfmt-nv12.xml">
|
||||
<!ENTITY sub-nv12m SYSTEM "v4l/pixfmt-nv12m.xml">
|
||||
<!ENTITY sub-nv12mt SYSTEM "v4l/pixfmt-nv12mt.xml">
|
||||
<!ENTITY sub-nv16 SYSTEM "v4l/pixfmt-nv16.xml">
|
||||
<!ENTITY sub-packed-rgb SYSTEM "v4l/pixfmt-packed-rgb.xml">
|
||||
<!ENTITY sub-packed-yuv SYSTEM "v4l/pixfmt-packed-yuv.xml">
|
||||
|
@ -247,6 +287,7 @@
|
|||
<!ENTITY sub-yuv410 SYSTEM "v4l/pixfmt-yuv410.xml">
|
||||
<!ENTITY sub-yuv411p SYSTEM "v4l/pixfmt-yuv411p.xml">
|
||||
<!ENTITY sub-yuv420 SYSTEM "v4l/pixfmt-yuv420.xml">
|
||||
<!ENTITY sub-yuv420m SYSTEM "v4l/pixfmt-yuv420m.xml">
|
||||
<!ENTITY sub-yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
|
||||
<!ENTITY sub-yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
|
||||
<!ENTITY sub-yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
|
||||
|
@ -298,6 +339,13 @@
|
|||
<!ENTITY sub-reqbufs SYSTEM "v4l/vidioc-reqbufs.xml">
|
||||
<!ENTITY sub-s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml">
|
||||
<!ENTITY sub-streamon SYSTEM "v4l/vidioc-streamon.xml">
|
||||
<!ENTITY sub-subdev-enum-frame-interval SYSTEM "v4l/vidioc-subdev-enum-frame-interval.xml">
|
||||
<!ENTITY sub-subdev-enum-frame-size SYSTEM "v4l/vidioc-subdev-enum-frame-size.xml">
|
||||
<!ENTITY sub-subdev-enum-mbus-code SYSTEM "v4l/vidioc-subdev-enum-mbus-code.xml">
|
||||
<!ENTITY sub-subdev-formats SYSTEM "v4l/subdev-formats.xml">
|
||||
<!ENTITY sub-subdev-g-crop SYSTEM "v4l/vidioc-subdev-g-crop.xml">
|
||||
<!ENTITY sub-subdev-g-fmt SYSTEM "v4l/vidioc-subdev-g-fmt.xml">
|
||||
<!ENTITY sub-subdev-g-frame-interval SYSTEM "v4l/vidioc-subdev-g-frame-interval.xml">
|
||||
<!ENTITY sub-capture-c SYSTEM "v4l/capture.c.xml">
|
||||
<!ENTITY sub-keytable-c SYSTEM "v4l/keytable.c.xml">
|
||||
<!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml">
|
||||
|
@ -321,6 +369,15 @@
|
|||
<!ENTITY sub-media-entities SYSTEM "media-entities.tmpl">
|
||||
<!ENTITY sub-media-indices SYSTEM "media-indices.tmpl">
|
||||
|
||||
<!ENTITY sub-media-controller SYSTEM "v4l/media-controller.xml">
|
||||
<!ENTITY sub-media-open SYSTEM "v4l/media-func-open.xml">
|
||||
<!ENTITY sub-media-close SYSTEM "v4l/media-func-close.xml">
|
||||
<!ENTITY sub-media-ioctl SYSTEM "v4l/media-func-ioctl.xml">
|
||||
<!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml">
|
||||
<!ENTITY sub-media-ioc-enum-entities SYSTEM "v4l/media-ioc-enum-entities.xml">
|
||||
<!ENTITY sub-media-ioc-enum-links SYSTEM "v4l/media-ioc-enum-links.xml">
|
||||
<!ENTITY sub-media-ioc-setup-link SYSTEM "v4l/media-ioc-setup-link.xml">
|
||||
|
||||
<!-- Function Reference -->
|
||||
<!ENTITY close SYSTEM "v4l/func-close.xml">
|
||||
<!ENTITY ioctl SYSTEM "v4l/func-ioctl.xml">
|
||||
|
@ -333,6 +390,7 @@
|
|||
<!ENTITY write SYSTEM "v4l/func-write.xml">
|
||||
<!ENTITY grey SYSTEM "v4l/pixfmt-grey.xml">
|
||||
<!ENTITY nv12 SYSTEM "v4l/pixfmt-nv12.xml">
|
||||
<!ENTITY nv12m SYSTEM "v4l/pixfmt-nv12m.xml">
|
||||
<!ENTITY nv16 SYSTEM "v4l/pixfmt-nv16.xml">
|
||||
<!ENTITY packed-rgb SYSTEM "v4l/pixfmt-packed-rgb.xml">
|
||||
<!ENTITY packed-yuv SYSTEM "v4l/pixfmt-packed-yuv.xml">
|
||||
|
@ -347,6 +405,7 @@
|
|||
<!ENTITY yuv410 SYSTEM "v4l/pixfmt-yuv410.xml">
|
||||
<!ENTITY yuv411p SYSTEM "v4l/pixfmt-yuv411p.xml">
|
||||
<!ENTITY yuv420 SYSTEM "v4l/pixfmt-yuv420.xml">
|
||||
<!ENTITY yuv420m SYSTEM "v4l/pixfmt-yuv420m.xml">
|
||||
<!ENTITY yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
|
||||
<!ENTITY yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
|
||||
<!ENTITY yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
|
||||
|
|
|
@ -106,6 +106,9 @@ Foundation. A copy of the license is included in the chapter entitled
|
|||
&sub-remote_controllers;
|
||||
</chapter>
|
||||
</part>
|
||||
<part id="media_common">
|
||||
&sub-media-controller;
|
||||
</part>
|
||||
|
||||
&sub-fdl-appendix;
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 9.5 KiB |
|
@ -846,6 +846,8 @@ conversion routine or library for integration into applications.</para>
|
|||
</section>
|
||||
</section>
|
||||
|
||||
&sub-planar-apis;
|
||||
|
||||
<section id="crop">
|
||||
<title>Image Cropping, Insertion and Scaling</title>
|
||||
|
||||
|
|
|
@ -1711,8 +1711,8 @@ ioctl would enumerate the available audio inputs. An ioctl to
|
|||
determine the current audio input, if more than one combines with the
|
||||
current video input, did not exist. So
|
||||
<constant>VIDIOC_G_AUDIO</constant> was renamed to
|
||||
<constant>VIDIOC_G_AUDIO_OLD</constant>, this ioctl will be removed in
|
||||
the future. The &VIDIOC-ENUMAUDIO; ioctl was added to enumerate
|
||||
<constant>VIDIOC_G_AUDIO_OLD</constant>, this ioctl was removed on
|
||||
Kernel 2.6.39. The &VIDIOC-ENUMAUDIO; ioctl was added to enumerate
|
||||
audio inputs, while &VIDIOC-G-AUDIO; now reports the current audio
|
||||
input.</para>
|
||||
<para>The same changes were made to &VIDIOC-G-AUDOUT; and
|
||||
|
@ -1726,7 +1726,7 @@ must be updated to successfully compile again.</para>
|
|||
<para>The &VIDIOC-OVERLAY; ioctl was incorrectly defined with
|
||||
write-read parameter. It was changed to write-only, while the write-read
|
||||
version was renamed to <constant>VIDIOC_OVERLAY_OLD</constant>. The old
|
||||
ioctl will be removed in the future. Until further the "videodev"
|
||||
ioctl was removed on Kernel 2.6.39. Until further the "videodev"
|
||||
kernel module will automatically translate to the new version, so drivers
|
||||
must be recompiled, but not applications.</para>
|
||||
</listitem>
|
||||
|
@ -1744,7 +1744,7 @@ surface can be seen.</para>
|
|||
defined with write-only parameter, inconsistent with other ioctls
|
||||
modifying their argument. They were changed to write-read, while a
|
||||
<constant>_OLD</constant> suffix was added to the write-only versions.
|
||||
The old ioctls will be removed in the future. Drivers and
|
||||
The old ioctls were removed on Kernel 2.6.39. Drivers and
|
||||
applications assuming a constant parameter need an update.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
@ -1815,8 +1815,8 @@ yet to be addressed, for details see <xref
|
|||
<para>The &VIDIOC-CROPCAP; ioctl was incorrectly defined
|
||||
with read-only parameter. It is now defined as write-read ioctl, while
|
||||
the read-only version was renamed to
|
||||
<constant>VIDIOC_CROPCAP_OLD</constant>. The old ioctl will be removed
|
||||
in the future.</para>
|
||||
<constant>VIDIOC_CROPCAP_OLD</constant>. The old ioctl was removed
|
||||
on Kernel 2.6.39.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
|
@ -2353,6 +2353,20 @@ that used it. It was originally scheduled for removal in 2.6.35.
|
|||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
<section>
|
||||
<title>V4L2 in Linux 2.6.39</title>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>The old VIDIOC_*_OLD symbols and V4L1 support were removed.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Multi-planar API added. Does not affect the compatibility of
|
||||
current drivers and applications. See
|
||||
<link linkend="planar-apis">multi-planar API</link>
|
||||
for details.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
|
||||
<section id="other">
|
||||
<title>Relation of V4L2 to other Linux multimedia APIs</title>
|
||||
|
|
|
@ -18,7 +18,8 @@ files are used for video output devices.</para>
|
|||
<title>Querying Capabilities</title>
|
||||
|
||||
<para>Devices supporting the video capture interface set the
|
||||
<constant>V4L2_CAP_VIDEO_CAPTURE</constant> flag in the
|
||||
<constant>V4L2_CAP_VIDEO_CAPTURE</constant> or
|
||||
<constant>V4L2_CAP_VIDEO_CAPTURE_MPLANE</constant> flag in the
|
||||
<structfield>capabilities</structfield> field of &v4l2-capability;
|
||||
returned by the &VIDIOC-QUERYCAP; ioctl. As secondary device functions
|
||||
they may also support the <link linkend="overlay">video overlay</link>
|
||||
|
@ -64,9 +65,11 @@ linkend="crop" />.</para>
|
|||
|
||||
<para>To query the current image format applications set the
|
||||
<structfield>type</structfield> field of a &v4l2-format; to
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> and call the
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> or
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> and call the
|
||||
&VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill
|
||||
the &v4l2-pix-format; <structfield>pix</structfield> member of the
|
||||
the &v4l2-pix-format; <structfield>pix</structfield> or the
|
||||
&v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member of the
|
||||
<structfield>fmt</structfield> union.</para>
|
||||
|
||||
<para>To request different parameters applications set the
|
||||
|
@ -84,8 +87,8 @@ adjust the parameters and finally return the actual parameters as
|
|||
without disabling I/O or possibly time consuming hardware
|
||||
preparations.</para>
|
||||
|
||||
<para>The contents of &v4l2-pix-format; are discussed in <xref
|
||||
linkend="pixfmt" />. See also the specification of the
|
||||
<para>The contents of &v4l2-pix-format; and &v4l2-pix-format-mplane;
|
||||
are discussed in <xref linkend="pixfmt" />. See also the specification of the
|
||||
<constant>VIDIOC_G_FMT</constant>, <constant>VIDIOC_S_FMT</constant>
|
||||
and <constant>VIDIOC_TRY_FMT</constant> ioctls for details. Video
|
||||
capture devices must implement both the
|
||||
|
|
|
@ -17,7 +17,8 @@ files are used for video capture devices.</para>
|
|||
<title>Querying Capabilities</title>
|
||||
|
||||
<para>Devices supporting the video output interface set the
|
||||
<constant>V4L2_CAP_VIDEO_OUTPUT</constant> flag in the
|
||||
<constant>V4L2_CAP_VIDEO_OUTPUT</constant> or
|
||||
<constant>V4L2_CAP_VIDEO_OUTPUT_MPLANE</constant> flag in the
|
||||
<structfield>capabilities</structfield> field of &v4l2-capability;
|
||||
returned by the &VIDIOC-QUERYCAP; ioctl. As secondary device functions
|
||||
they may also support the <link linkend="raw-vbi">raw VBI
|
||||
|
@ -60,9 +61,11 @@ linkend="crop" />.</para>
|
|||
|
||||
<para>To query the current image format applications set the
|
||||
<structfield>type</structfield> field of a &v4l2-format; to
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> and call the
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> or
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant> and call the
|
||||
&VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill
|
||||
the &v4l2-pix-format; <structfield>pix</structfield> member of the
|
||||
the &v4l2-pix-format; <structfield>pix</structfield> or the
|
||||
&v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member of the
|
||||
<structfield>fmt</structfield> union.</para>
|
||||
|
||||
<para>To request different parameters applications set the
|
||||
|
@ -80,8 +83,8 @@ adjust the parameters and finally return the actual parameters as
|
|||
without disabling I/O or possibly time consuming hardware
|
||||
preparations.</para>
|
||||
|
||||
<para>The contents of &v4l2-pix-format; are discussed in <xref
|
||||
linkend="pixfmt" />. See also the specification of the
|
||||
<para>The contents of &v4l2-pix-format; and &v4l2-pix-format-mplane;
|
||||
are discussed in <xref linkend="pixfmt" />. See also the specification of the
|
||||
<constant>VIDIOC_G_FMT</constant>, <constant>VIDIOC_S_FMT</constant>
|
||||
and <constant>VIDIOC_TRY_FMT</constant> ioctls for details. Video
|
||||
output devices must implement both the
|
||||
|
|
|
@ -0,0 +1,313 @@
|
|||
<title>Sub-device Interface</title>
|
||||
|
||||
<note>
|
||||
<title>Experimental</title>
|
||||
<para>This is an <link linkend="experimental">experimental</link>
|
||||
interface and may change in the future.</para>
|
||||
</note>
|
||||
|
||||
<para>The complex nature of V4L2 devices, where hardware is often made of
|
||||
several integrated circuits that need to interact with each other in a
|
||||
controlled way, leads to complex V4L2 drivers. The drivers usually reflect
|
||||
the hardware model in software, and model the different hardware components
|
||||
as software blocks called sub-devices.</para>
|
||||
|
||||
<para>V4L2 sub-devices are usually kernel-only objects. If the V4L2 driver
|
||||
implements the media device API, they will automatically inherit from media
|
||||
entities. Applications will be able to enumerate the sub-devices and discover
|
||||
the hardware topology using the media entities, pads and links enumeration
|
||||
API.</para>
|
||||
|
||||
<para>In addition to make sub-devices discoverable, drivers can also choose
|
||||
to make them directly configurable by applications. When both the sub-device
|
||||
driver and the V4L2 device driver support this, sub-devices will feature a
|
||||
character device node on which ioctls can be called to
|
||||
<itemizedlist>
|
||||
<listitem><para>query, read and write sub-devices controls</para></listitem>
|
||||
<listitem><para>subscribe and unsubscribe to events and retrieve them</para></listitem>
|
||||
<listitem><para>negotiate image formats on individual pads</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>Sub-device character device nodes, conventionally named
|
||||
<filename>/dev/v4l-subdev*</filename>, use major number 81.</para>
|
||||
|
||||
<section>
|
||||
<title>Controls</title>
|
||||
<para>Most V4L2 controls are implemented by sub-device hardware. Drivers
|
||||
usually merge all controls and expose them through video device nodes.
|
||||
Applications can control all sub-devices through a single interface.</para>
|
||||
|
||||
<para>Complex devices sometimes implement the same control in different
|
||||
pieces of hardware. This situation is common in embedded platforms, where
|
||||
both sensors and image processing hardware implement identical functions,
|
||||
such as contrast adjustment, white balance or faulty pixels correction. As
|
||||
the V4L2 controls API doesn't support several identical controls in a single
|
||||
device, all but one of the identical controls are hidden.</para>
|
||||
|
||||
<para>Applications can access those hidden controls through the sub-device
|
||||
node with the V4L2 control API described in <xref linkend="control" />. The
|
||||
ioctls behave identically as when issued on V4L2 device nodes, with the
|
||||
exception that they deal only with controls implemented in the sub-device.
|
||||
</para>
|
||||
|
||||
<para>Depending on the driver, those controls might also be exposed through
|
||||
one (or several) V4L2 device nodes.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Events</title>
|
||||
<para>V4L2 sub-devices can notify applications of events as described in
|
||||
<xref linkend="event" />. The API behaves identically as when used on V4L2
|
||||
device nodes, with the exception that it only deals with events generated by
|
||||
the sub-device. Depending on the driver, those events might also be reported
|
||||
on one (or several) V4L2 device nodes.</para>
|
||||
</section>
|
||||
|
||||
<section id="pad-level-formats">
|
||||
<title>Pad-level Formats</title>
|
||||
|
||||
<warning><para>Pad-level formats are only applicable to very complex device that
|
||||
need to expose low-level format configuration to user space. Generic V4L2
|
||||
applications do <emphasis>not</emphasis> need to use the API described in
|
||||
this section.</para></warning>
|
||||
|
||||
<note><para>For the purpose of this section, the term
|
||||
<wordasword>format</wordasword> means the combination of media bus data
|
||||
format, frame width and frame height.</para></note>
|
||||
|
||||
<para>Image formats are typically negotiated on video capture and output
|
||||
devices using the <link linkend="crop">cropping and scaling</link> ioctls.
|
||||
The driver is responsible for configuring every block in the video pipeline
|
||||
according to the requested format at the pipeline input and/or
|
||||
output.</para>
|
||||
|
||||
<para>For complex devices, such as often found in embedded systems,
|
||||
identical image sizes at the output of a pipeline can be achieved using
|
||||
different hardware configurations. One such example is shown on
|
||||
<xref linkend="pipeline-scaling" />, where
|
||||
image scaling can be performed on both the video sensor and the host image
|
||||
processing hardware.</para>
|
||||
|
||||
<figure id="pipeline-scaling">
|
||||
<title>Image Format Negotation on Pipelines</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="pipeline.pdf" format="PS" />
|
||||
</imageobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="pipeline.png" format="PNG" />
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>High quality and high speed pipeline configuration</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
|
||||
<para>The sensor scaler is usually of less quality than the host scaler, but
|
||||
scaling on the sensor is required to achieve higher frame rates. Depending
|
||||
on the use case (quality vs. speed), the pipeline must be configured
|
||||
differently. Applications need to configure the formats at every point in
|
||||
the pipeline explicitly.</para>
|
||||
|
||||
<para>Drivers that implement the <link linkend="media-controller-intro">media
|
||||
API</link> can expose pad-level image format configuration to applications.
|
||||
When they do, applications can use the &VIDIOC-SUBDEV-G-FMT; and
|
||||
&VIDIOC-SUBDEV-S-FMT; ioctls. to negotiate formats on a per-pad basis.</para>
|
||||
|
||||
<para>Applications are responsible for configuring coherent parameters on
|
||||
the whole pipeline and making sure that connected pads have compatible
|
||||
formats. The pipeline is checked for formats mismatch at &VIDIOC-STREAMON;
|
||||
time, and an &EPIPE; is then returned if the configuration is
|
||||
invalid.</para>
|
||||
|
||||
<para>Pad-level image format configuration support can be tested by calling
|
||||
the &VIDIOC-SUBDEV-G-FMT; ioctl on pad 0. If the driver returns an &EINVAL;
|
||||
pad-level format configuration is not supported by the sub-device.</para>
|
||||
|
||||
<section>
|
||||
<title>Format Negotiation</title>
|
||||
|
||||
<para>Acceptable formats on pads can (and usually do) depend on a number
|
||||
of external parameters, such as formats on other pads, active links, or
|
||||
even controls. Finding a combination of formats on all pads in a video
|
||||
pipeline, acceptable to both application and driver, can't rely on formats
|
||||
enumeration only. A format negotiation mechanism is required.</para>
|
||||
|
||||
<para>Central to the format negotiation mechanism are the get/set format
|
||||
operations. When called with the <structfield>which</structfield> argument
|
||||
set to <constant>V4L2_SUBDEV_FORMAT_TRY</constant>, the
|
||||
&VIDIOC-SUBDEV-G-FMT; and &VIDIOC-SUBDEV-S-FMT; ioctls operate on a set of
|
||||
formats parameters that are not connected to the hardware configuration.
|
||||
Modifying those 'try' formats leaves the device state untouched (this
|
||||
applies to both the software state stored in the driver and the hardware
|
||||
state stored in the device itself).</para>
|
||||
|
||||
<para>While not kept as part of the device state, try formats are stored
|
||||
in the sub-device file handles. A &VIDIOC-SUBDEV-G-FMT; call will return
|
||||
the last try format set <emphasis>on the same sub-device file
|
||||
handle</emphasis>. Several applications querying the same sub-device at
|
||||
the same time will thus not interact with each other.</para>
|
||||
|
||||
<para>To find out whether a particular format is supported by the device,
|
||||
applications use the &VIDIOC-SUBDEV-S-FMT; ioctl. Drivers verify and, if
|
||||
needed, change the requested <structfield>format</structfield> based on
|
||||
device requirements and return the possibly modified value. Applications
|
||||
can then choose to try a different format or accept the returned value and
|
||||
continue.</para>
|
||||
|
||||
<para>Formats returned by the driver during a negotiation iteration are
|
||||
guaranteed to be supported by the device. In particular, drivers guarantee
|
||||
that a returned format will not be further changed if passed to an
|
||||
&VIDIOC-SUBDEV-S-FMT; call as-is (as long as external parameters, such as
|
||||
formats on other pads or links' configuration are not changed).</para>
|
||||
|
||||
<para>Drivers automatically propagate formats inside sub-devices. When a
|
||||
try or active format is set on a pad, corresponding formats on other pads
|
||||
of the same sub-device can be modified by the driver. Drivers are free to
|
||||
modify formats as required by the device. However, they should comply with
|
||||
the following rules when possible:
|
||||
<itemizedlist>
|
||||
<listitem><para>Formats should be propagated from sink pads to source pads.
|
||||
Modifying a format on a source pad should not modify the format on any
|
||||
sink pad.</para></listitem>
|
||||
<listitem><para>Sub-devices that scale frames using variable scaling factors
|
||||
should reset the scale factors to default values when sink pads formats
|
||||
are modified. If the 1:1 scaling ratio is supported, this means that
|
||||
source pads formats should be reset to the sink pads formats.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>Formats are not propagated across links, as that would involve
|
||||
propagating them from one sub-device file handle to another. Applications
|
||||
must then take care to configure both ends of every link explicitly with
|
||||
compatible formats. Identical formats on the two ends of a link are
|
||||
guaranteed to be compatible. Drivers are free to accept different formats
|
||||
matching device requirements as being compatible.</para>
|
||||
|
||||
<para><xref linkend="sample-pipeline-config" />
|
||||
shows a sample configuration sequence for the pipeline described in
|
||||
<xref linkend="pipeline-scaling" /> (table
|
||||
columns list entity names and pad numbers).</para>
|
||||
|
||||
<table pgwide="0" frame="none" id="sample-pipeline-config">
|
||||
<title>Sample Pipeline Configuration</title>
|
||||
<tgroup cols="3">
|
||||
<colspec colname="what"/>
|
||||
<colspec colname="sensor-0" />
|
||||
<colspec colname="frontend-0" />
|
||||
<colspec colname="frontend-1" />
|
||||
<colspec colname="scaler-0" />
|
||||
<colspec colname="scaler-1" />
|
||||
<thead>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>Sensor/0</entry>
|
||||
<entry>Frontend/0</entry>
|
||||
<entry>Frontend/1</entry>
|
||||
<entry>Scaler/0</entry>
|
||||
<entry>Scaler/1</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>Initial state</entry>
|
||||
<entry>2048x1536</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Configure frontend input</entry>
|
||||
<entry>2048x1536</entry>
|
||||
<entry><emphasis>2048x1536</emphasis></entry>
|
||||
<entry><emphasis>2046x1534</emphasis></entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Configure scaler input</entry>
|
||||
<entry>2048x1536</entry>
|
||||
<entry>2048x1536</entry>
|
||||
<entry>2046x1534</entry>
|
||||
<entry><emphasis>2046x1534</emphasis></entry>
|
||||
<entry><emphasis>2046x1534</emphasis></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Configure scaler output</entry>
|
||||
<entry>2048x1536</entry>
|
||||
<entry>2048x1536</entry>
|
||||
<entry>2046x1534</entry>
|
||||
<entry>2046x1534</entry>
|
||||
<entry><emphasis>1280x960</emphasis></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
<orderedlist>
|
||||
<listitem><para>Initial state. The sensor output is set to its native 3MP
|
||||
resolution. Resolutions on the host frontend and scaler input and output
|
||||
pads are undefined.</para></listitem>
|
||||
<listitem><para>The application configures the frontend input pad resolution to
|
||||
2048x1536. The driver propagates the format to the frontend output pad.
|
||||
Note that the propagated output format can be different, as in this case,
|
||||
than the input format, as the hardware might need to crop pixels (for
|
||||
instance when converting a Bayer filter pattern to RGB or YUV).</para></listitem>
|
||||
<listitem><para>The application configures the scaler input pad resolution to
|
||||
2046x1534 to match the frontend output resolution. The driver propagates
|
||||
the format to the scaler output pad.</para></listitem>
|
||||
<listitem><para>The application configures the scaler output pad resolution to
|
||||
1280x960.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>When satisfied with the try results, applications can set the active
|
||||
formats by setting the <structfield>which</structfield> argument to
|
||||
<constant>V4L2_SUBDEV_FORMAT_TRY</constant>. Active formats are changed
|
||||
exactly as try formats by drivers. To avoid modifying the hardware state
|
||||
during format negotiation, applications should negotiate try formats first
|
||||
and then modify the active settings using the try formats returned during
|
||||
the last negotiation iteration. This guarantees that the active format
|
||||
will be applied as-is by the driver without being modified.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Cropping and scaling</title>
|
||||
|
||||
<para>Many sub-devices support cropping frames on their input or output
|
||||
pads (or possible even on both). Cropping is used to select the area of
|
||||
interest in an image, typically on a video sensor or video decoder. It can
|
||||
also be used as part of digital zoom implementations to select the area of
|
||||
the image that will be scaled up.</para>
|
||||
|
||||
<para>Crop settings are defined by a crop rectangle and represented in a
|
||||
&v4l2-rect; by the coordinates of the top left corner and the rectangle
|
||||
size. Both the coordinates and sizes are expressed in pixels.</para>
|
||||
|
||||
<para>The crop rectangle is retrieved and set using the
|
||||
&VIDIOC-SUBDEV-G-CROP; and &VIDIOC-SUBDEV-S-CROP; ioctls. Like for pad
|
||||
formats, drivers store try and active crop rectangles. The format
|
||||
negotiation mechanism applies to crop settings as well.</para>
|
||||
|
||||
<para>On input pads, cropping is applied relatively to the current pad
|
||||
format. The pad format represents the image size as received by the
|
||||
sub-device from the previous block in the pipeline, and the crop rectangle
|
||||
represents the sub-image that will be transmitted further inside the
|
||||
sub-device for processing. The crop rectangle be entirely containted
|
||||
inside the input image size.</para>
|
||||
|
||||
<para>Input crop rectangle are reset to their default value when the input
|
||||
image format is modified. Drivers should use the input image size as the
|
||||
crop rectangle default value, but hardware requirements may prevent this.
|
||||
</para>
|
||||
|
||||
<para>Cropping behaviour on output pads is not defined.</para>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
&sub-subdev-formats;
|
|
@ -45,7 +45,10 @@ just specify a <constant>NULL</constant> pointer here.</para>
|
|||
<listitem>
|
||||
<para>Length of the memory area to map. This must be the
|
||||
same value as returned by the driver in the &v4l2-buffer;
|
||||
<structfield>length</structfield> field.</para>
|
||||
<structfield>length</structfield> field for the
|
||||
single-planar API, and the same value as returned by the driver
|
||||
in the &v4l2-plane; <structfield>length</structfield> field for the
|
||||
multi-planar API.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
@ -106,7 +109,10 @@ flag.</para>
|
|||
<listitem>
|
||||
<para>Offset of the buffer in device memory. This must be the
|
||||
same value as returned by the driver in the &v4l2-buffer;
|
||||
<structfield>m</structfield> union <structfield>offset</structfield> field.</para>
|
||||
<structfield>m</structfield> union <structfield>offset</structfield> field for
|
||||
the single-planar API, and the same value as returned by the driver
|
||||
in the &v4l2-plane; <structfield>m</structfield> union
|
||||
<structfield>mem_offset</structfield> field for the multi-planar API.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
|
|
@ -37,7 +37,8 @@
|
|||
<para>Length of the mapped buffer. This must be the same
|
||||
value as given to <function>mmap()</function> and returned by the
|
||||
driver in the &v4l2-buffer; <structfield>length</structfield>
|
||||
field.</para>
|
||||
field for the single-planar API and in the &v4l2-plane;
|
||||
<structfield>length</structfield> field for the multi-planar API.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
|
|
@ -121,18 +121,22 @@ mapped.</para>
|
|||
<para>Before applications can access the buffers they must map
|
||||
them into their address space with the &func-mmap; function. The
|
||||
location of the buffers in device memory can be determined with the
|
||||
&VIDIOC-QUERYBUF; ioctl. The <structfield>m.offset</structfield> and
|
||||
<structfield>length</structfield> returned in a &v4l2-buffer; are
|
||||
passed as sixth and second parameter to the
|
||||
<function>mmap()</function> function. The offset and length values
|
||||
must not be modified. Remember the buffers are allocated in physical
|
||||
memory, as opposed to virtual memory which can be swapped out to disk.
|
||||
Applications should free the buffers as soon as possible with the
|
||||
&func-munmap; function.</para>
|
||||
&VIDIOC-QUERYBUF; ioctl. In the single-planar API case, the
|
||||
<structfield>m.offset</structfield> and <structfield>length</structfield>
|
||||
returned in a &v4l2-buffer; are passed as sixth and second parameter to the
|
||||
<function>mmap()</function> function. When using the multi-planar API,
|
||||
struct &v4l2-buffer; contains an array of &v4l2-plane; structures, each
|
||||
containing its own <structfield>m.offset</structfield> and
|
||||
<structfield>length</structfield>. When using the multi-planar API, every
|
||||
plane of every buffer has to be mapped separately, so the number of
|
||||
calls to &func-mmap; should be equal to number of buffers times number of
|
||||
planes in each buffer. The offset and length values must not be modified.
|
||||
Remember, the buffers are allocated in physical memory, as opposed to virtual
|
||||
memory, which can be swapped out to disk. Applications should free the buffers
|
||||
as soon as possible with the &func-munmap; function.</para>
|
||||
|
||||
<example>
|
||||
<title>Mapping buffers</title>
|
||||
|
||||
<title>Mapping buffers in the single-planar API</title>
|
||||
<programlisting>
|
||||
&v4l2-requestbuffers; reqbuf;
|
||||
struct {
|
||||
|
@ -141,63 +145,145 @@ struct {
|
|||
} *buffers;
|
||||
unsigned int i;
|
||||
|
||||
memset (&reqbuf, 0, sizeof (reqbuf));
|
||||
memset(&reqbuf, 0, sizeof(reqbuf));
|
||||
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
reqbuf.memory = V4L2_MEMORY_MMAP;
|
||||
reqbuf.count = 20;
|
||||
|
||||
if (-1 == ioctl (fd, &VIDIOC-REQBUFS;, &reqbuf)) {
|
||||
if (errno == EINVAL)
|
||||
printf ("Video capturing or mmap-streaming is not supported\n");
|
||||
printf("Video capturing or mmap-streaming is not supported\n");
|
||||
else
|
||||
perror ("VIDIOC_REQBUFS");
|
||||
perror("VIDIOC_REQBUFS");
|
||||
|
||||
exit (EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* We want at least five buffers. */
|
||||
|
||||
if (reqbuf.count < 5) {
|
||||
/* You may need to free the buffers here. */
|
||||
printf ("Not enough buffer memory\n");
|
||||
exit (EXIT_FAILURE);
|
||||
printf("Not enough buffer memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
buffers = calloc (reqbuf.count, sizeof (*buffers));
|
||||
assert (buffers != NULL);
|
||||
buffers = calloc(reqbuf.count, sizeof(*buffers));
|
||||
assert(buffers != NULL);
|
||||
|
||||
for (i = 0; i < reqbuf.count; i++) {
|
||||
&v4l2-buffer; buffer;
|
||||
|
||||
memset (&buffer, 0, sizeof (buffer));
|
||||
memset(&buffer, 0, sizeof(buffer));
|
||||
buffer.type = reqbuf.type;
|
||||
buffer.memory = V4L2_MEMORY_MMAP;
|
||||
buffer.index = i;
|
||||
|
||||
if (-1 == ioctl (fd, &VIDIOC-QUERYBUF;, &buffer)) {
|
||||
perror ("VIDIOC_QUERYBUF");
|
||||
exit (EXIT_FAILURE);
|
||||
perror("VIDIOC_QUERYBUF");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
buffers[i].length = buffer.length; /* remember for munmap() */
|
||||
|
||||
buffers[i].start = mmap (NULL, buffer.length,
|
||||
PROT_READ | PROT_WRITE, /* recommended */
|
||||
MAP_SHARED, /* recommended */
|
||||
fd, buffer.m.offset);
|
||||
buffers[i].start = mmap(NULL, buffer.length,
|
||||
PROT_READ | PROT_WRITE, /* recommended */
|
||||
MAP_SHARED, /* recommended */
|
||||
fd, buffer.m.offset);
|
||||
|
||||
if (MAP_FAILED == buffers[i].start) {
|
||||
/* If you do not exit here you should unmap() and free()
|
||||
the buffers mapped so far. */
|
||||
perror ("mmap");
|
||||
exit (EXIT_FAILURE);
|
||||
perror("mmap");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup. */
|
||||
|
||||
for (i = 0; i < reqbuf.count; i++)
|
||||
munmap (buffers[i].start, buffers[i].length);
|
||||
munmap(buffers[i].start, buffers[i].length);
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Mapping buffers in the multi-planar API</title>
|
||||
<programlisting>
|
||||
&v4l2-requestbuffers; reqbuf;
|
||||
/* Our current format uses 3 planes per buffer */
|
||||
#define FMT_NUM_PLANES = 3;
|
||||
|
||||
struct {
|
||||
void *start[FMT_NUM_PLANES];
|
||||
size_t length[FMT_NUM_PLANES];
|
||||
} *buffers;
|
||||
unsigned int i, j;
|
||||
|
||||
memset(&reqbuf, 0, sizeof(reqbuf));
|
||||
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
reqbuf.memory = V4L2_MEMORY_MMAP;
|
||||
reqbuf.count = 20;
|
||||
|
||||
if (ioctl(fd, &VIDIOC-REQBUFS;, &reqbuf) < 0) {
|
||||
if (errno == EINVAL)
|
||||
printf("Video capturing or mmap-streaming is not supported\n");
|
||||
else
|
||||
perror("VIDIOC_REQBUFS");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* We want at least five buffers. */
|
||||
|
||||
if (reqbuf.count < 5) {
|
||||
/* You may need to free the buffers here. */
|
||||
printf("Not enough buffer memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
buffers = calloc(reqbuf.count, sizeof(*buffers));
|
||||
assert(buffers != NULL);
|
||||
|
||||
for (i = 0; i < reqbuf.count; i++) {
|
||||
&v4l2-buffer; buffer;
|
||||
&v4l2-plane; planes[FMT_NUM_PLANES];
|
||||
|
||||
memset(&buffer, 0, sizeof(buffer));
|
||||
buffer.type = reqbuf.type;
|
||||
buffer.memory = V4L2_MEMORY_MMAP;
|
||||
buffer.index = i;
|
||||
/* length in struct v4l2_buffer in multi-planar API stores the size
|
||||
* of planes array. */
|
||||
buffer.length = FMT_NUM_PLANES;
|
||||
buffer.m.planes = planes;
|
||||
|
||||
if (ioctl(fd, &VIDIOC-QUERYBUF;, &buffer) < 0) {
|
||||
perror("VIDIOC_QUERYBUF");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Every plane has to be mapped separately */
|
||||
for (j = 0; j < FMT_NUM_PLANES; j++) {
|
||||
buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */
|
||||
|
||||
buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length,
|
||||
PROT_READ | PROT_WRITE, /* recommended */
|
||||
MAP_SHARED, /* recommended */
|
||||
fd, buffer.m.planes[j].m.offset);
|
||||
|
||||
if (MAP_FAILED == buffers[i].start[j]) {
|
||||
/* If you do not exit here you should unmap() and free()
|
||||
the buffers and planes mapped so far. */
|
||||
perror("mmap");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup. */
|
||||
|
||||
for (i = 0; i < reqbuf.count; i++)
|
||||
for (j = 0; j < FMT_NUM_PLANES; j++)
|
||||
munmap(buffers[i].start[j], buffers[i].length[j]);
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
|
@ -286,13 +372,13 @@ pointer method (not only memory mapping) is supported must be
|
|||
determined by calling the &VIDIOC-REQBUFS; ioctl.</para>
|
||||
|
||||
<para>This I/O method combines advantages of the read/write and
|
||||
memory mapping methods. Buffers are allocated by the application
|
||||
memory mapping methods. Buffers (planes) are allocated by the application
|
||||
itself, and can reside for example in virtual or shared memory. Only
|
||||
pointers to data are exchanged, these pointers and meta-information
|
||||
are passed in &v4l2-buffer;. The driver must be switched
|
||||
into user pointer I/O mode by calling the &VIDIOC-REQBUFS; with the
|
||||
desired buffer type. No buffers are allocated beforehands,
|
||||
consequently they are not indexed and cannot be queried like mapped
|
||||
are passed in &v4l2-buffer; (or in &v4l2-plane; in the multi-planar API case).
|
||||
The driver must be switched into user pointer I/O mode by calling the
|
||||
&VIDIOC-REQBUFS; with the desired buffer type. No buffers (planes) are allocated
|
||||
beforehand, consequently they are not indexed and cannot be queried like mapped
|
||||
buffers with the <constant>VIDIOC_QUERYBUF</constant> ioctl.</para>
|
||||
|
||||
<example>
|
||||
|
@ -316,7 +402,7 @@ if (ioctl (fd, &VIDIOC-REQBUFS;, &reqbuf) == -1) {
|
|||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>Buffer addresses and sizes are passed on the fly with the
|
||||
<para>Buffer (plane) addresses and sizes are passed on the fly with the
|
||||
&VIDIOC-QBUF; ioctl. Although buffers are commonly cycled,
|
||||
applications can pass different addresses and sizes at each
|
||||
<constant>VIDIOC_QBUF</constant> call. If required by the hardware the
|
||||
|
@ -396,11 +482,18 @@ rest should be evident.</para>
|
|||
<title>Buffers</title>
|
||||
|
||||
<para>A buffer contains data exchanged by application and
|
||||
driver using one of the Streaming I/O methods. Only pointers to
|
||||
buffers are exchanged, the data itself is not copied. These pointers,
|
||||
together with meta-information like timestamps or field parity, are
|
||||
stored in a struct <structname>v4l2_buffer</structname>, argument to
|
||||
the &VIDIOC-QUERYBUF;, &VIDIOC-QBUF; and &VIDIOC-DQBUF; ioctl.</para>
|
||||
driver using one of the Streaming I/O methods. In the multi-planar API, the
|
||||
data is held in planes, while the buffer structure acts as a container
|
||||
for the planes. Only pointers to buffers (planes) are exchanged, the data
|
||||
itself is not copied. These pointers, together with meta-information like
|
||||
timestamps or field parity, are stored in a struct
|
||||
<structname>v4l2_buffer</structname>, argument to
|
||||
the &VIDIOC-QUERYBUF;, &VIDIOC-QBUF; and &VIDIOC-DQBUF; ioctl.
|
||||
In the multi-planar API, some plane-specific members of struct
|
||||
<structname>v4l2_buffer</structname>, such as pointers and sizes for each
|
||||
plane, are stored in struct <structname>v4l2_plane</structname> instead.
|
||||
In that case, struct <structname>v4l2_buffer</structname> contains an array of
|
||||
plane structures.</para>
|
||||
|
||||
<para>Nominally timestamps refer to the first data byte transmitted.
|
||||
In practice however the wide range of hardware covered by the V4L2 API
|
||||
|
@ -551,26 +644,40 @@ in accordance with the selected I/O method.</entry>
|
|||
<entry></entry>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>offset</structfield></entry>
|
||||
<entry>When <structfield>memory</structfield> is
|
||||
<constant>V4L2_MEMORY_MMAP</constant> this is the offset of the buffer
|
||||
from the start of the device memory. The value is returned by the
|
||||
driver and apart of serving as parameter to the &func-mmap; function
|
||||
not useful for applications. See <xref linkend="mmap" /> for details.</entry>
|
||||
<entry>For the single-planar API and when
|
||||
<structfield>memory</structfield> is <constant>V4L2_MEMORY_MMAP</constant> this
|
||||
is the offset of the buffer from the start of the device memory. The value is
|
||||
returned by the driver and apart of serving as parameter to the &func-mmap;
|
||||
function not useful for applications. See <xref linkend="mmap" /> for details
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>unsigned long</entry>
|
||||
<entry><structfield>userptr</structfield></entry>
|
||||
<entry>When <structfield>memory</structfield> is
|
||||
<constant>V4L2_MEMORY_USERPTR</constant> this is a pointer to the
|
||||
buffer (casted to unsigned long type) in virtual memory, set by the
|
||||
application. See <xref linkend="userp" /> for details.</entry>
|
||||
<entry>For the single-planar API and when
|
||||
<structfield>memory</structfield> is <constant>V4L2_MEMORY_USERPTR</constant>
|
||||
this is a pointer to the buffer (casted to unsigned long type) in virtual
|
||||
memory, set by the application. See <xref linkend="userp" /> for details.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>struct v4l2_plane</entry>
|
||||
<entry><structfield>*planes</structfield></entry>
|
||||
<entry>When using the multi-planar API, contains a userspace pointer
|
||||
to an array of &v4l2-plane;. The size of the array should be put
|
||||
in the <structfield>length</structfield> field of this
|
||||
<structname>v4l2_buffer</structname> structure.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>length</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>Size of the buffer (not the payload) in bytes.</entry>
|
||||
<entry>Size of the buffer (not the payload) in bytes for the
|
||||
single-planar API. For the multi-planar API should contain the
|
||||
number of elements in the <structfield>planes</structfield> array.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
|
@ -596,6 +703,66 @@ should set this to 0.</entry>
|
|||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="v4l2-plane">
|
||||
<title>struct <structname>v4l2_plane</structname></title>
|
||||
<tgroup cols="4">
|
||||
&cs-ustr;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>bytesused</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The number of bytes occupied by data in the plane
|
||||
(its payload).</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>length</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>Size in bytes of the plane (not its payload).</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>union</entry>
|
||||
<entry><structfield>m</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>mem_offset</structfield></entry>
|
||||
<entry>When the memory type in the containing &v4l2-buffer; is
|
||||
<constant>V4L2_MEMORY_MMAP</constant>, this is the value that
|
||||
should be passed to &func-mmap;, similar to the
|
||||
<structfield>offset</structfield> field in &v4l2-buffer;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>__unsigned long</entry>
|
||||
<entry><structfield>userptr</structfield></entry>
|
||||
<entry>When the memory type in the containing &v4l2-buffer; is
|
||||
<constant>V4L2_MEMORY_USERPTR</constant>, this is a userspace
|
||||
pointer to the memory allocated for this plane by an application.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>data_offset</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>Offset in bytes to video data in the plane, if applicable.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved[11]</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>Reserved for future use. Should be zeroed by an
|
||||
application.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="v4l2-buf-type">
|
||||
<title>enum v4l2_buf_type</title>
|
||||
<tgroup cols="3">
|
||||
|
@ -604,13 +771,27 @@ should set this to 0.</entry>
|
|||
<row>
|
||||
<entry><constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant></entry>
|
||||
<entry>1</entry>
|
||||
<entry>Buffer of a video capture stream, see <xref
|
||||
<entry>Buffer of a single-planar video capture stream, see <xref
|
||||
linkend="capture" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>
|
||||
</entry>
|
||||
<entry>9</entry>
|
||||
<entry>Buffer of a multi-planar video capture stream, see <xref
|
||||
linkend="capture" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant></entry>
|
||||
<entry>2</entry>
|
||||
<entry>Buffer of a video output stream, see <xref
|
||||
<entry>Buffer of a single-planar video output stream, see <xref
|
||||
linkend="output" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>
|
||||
</entry>
|
||||
<entry>10</entry>
|
||||
<entry>Buffer of a multi-planar video output stream, see <xref
|
||||
linkend="output" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
|
|
|
@ -45,7 +45,7 @@ describing an IR signal are read from the chardev.</para>
|
|||
<para>The data written to the chardev is a pulse/space sequence of integer
|
||||
values. Pulses and spaces are only marked implicitly by their position. The
|
||||
data must start and end with a pulse, therefore, the data must always include
|
||||
an unevent number of samples. The write function must block until the data has
|
||||
an uneven number of samples. The write function must block until the data has
|
||||
been transmitted by the hardware.</para>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<partinfo>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Laurent</firstname>
|
||||
<surname>Pinchart</surname>
|
||||
<affiliation><address><email>laurent.pinchart@ideasonboard.com</email></address></affiliation>
|
||||
<contrib>Initial version.</contrib>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<copyright>
|
||||
<year>2010</year>
|
||||
<holder>Laurent Pinchart</holder>
|
||||
</copyright>
|
||||
|
||||
<revhistory>
|
||||
<!-- Put document revisions here, newest first. -->
|
||||
<revision>
|
||||
<revnumber>1.0.0</revnumber>
|
||||
<date>2010-11-10</date>
|
||||
<authorinitials>lp</authorinitials>
|
||||
<revremark>Initial revision</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
</partinfo>
|
||||
|
||||
<title>Media Controller API</title>
|
||||
|
||||
<chapter id="media_controller">
|
||||
<title>Media Controller</title>
|
||||
|
||||
<section id="media-controller-intro">
|
||||
<title>Introduction</title>
|
||||
<para>Media devices increasingly handle multiple related functions. Many USB
|
||||
cameras include microphones, video capture hardware can also output video,
|
||||
or SoC camera interfaces also perform memory-to-memory operations similar to
|
||||
video codecs.</para>
|
||||
<para>Independent functions, even when implemented in the same hardware, can
|
||||
be modelled as separate devices. A USB camera with a microphone will be
|
||||
presented to userspace applications as V4L2 and ALSA capture devices. The
|
||||
devices' relationships (when using a webcam, end-users shouldn't have to
|
||||
manually select the associated USB microphone), while not made available
|
||||
directly to applications by the drivers, can usually be retrieved from
|
||||
sysfs.</para>
|
||||
<para>With more and more advanced SoC devices being introduced, the current
|
||||
approach will not scale. Device topologies are getting increasingly complex
|
||||
and can't always be represented by a tree structure. Hardware blocks are
|
||||
shared between different functions, creating dependencies between seemingly
|
||||
unrelated devices.</para>
|
||||
<para>Kernel abstraction APIs such as V4L2 and ALSA provide means for
|
||||
applications to access hardware parameters. As newer hardware expose an
|
||||
increasingly high number of those parameters, drivers need to guess what
|
||||
applications really require based on limited information, thereby
|
||||
implementing policies that belong to userspace.</para>
|
||||
<para>The media controller API aims at solving those problems.</para>
|
||||
</section>
|
||||
|
||||
<section id="media-controller-model">
|
||||
<title>Media device model</title>
|
||||
<para>Discovering a device internal topology, and configuring it at runtime,
|
||||
is one of the goals of the media controller API. To achieve this, hardware
|
||||
devices are modelled as an oriented graph of building blocks called entities
|
||||
connected through pads.</para>
|
||||
<para>An entity is a basic media hardware or software building block. It can
|
||||
correspond to a large variety of logical blocks such as physical hardware
|
||||
devices (CMOS sensor for instance), logical hardware devices (a building
|
||||
block in a System-on-Chip image processing pipeline), DMA channels or
|
||||
physical connectors.</para>
|
||||
<para>A pad is a connection endpoint through which an entity can interact
|
||||
with other entities. Data (not restricted to video) produced by an entity
|
||||
flows from the entity's output to one or more entity inputs. Pads should not
|
||||
be confused with physical pins at chip boundaries.</para>
|
||||
<para>A link is a point-to-point oriented connection between two pads,
|
||||
either on the same entity or on different entities. Data flows from a source
|
||||
pad to a sink pad.</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
<appendix id="media-user-func">
|
||||
<title>Function Reference</title>
|
||||
<!-- Keep this alphabetically sorted. -->
|
||||
&sub-media-open;
|
||||
&sub-media-close;
|
||||
&sub-media-ioctl;
|
||||
<!-- All ioctls go here. -->
|
||||
&sub-media-ioc-device-info;
|
||||
&sub-media-ioc-enum-entities;
|
||||
&sub-media-ioc-enum-links;
|
||||
&sub-media-ioc-setup-link;
|
||||
</appendix>
|
|
@ -0,0 +1,59 @@
|
|||
<refentry id="media-func-close">
|
||||
<refmeta>
|
||||
<refentrytitle>media close()</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>media-close</refname>
|
||||
<refpurpose>Close a media device</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <unistd.h></funcsynopsisinfo>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>close</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>&fd;</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>Closes the media device. Resources associated with the file descriptor
|
||||
are freed. The device configuration remain unchanged.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para><function>close</function> returns 0 on success. On error, -1 is
|
||||
returned, and <varname>errno</varname> is set appropriately. Possible error
|
||||
codes are:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EBADF</errorcode></term>
|
||||
<listitem>
|
||||
<para><parameter>fd</parameter> is not a valid open file descriptor.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,116 @@
|
|||
<refentry id="media-func-ioctl">
|
||||
<refmeta>
|
||||
<refentrytitle>media ioctl()</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>media-ioctl</refname>
|
||||
<refpurpose>Control a media device</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <sys/ioctl.h></funcsynopsisinfo>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>void *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>&fd;</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>Media ioctl request code as defined in the media.h header file,
|
||||
for example MEDIA_IOC_SETUP_LINK.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para>Pointer to a request-specific structure.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para>The <function>ioctl()</function> function manipulates media device
|
||||
parameters. The argument <parameter>fd</parameter> must be an open file
|
||||
descriptor.</para>
|
||||
<para>The ioctl <parameter>request</parameter> code specifies the media
|
||||
function to be called. It has encoded in it whether the argument is an
|
||||
input, output or read/write parameter, and the size of the argument
|
||||
<parameter>argp</parameter> in bytes.</para>
|
||||
<para>Macros and structures definitions specifying media ioctl requests and
|
||||
their parameters are located in the media.h header file. All media ioctl
|
||||
requests, their respective function and parameters are specified in
|
||||
<xref linkend="media-user-func" />.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para><function>ioctl()</function> returns <returnvalue>0</returnvalue> on
|
||||
success. On failure, <returnvalue>-1</returnvalue> is returned, and the
|
||||
<varname>errno</varname> variable is set appropriately. Generic error codes
|
||||
are listed below, and request-specific error codes are listed in the
|
||||
individual requests descriptions.</para>
|
||||
<para>When an ioctl that takes an output or read/write parameter fails,
|
||||
the parameter remains unmodified.</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EBADF</errorcode></term>
|
||||
<listitem>
|
||||
<para><parameter>fd</parameter> is not a valid open file descriptor.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EFAULT</errorcode></term>
|
||||
<listitem>
|
||||
<para><parameter>argp</parameter> references an inaccessible memory
|
||||
area.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The <parameter>request</parameter> or the data pointed to by
|
||||
<parameter>argp</parameter> is not valid. This is a very common error
|
||||
code, see the individual ioctl requests listed in
|
||||
<xref linkend="media-user-func" /> for actual causes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>ENOMEM</errorcode></term>
|
||||
<listitem>
|
||||
<para>Insufficient kernel memory was available to complete the
|
||||
request.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>ENOTTY</errorcode></term>
|
||||
<listitem>
|
||||
<para><parameter>fd</parameter> is not associated with a character
|
||||
special device.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,94 @@
|
|||
<refentry id="media-func-open">
|
||||
<refmeta>
|
||||
<refentrytitle>media open()</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>media-open</refname>
|
||||
<refpurpose>Open a media device</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <fcntl.h></funcsynopsisinfo>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>open</function></funcdef>
|
||||
<paramdef>const char *<parameter>device_name</parameter></paramdef>
|
||||
<paramdef>int <parameter>flags</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>device_name</parameter></term>
|
||||
<listitem>
|
||||
<para>Device to be opened.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>flags</parameter></term>
|
||||
<listitem>
|
||||
<para>Open flags. Access mode must be either <constant>O_RDONLY</constant>
|
||||
or <constant>O_RDWR</constant>. Other flags have no effect.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para>To open a media device applications call <function>open()</function>
|
||||
with the desired device name. The function has no side effects; the device
|
||||
configuration remain unchanged.</para>
|
||||
<para>When the device is opened in read-only mode, attemps to modify its
|
||||
configuration will result in an error, and <varname>errno</varname> will be
|
||||
set to <errorcode>EBADF</errorcode>.</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para><function>open</function> returns the new file descriptor on success.
|
||||
On error, -1 is returned, and <varname>errno</varname> is set appropriately.
|
||||
Possible error codes are:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EACCES</errorcode></term>
|
||||
<listitem>
|
||||
<para>The requested access to the file is not allowed.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EMFILE</errorcode></term>
|
||||
<listitem>
|
||||
<para>The process already has the maximum number of files open.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>ENFILE</errorcode></term>
|
||||
<listitem>
|
||||
<para>The system limit on the total number of open files has been
|
||||
reached.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>ENOMEM</errorcode></term>
|
||||
<listitem>
|
||||
<para>Insufficient kernel memory was available.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>ENXIO</errorcode></term>
|
||||
<listitem>
|
||||
<para>No device corresponding to this device special file exists.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,133 @@
|
|||
<refentry id="media-ioc-device-info">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl MEDIA_IOC_DEVICE_INFO</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>MEDIA_IOC_DEVICE_INFO</refname>
|
||||
<refpurpose>Query device information</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct media_device_info *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>File descriptor returned by
|
||||
<link linkend='media-func-open'><function>open()</function></link>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>MEDIA_IOC_DEVICE_INFO</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>All media devices must support the <constant>MEDIA_IOC_DEVICE_INFO</constant>
|
||||
ioctl. To query device information, applications call the ioctl with a
|
||||
pointer to a &media-device-info;. The driver fills the structure and returns
|
||||
the information to the application.
|
||||
The ioctl never fails.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="media-device-info">
|
||||
<title>struct <structname>media_device_info</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>char</entry>
|
||||
<entry><structfield>driver</structfield>[16]</entry>
|
||||
<entry><para>Name of the driver implementing the media API as a
|
||||
NUL-terminated ASCII string. The driver version is stored in the
|
||||
<structfield>driver_version</structfield> field.</para>
|
||||
<para>Driver specific applications can use this information to
|
||||
verify the driver identity. It is also useful to work around
|
||||
known bugs, or to identify drivers in error reports.</para></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>char</entry>
|
||||
<entry><structfield>model</structfield>[32]</entry>
|
||||
<entry>Device model name as a NUL-terminated UTF-8 string. The
|
||||
device version is stored in the <structfield>device_version</structfield>
|
||||
field and is not be appended to the model name.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>char</entry>
|
||||
<entry><structfield>serial</structfield>[40]</entry>
|
||||
<entry>Serial number as a NUL-terminated ASCII string.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>char</entry>
|
||||
<entry><structfield>bus_info</structfield>[32]</entry>
|
||||
<entry>Location of the device in the system as a NUL-terminated
|
||||
ASCII string. This includes the bus type name (PCI, USB, ...) and a
|
||||
bus-specific identifier.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>media_version</structfield></entry>
|
||||
<entry>Media API version, formatted with the
|
||||
<constant>KERNEL_VERSION()</constant> macro.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>hw_revision</structfield></entry>
|
||||
<entry>Hardware device revision in a driver-specific format.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>media_version</structfield></entry>
|
||||
<entry>Media device driver version, formatted with the
|
||||
<constant>KERNEL_VERSION()</constant> macro. Together with the
|
||||
<structfield>driver</structfield> field this identifies a particular
|
||||
driver.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[31]</entry>
|
||||
<entry>Reserved for future extensions. Drivers and applications must
|
||||
set this array to zero.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<para>The <structfield>serial</structfield> and <structfield>bus_info</structfield>
|
||||
fields can be used to distinguish between multiple instances of otherwise
|
||||
identical hardware. The serial number takes precedence when provided and can
|
||||
be assumed to be unique. If the serial number is an empty string, the
|
||||
<structfield>bus_info</structfield> field can be used instead. The
|
||||
<structfield>bus_info</structfield> field is guaranteed to be unique, but
|
||||
can vary across reboots or device unplug/replug.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return value</title>
|
||||
<para>This function doesn't return specific error codes.</para>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,308 @@
|
|||
<refentry id="media-ioc-enum-entities">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl MEDIA_IOC_ENUM_ENTITIES</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>MEDIA_IOC_ENUM_ENTITIES</refname>
|
||||
<refpurpose>Enumerate entities and their properties</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct media_entity_desc *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>File descriptor returned by
|
||||
<link linkend='media-func-open'><function>open()</function></link>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>MEDIA_IOC_ENUM_ENTITIES</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para>To query the attributes of an entity, applications set the id field
|
||||
of a &media-entity-desc; structure and call the MEDIA_IOC_ENUM_ENTITIES
|
||||
ioctl with a pointer to this structure. The driver fills the rest of the
|
||||
structure or returns an &EINVAL; when the id is invalid.</para>
|
||||
<para>Entities can be enumerated by or'ing the id with the
|
||||
<constant>MEDIA_ENT_ID_FLAG_NEXT</constant> flag. The driver will return
|
||||
information about the entity with the smallest id strictly larger than the
|
||||
requested one ('next entity'), or the &EINVAL; if there is none.</para>
|
||||
<para>Entity IDs can be non-contiguous. Applications must
|
||||
<emphasis>not</emphasis> try to enumerate entities by calling
|
||||
MEDIA_IOC_ENUM_ENTITIES with increasing id's until they get an error.</para>
|
||||
<para>Two or more entities that share a common non-zero
|
||||
<structfield>group_id</structfield> value are considered as logically
|
||||
grouped. Groups are used to report
|
||||
<itemizedlist>
|
||||
<listitem><para>ALSA, VBI and video nodes that carry the same media
|
||||
stream</para></listitem>
|
||||
<listitem><para>lens and flash controllers associated with a sensor</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="media-entity-desc">
|
||||
<title>struct <structname>media_entity_desc</structname></title>
|
||||
<tgroup cols="5">
|
||||
<colspec colname="c1" />
|
||||
<colspec colname="c2" />
|
||||
<colspec colname="c3" />
|
||||
<colspec colname="c4" />
|
||||
<colspec colname="c5" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>id</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>Entity id, set by the application. When the id is or'ed with
|
||||
<constant>MEDIA_ENT_ID_FLAG_NEXT</constant>, the driver clears the
|
||||
flag and returns the first entity with a larger id.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>char</entry>
|
||||
<entry><structfield>name</structfield>[32]</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>Entity name as an UTF-8 NULL-terminated string.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>type</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>Entity type, see <xref linkend="media-entity-type" /> for details.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>revision</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>Entity revision in a driver/hardware specific format.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>flags</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>Entity flags, see <xref linkend="media-entity-flag" /> for details.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>group_id</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>Entity group ID</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u16</entry>
|
||||
<entry><structfield>pads</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>Number of pads</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u16</entry>
|
||||
<entry><structfield>links</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>Total number of outbound links. Inbound links are not counted
|
||||
in this field.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>union</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>struct</entry>
|
||||
<entry><structfield>v4l</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>Valid for V4L sub-devices and nodes only.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>major</structfield></entry>
|
||||
<entry>V4L device node major number. For V4L sub-devices with no
|
||||
device node, set by the driver to 0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>minor</structfield></entry>
|
||||
<entry>V4L device node minor number. For V4L sub-devices with no
|
||||
device node, set by the driver to 0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>struct</entry>
|
||||
<entry><structfield>fb</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>Valid for frame buffer nodes only.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>major</structfield></entry>
|
||||
<entry>Frame buffer device node major number.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>minor</structfield></entry>
|
||||
<entry>Frame buffer device node minor number.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>struct</entry>
|
||||
<entry><structfield>alsa</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>Valid for ALSA devices only.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>card</structfield></entry>
|
||||
<entry>ALSA card number</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>device</structfield></entry>
|
||||
<entry>ALSA device number</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>subdevice</structfield></entry>
|
||||
<entry>ALSA sub-device number</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>int</entry>
|
||||
<entry><structfield>dvb</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>DVB card number</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>__u8</entry>
|
||||
<entry><structfield>raw</structfield>[180]</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="media-entity-type">
|
||||
<title>Media entity types</title>
|
||||
<tgroup cols="2">
|
||||
<colspec colname="c1"/>
|
||||
<colspec colname="c2"/>
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_T_DEVNODE</constant></entry>
|
||||
<entry>Unknown device node</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_T_DEVNODE_V4L</constant></entry>
|
||||
<entry>V4L video, radio or vbi device node</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_T_DEVNODE_FB</constant></entry>
|
||||
<entry>Frame buffer device node</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_T_DEVNODE_ALSA</constant></entry>
|
||||
<entry>ALSA card</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_T_DEVNODE_DVB</constant></entry>
|
||||
<entry>DVB card</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_T_V4L2_SUBDEV</constant></entry>
|
||||
<entry>Unknown V4L sub-device</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_SENSOR</constant></entry>
|
||||
<entry>Video sensor</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_FLASH</constant></entry>
|
||||
<entry>Flash controller</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_LENS</constant></entry>
|
||||
<entry>Lens controller</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="media-entity-flag">
|
||||
<title>Media entity flags</title>
|
||||
<tgroup cols="2">
|
||||
<colspec colname="c1"/>
|
||||
<colspec colname="c2"/>
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_FL_DEFAULT</constant></entry>
|
||||
<entry>Default entity for its type. Used to discover the default
|
||||
audio, VBI and video devices, the default camera sensor, ...</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &media-entity-desc; <structfield>id</structfield> references
|
||||
a non-existing entity.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,207 @@
|
|||
<refentry id="media-ioc-enum-links">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl MEDIA_IOC_ENUM_LINKS</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>MEDIA_IOC_ENUM_LINKS</refname>
|
||||
<refpurpose>Enumerate all pads and links for a given entity</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct media_links_enum *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>File descriptor returned by
|
||||
<link linkend='media-func-open'><function>open()</function></link>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>MEDIA_IOC_ENUM_LINKS</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>To enumerate pads and/or links for a given entity, applications set
|
||||
the entity field of a &media-links-enum; structure and initialize the
|
||||
&media-pad-desc; and &media-link-desc; structure arrays pointed by the
|
||||
<structfield>pads</structfield> and <structfield>links</structfield> fields.
|
||||
They then call the MEDIA_IOC_ENUM_LINKS ioctl with a pointer to this
|
||||
structure.</para>
|
||||
<para>If the <structfield>pads</structfield> field is not NULL, the driver
|
||||
fills the <structfield>pads</structfield> array with information about the
|
||||
entity's pads. The array must have enough room to store all the entity's
|
||||
pads. The number of pads can be retrieved with the &MEDIA-IOC-ENUM-ENTITIES;
|
||||
ioctl.</para>
|
||||
<para>If the <structfield>links</structfield> field is not NULL, the driver
|
||||
fills the <structfield>links</structfield> array with information about the
|
||||
entity's outbound links. The array must have enough room to store all the
|
||||
entity's outbound links. The number of outbound links can be retrieved with
|
||||
the &MEDIA-IOC-ENUM-ENTITIES; ioctl.</para>
|
||||
<para>Only forward links that originate at one of the entity's source pads
|
||||
are returned during the enumeration process.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="media-links-enum">
|
||||
<title>struct <structname>media_links_enum</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>entity</structfield></entry>
|
||||
<entry>Entity id, set by the application.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>struct &media-pad-desc;</entry>
|
||||
<entry>*<structfield>pads</structfield></entry>
|
||||
<entry>Pointer to a pads array allocated by the application. Ignored
|
||||
if NULL.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>struct &media-link-desc;</entry>
|
||||
<entry>*<structfield>links</structfield></entry>
|
||||
<entry>Pointer to a links array allocated by the application. Ignored
|
||||
if NULL.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table pgwide="1" frame="none" id="media-pad-desc">
|
||||
<title>struct <structname>media_pad_desc</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>entity</structfield></entry>
|
||||
<entry>ID of the entity this pad belongs to.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u16</entry>
|
||||
<entry><structfield>index</structfield></entry>
|
||||
<entry>0-based pad index.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>flags</structfield></entry>
|
||||
<entry>Pad flags, see <xref linkend="media-pad-flag" /> for more details.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="media-pad-flag">
|
||||
<title>Media pad flags</title>
|
||||
<tgroup cols="2">
|
||||
<colspec colname="c1"/>
|
||||
<colspec colname="c2"/>
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry><constant>MEDIA_PAD_FL_SINK</constant></entry>
|
||||
<entry>Input pad, relative to the entity. Input pads sink data and
|
||||
are targets of links.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_PAD_FL_SOURCE</constant></entry>
|
||||
<entry>Output pad, relative to the entity. Output pads source data
|
||||
and are origins of links.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table pgwide="1" frame="none" id="media-link-desc">
|
||||
<title>struct <structname>media_links_desc</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>struct &media-pad-desc;</entry>
|
||||
<entry><structfield>source</structfield></entry>
|
||||
<entry>Pad at the origin of this link.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>struct &media-pad-desc;</entry>
|
||||
<entry><structfield>sink</structfield></entry>
|
||||
<entry>Pad at the target of this link.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>flags</structfield></entry>
|
||||
<entry>Link flags, see <xref linkend="media-link-flag" /> for more details.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="media-link-flag">
|
||||
<title>Media link flags</title>
|
||||
<tgroup cols="2">
|
||||
<colspec colname="c1"/>
|
||||
<colspec colname="c2"/>
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry><constant>MEDIA_LNK_FL_ENABLED</constant></entry>
|
||||
<entry>The link is enabled and can be used to transfer media data.
|
||||
When two or more links target a sink pad, only one of them can be
|
||||
enabled at a time.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_LNK_FL_IMMUTABLE</constant></entry>
|
||||
<entry>The link enabled state can't be modified at runtime. An
|
||||
immutable link is always enabled.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_LNK_FL_DYNAMIC</constant></entry>
|
||||
<entry>The link enabled state can be modified during streaming. This
|
||||
flag is set by drivers and is read-only for applications.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<para>One and only one of <constant>MEDIA_PAD_FL_SINK</constant> and
|
||||
<constant>MEDIA_PAD_FL_SOURCE</constant> must be set for every pad.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &media-links-enum; <structfield>id</structfield> references
|
||||
a non-existing entity.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,93 @@
|
|||
<refentry id="media-ioc-setup-link">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl MEDIA_IOC_SETUP_LINK</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>MEDIA_IOC_SETUP_LINK</refname>
|
||||
<refpurpose>Modify the properties of a link</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct media_link_desc *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>File descriptor returned by
|
||||
<link linkend='media-func-open'><function>open()</function></link>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>MEDIA_IOC_ENUM_LINKS</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>To change link properties applications fill a &media-link-desc; with
|
||||
link identification information (source and sink pad) and the new requested
|
||||
link flags. They then call the MEDIA_IOC_SETUP_LINK ioctl with a pointer to
|
||||
that structure.</para>
|
||||
<para>The only configurable property is the <constant>ENABLED</constant>
|
||||
link flag to enable/disable a link. Links marked with the
|
||||
<constant>IMMUTABLE</constant> link flag can not be enabled or disabled.
|
||||
</para>
|
||||
<para>Link configuration has no side effect on other links. If an enabled
|
||||
link at the sink pad prevents the link from being enabled, the driver
|
||||
returns with an &EBUSY;.</para>
|
||||
<para>Only links marked with the <constant>DYNAMIC</constant> link flag can
|
||||
be enabled/disabled while streaming media data. Attempting to enable or
|
||||
disable a streaming non-dynamic link will return an &EBUSY;.</para>
|
||||
<para>If the specified link can't be found the driver returns with an
|
||||
&EINVAL;.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EBUSY</errorcode></term>
|
||||
<listitem>
|
||||
<para>The link properties can't be changed because the link is
|
||||
currently busy. This can be caused, for instance, by an active media
|
||||
stream (audio or video) on the link. The ioctl shouldn't be retried if
|
||||
no other action is performed before to fix the problem.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &media-link-desc; references a non-existing link, or the
|
||||
link is immutable and an attempt to modify its configuration was made.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,154 @@
|
|||
<refentry id="V4L2-PIX-FMT-NV12M">
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_NV12M ('NV12M')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname> <constant>V4L2_PIX_FMT_NV12M</constant></refname>
|
||||
<refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> with planes
|
||||
non contiguous in memory. </refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>This is a multi-planar, two-plane version of the YUV 4:2:0 format.
|
||||
The three components are separated into two sub-images or planes.
|
||||
<constant>V4L2_PIX_FMT_NV12M</constant> differs from <constant>V4L2_PIX_FMT_NV12
|
||||
</constant> in that the two planes are non-contiguous in memory, i.e. the chroma
|
||||
plane do not necessarily immediately follows the luma plane.
|
||||
The luminance data occupies the first plane. The Y plane has one byte per pixel.
|
||||
In the second plane there is a chrominance data with alternating chroma samples.
|
||||
The CbCr plane is the same width, in bytes, as the Y plane (and of the image),
|
||||
but is half as tall in pixels. Each CbCr pair belongs to four pixels. For example,
|
||||
Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
|
||||
Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
|
||||
Y'<subscript>10</subscript>, Y'<subscript>11</subscript>. </para>
|
||||
|
||||
<para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
|
||||
used only in drivers and applications that support the multi-planar API,
|
||||
described in <xref linkend="planar-apis"/>. </para>
|
||||
|
||||
<para>If the Y plane has pad bytes after each row, then the
|
||||
CbCr plane has as many pad bytes after its rows.</para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_NV12M</constant> 4 × 4 pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Byte Order.</title>
|
||||
<para>Each cell is one byte.
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="5" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>start0 + 0:</entry>
|
||||
<entry>Y'<subscript>00</subscript></entry>
|
||||
<entry>Y'<subscript>01</subscript></entry>
|
||||
<entry>Y'<subscript>02</subscript></entry>
|
||||
<entry>Y'<subscript>03</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start0 + 4:</entry>
|
||||
<entry>Y'<subscript>10</subscript></entry>
|
||||
<entry>Y'<subscript>11</subscript></entry>
|
||||
<entry>Y'<subscript>12</subscript></entry>
|
||||
<entry>Y'<subscript>13</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start0 + 8:</entry>
|
||||
<entry>Y'<subscript>20</subscript></entry>
|
||||
<entry>Y'<subscript>21</subscript></entry>
|
||||
<entry>Y'<subscript>22</subscript></entry>
|
||||
<entry>Y'<subscript>23</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start0 + 12:</entry>
|
||||
<entry>Y'<subscript>30</subscript></entry>
|
||||
<entry>Y'<subscript>31</subscript></entry>
|
||||
<entry>Y'<subscript>32</subscript></entry>
|
||||
<entry>Y'<subscript>33</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start1 + 0:</entry>
|
||||
<entry>Cb<subscript>00</subscript></entry>
|
||||
<entry>Cr<subscript>00</subscript></entry>
|
||||
<entry>Cb<subscript>01</subscript></entry>
|
||||
<entry>Cr<subscript>01</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start1 + 4:</entry>
|
||||
<entry>Cb<subscript>10</subscript></entry>
|
||||
<entry>Cr<subscript>10</subscript></entry>
|
||||
<entry>Cb<subscript>11</subscript></entry>
|
||||
<entry>Cr<subscript>11</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
|
||||
<formalpara>
|
||||
<title>Color Sample Location.</title>
|
||||
<para>
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="7" align="center">
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>0</entry><entry></entry><entry>1</entry><entry></entry>
|
||||
<entry>2</entry><entry></entry><entry>3</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry><entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>1</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>2</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry><entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>3</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: sgml
|
||||
sgml-parent-document: "pixfmt.sgml"
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
-->
|
|
@ -0,0 +1,74 @@
|
|||
<refentry>
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_NV12MT ('TM12')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname id="V4L2-PIX-FMT-NV12MT"><constant>V4L2_PIX_FMT_NV12MT
|
||||
</constant></refname>
|
||||
<refpurpose>Formats with ½ horizontal and vertical
|
||||
chroma resolution. This format has two planes - one for luminance and one for
|
||||
chrominance. Chroma samples are interleaved. The difference to
|
||||
<constant>V4L2_PIX_FMT_NV12</constant> is the memory layout. Pixels are
|
||||
grouped in macroblocks of 64x32 size. The order of macroblocks in memory is
|
||||
also not standard.
|
||||
</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>This is the two-plane versions of the YUV 4:2:0 format where data
|
||||
is grouped into 64x32 macroblocks. The three components are separated into two
|
||||
sub-images or planes. The Y plane has one byte per pixel and pixels are grouped
|
||||
into 64x32 macroblocks. The CbCr plane has the same width, in bytes, as the Y
|
||||
plane (and the image), but is half as tall in pixels. The chroma plane is also
|
||||
grouped into 64x32 macroblocks.</para>
|
||||
<para>Width of the buffer has to be aligned to the multiple of 128, and
|
||||
height alignment is 32. Every four adjactent buffers - two horizontally and two
|
||||
vertically are grouped together and are located in memory in Z or flipped Z
|
||||
order. </para>
|
||||
<para>Layout of macroblocks in memory is presented in the following
|
||||
figure.</para>
|
||||
<para><figure id="nv12mt">
|
||||
<title><constant>V4L2_PIX_FMT_NV12MT</constant> macroblock Z shape
|
||||
memory layout</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="nv12mt.gif" format="GIF" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
The requirement that width is multiple of 128 is implemented because,
|
||||
the Z shape cannot be cut in half horizontally. In case the vertical resolution
|
||||
of macroblocks is odd then the last row of macroblocks is arranged in a linear
|
||||
order. </para>
|
||||
<para>In case of chroma the layout is identical. Cb and Cr samples are
|
||||
interleaved. Height of the buffer is aligned to 32.
|
||||
</para>
|
||||
<example>
|
||||
<title>Memory layout of macroblocks in <constant>V4L2_PIX_FMT_NV12
|
||||
</constant> format pixel image - extreme case</title>
|
||||
<para>
|
||||
<figure id="nv12mt_ex">
|
||||
<title>Example <constant>V4L2_PIX_FMT_NV12MT</constant> memory
|
||||
layout of macroblocks</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="nv12mt_example.gif" format="GIF" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
Memory layout of macroblocks of <constant>V4L2_PIX_FMT_NV12MT
|
||||
</constant> format in most extreme case.
|
||||
</para>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: sgml
|
||||
sgml-parent-document: "pixfmt.sgml"
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
-->
|
|
@ -0,0 +1,90 @@
|
|||
<refentry>
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_SRGGB12 ('RG12'),
|
||||
V4L2_PIX_FMT_SGRBG12 ('BA12'),
|
||||
V4L2_PIX_FMT_SGBRG12 ('GB12'),
|
||||
V4L2_PIX_FMT_SBGGR12 ('BG12'),
|
||||
</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname id="V4L2-PIX-FMT-SRGGB12"><constant>V4L2_PIX_FMT_SRGGB12</constant></refname>
|
||||
<refname id="V4L2-PIX-FMT-SGRBG12"><constant>V4L2_PIX_FMT_SGRBG12</constant></refname>
|
||||
<refname id="V4L2-PIX-FMT-SGBRG12"><constant>V4L2_PIX_FMT_SGBRG12</constant></refname>
|
||||
<refname id="V4L2-PIX-FMT-SBGGR12"><constant>V4L2_PIX_FMT_SBGGR12</constant></refname>
|
||||
<refpurpose>12-bit Bayer formats expanded to 16 bits</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>The following four pixel formats are raw sRGB / Bayer formats with
|
||||
12 bits per colour. Each colour component is stored in a 16-bit word, with 6
|
||||
unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
|
||||
and n/2 blue or red samples, with alternating red and blue rows. Bytes are
|
||||
stored in memory in little endian order. They are conventionally described
|
||||
as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of one of these
|
||||
formats</para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_SBGGR12</constant> 4 × 4
|
||||
pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Byte Order.</title>
|
||||
<para>Each cell is one byte, high 6 bits in high bytes are 0.
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="5" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>start + 0:</entry>
|
||||
<entry>B<subscript>00low</subscript></entry>
|
||||
<entry>B<subscript>00high</subscript></entry>
|
||||
<entry>G<subscript>01low</subscript></entry>
|
||||
<entry>G<subscript>01high</subscript></entry>
|
||||
<entry>B<subscript>02low</subscript></entry>
|
||||
<entry>B<subscript>02high</subscript></entry>
|
||||
<entry>G<subscript>03low</subscript></entry>
|
||||
<entry>G<subscript>03high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 8:</entry>
|
||||
<entry>G<subscript>10low</subscript></entry>
|
||||
<entry>G<subscript>10high</subscript></entry>
|
||||
<entry>R<subscript>11low</subscript></entry>
|
||||
<entry>R<subscript>11high</subscript></entry>
|
||||
<entry>G<subscript>12low</subscript></entry>
|
||||
<entry>G<subscript>12high</subscript></entry>
|
||||
<entry>R<subscript>13low</subscript></entry>
|
||||
<entry>R<subscript>13high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 16:</entry>
|
||||
<entry>B<subscript>20low</subscript></entry>
|
||||
<entry>B<subscript>20high</subscript></entry>
|
||||
<entry>G<subscript>21low</subscript></entry>
|
||||
<entry>G<subscript>21high</subscript></entry>
|
||||
<entry>B<subscript>22low</subscript></entry>
|
||||
<entry>B<subscript>22high</subscript></entry>
|
||||
<entry>G<subscript>23low</subscript></entry>
|
||||
<entry>G<subscript>23high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 24:</entry>
|
||||
<entry>G<subscript>30low</subscript></entry>
|
||||
<entry>G<subscript>30high</subscript></entry>
|
||||
<entry>R<subscript>31low</subscript></entry>
|
||||
<entry>R<subscript>31high</subscript></entry>
|
||||
<entry>G<subscript>32low</subscript></entry>
|
||||
<entry>G<subscript>32high</subscript></entry>
|
||||
<entry>R<subscript>33low</subscript></entry>
|
||||
<entry>R<subscript>33high</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,162 @@
|
|||
<refentry id="V4L2-PIX-FMT-YUV420M">
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_YUV420M ('YU12M')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname> <constant>V4L2_PIX_FMT_YUV420M</constant></refname>
|
||||
<refpurpose>Variation of <constant>V4L2_PIX_FMT_YUV420</constant>
|
||||
with planes non contiguous in memory. </refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>This is a multi-planar format, as opposed to a packed format.
|
||||
The three components are separated into three sub- images or planes.
|
||||
|
||||
The Y plane is first. The Y plane has one byte per pixel. The Cb data
|
||||
constitutes the second plane which is half the width and half
|
||||
the height of the Y plane (and of the image). Each Cb belongs to four
|
||||
pixels, a two-by-two square of the image. For example,
|
||||
Cb<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
|
||||
Y'<subscript>01</subscript>, Y'<subscript>10</subscript>, and
|
||||
Y'<subscript>11</subscript>. The Cr data, just like the Cb plane, is
|
||||
in the third plane. </para>
|
||||
|
||||
<para>If the Y plane has pad bytes after each row, then the Cb
|
||||
and Cr planes have half as many pad bytes after their rows. In other
|
||||
words, two Cx rows (including padding) is exactly as long as one Y row
|
||||
(including padding).</para>
|
||||
|
||||
<para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
|
||||
used only in drivers and applications that support the multi-planar API,
|
||||
described in <xref linkend="planar-apis"/>. </para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_YVU420M</constant> 4 × 4
|
||||
pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Byte Order.</title>
|
||||
<para>Each cell is one byte.
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="5" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>start0 + 0:</entry>
|
||||
<entry>Y'<subscript>00</subscript></entry>
|
||||
<entry>Y'<subscript>01</subscript></entry>
|
||||
<entry>Y'<subscript>02</subscript></entry>
|
||||
<entry>Y'<subscript>03</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start0 + 4:</entry>
|
||||
<entry>Y'<subscript>10</subscript></entry>
|
||||
<entry>Y'<subscript>11</subscript></entry>
|
||||
<entry>Y'<subscript>12</subscript></entry>
|
||||
<entry>Y'<subscript>13</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start0 + 8:</entry>
|
||||
<entry>Y'<subscript>20</subscript></entry>
|
||||
<entry>Y'<subscript>21</subscript></entry>
|
||||
<entry>Y'<subscript>22</subscript></entry>
|
||||
<entry>Y'<subscript>23</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start0 + 12:</entry>
|
||||
<entry>Y'<subscript>30</subscript></entry>
|
||||
<entry>Y'<subscript>31</subscript></entry>
|
||||
<entry>Y'<subscript>32</subscript></entry>
|
||||
<entry>Y'<subscript>33</subscript></entry>
|
||||
</row>
|
||||
<row><entry></entry></row>
|
||||
<row>
|
||||
<entry>start1 + 0:</entry>
|
||||
<entry>Cb<subscript>00</subscript></entry>
|
||||
<entry>Cb<subscript>01</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start1 + 2:</entry>
|
||||
<entry>Cb<subscript>10</subscript></entry>
|
||||
<entry>Cb<subscript>11</subscript></entry>
|
||||
</row>
|
||||
<row><entry></entry></row>
|
||||
<row>
|
||||
<entry>start2 + 0:</entry>
|
||||
<entry>Cr<subscript>00</subscript></entry>
|
||||
<entry>Cr<subscript>01</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start2 + 2:</entry>
|
||||
<entry>Cr<subscript>10</subscript></entry>
|
||||
<entry>Cr<subscript>11</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
|
||||
<formalpara>
|
||||
<title>Color Sample Location.</title>
|
||||
<para>
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="7" align="center">
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>0</entry><entry></entry><entry>1</entry><entry></entry>
|
||||
<entry>2</entry><entry></entry><entry>3</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry><entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>1</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>2</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry><entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>3</entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
|
||||
<entry>Y</entry><entry></entry><entry>Y</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: sgml
|
||||
sgml-parent-document: "pixfmt.sgml"
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
-->
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
<para>The V4L2 API was primarily designed for devices exchanging
|
||||
image data with applications. The
|
||||
<structname>v4l2_pix_format</structname> structure defines the format
|
||||
and layout of an image in memory. Image formats are negotiated with
|
||||
the &VIDIOC-S-FMT; ioctl. (The explanations here focus on video
|
||||
<structname>v4l2_pix_format</structname> and <structname>v4l2_pix_format_mplane
|
||||
</structname> structures define the format and layout of an image in memory.
|
||||
The former is used with the single-planar API, while the latter is used with the
|
||||
multi-planar version (see <xref linkend="planar-apis"/>). Image formats are
|
||||
negotiated with the &VIDIOC-S-FMT; ioctl. (The explanations here focus on video
|
||||
capturing and output, for overlay frame buffer formats see also
|
||||
&VIDIOC-G-FBUF;.)</para>
|
||||
|
||||
<section>
|
||||
<title>Single-planar format structure</title>
|
||||
<table pgwide="1" frame="none" id="v4l2-pix-format">
|
||||
<title>struct <structname>v4l2_pix_format</structname></title>
|
||||
<tgroup cols="3">
|
||||
|
@ -106,6 +110,98 @@ set this field to zero.</entry>
|
|||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Multi-planar format structures</title>
|
||||
<para>The <structname>v4l2_plane_pix_format</structname> structures define
|
||||
size and layout for each of the planes in a multi-planar format.
|
||||
The <structname>v4l2_pix_format_mplane</structname> structure contains
|
||||
information common to all planes (such as image width and height) and
|
||||
an array of <structname>v4l2_plane_pix_format</structname> structures,
|
||||
describing all planes of that format.</para>
|
||||
<table pgwide="1" frame="none" id="v4l2-plane-pix-format">
|
||||
<title>struct <structname>vl42_plane_pix_format</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>sizeimage</structfield></entry>
|
||||
<entry>Maximum size in bytes required for image data in this plane.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u16</entry>
|
||||
<entry><structfield>bytesperline</structfield></entry>
|
||||
<entry>Distance in bytes between the leftmost pixels in two adjacent
|
||||
lines.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u16</entry>
|
||||
<entry><structfield>reserved[7]</structfield></entry>
|
||||
<entry>Reserved for future extensions. Should be zeroed by the
|
||||
application.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<table pgwide="1" frame="none" id="v4l2-pix-format-mplane">
|
||||
<title>struct <structname>v4l2_pix_format_mplane</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>width</structfield></entry>
|
||||
<entry>Image width in pixels.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>height</structfield></entry>
|
||||
<entry>Image height in pixels.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>pixelformat</structfield></entry>
|
||||
<entry>The pixel format. Both single- and multi-planar four character
|
||||
codes can be used.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>&v4l2-field;</entry>
|
||||
<entry><structfield>field</structfield></entry>
|
||||
<entry>See &v4l2-pix-format;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>&v4l2-colorspace;</entry>
|
||||
<entry><structfield>colorspace</structfield></entry>
|
||||
<entry>See &v4l2-pix-format;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>&v4l2-plane-pix-format;</entry>
|
||||
<entry><structfield>plane_fmt[VIDEO_MAX_PLANES]</structfield></entry>
|
||||
<entry>An array of structures describing format of each plane this
|
||||
pixel format consists of. The number of valid entries in this array
|
||||
has to be put in the <structfield>num_planes</structfield>
|
||||
field.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u8</entry>
|
||||
<entry><structfield>num_planes</structfield></entry>
|
||||
<entry>Number of planes (i.e. separate memory buffers) for this format
|
||||
and the number of valid entries in the
|
||||
<structfield>plane_fmt</structfield> array.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u8</entry>
|
||||
<entry><structfield>reserved[11]</structfield></entry>
|
||||
<entry>Reserved for future extensions. Should be zeroed by the
|
||||
application.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Standard Image Formats</title>
|
||||
|
@ -142,11 +238,19 @@ leftmost pixel of the second row from the top, and so on. The last row
|
|||
has just as many pad bytes after it as the other rows.</para>
|
||||
|
||||
<para>In V4L2 each format has an identifier which looks like
|
||||
<constant>PIX_FMT_XXX</constant>, defined in the <filename>videodev2.h</filename>
|
||||
header file. These identifiers
|
||||
represent <link linkend="v4l2-fourcc">four character codes</link>
|
||||
<constant>PIX_FMT_XXX</constant>, defined in the <link
|
||||
linkend="videodev">videodev.h</link> header file. These identifiers
|
||||
represent <link linkend="v4l2-fourcc">four character (FourCC) codes</link>
|
||||
which are also listed below, however they are not the same as those
|
||||
used in the Windows world.</para>
|
||||
|
||||
<para>For some formats, data is stored in separate, discontiguous
|
||||
memory buffers. Those formats are identified by a separate set of FourCC codes
|
||||
and are referred to as "multi-planar formats". For example, a YUV422 frame is
|
||||
normally stored in one memory buffer, but it can also be placed in two or three
|
||||
separate buffers, with Y component in one buffer and CbCr components in another
|
||||
in the 2-planar version or with each component in its own buffer in the
|
||||
3-planar case. Those sub-buffers are referred to as "planes".</para>
|
||||
</section>
|
||||
|
||||
<section id="colorspaces">
|
||||
|
@ -599,10 +703,13 @@ information.</para>
|
|||
&sub-vyuy;
|
||||
&sub-y41p;
|
||||
&sub-yuv420;
|
||||
&sub-yuv420m;
|
||||
&sub-yuv410;
|
||||
&sub-yuv422p;
|
||||
&sub-yuv411p;
|
||||
&sub-nv12;
|
||||
&sub-nv12m;
|
||||
&sub-nv12mt;
|
||||
&sub-nv16;
|
||||
</section>
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<section id="planar-apis">
|
||||
<title>Single- and multi-planar APIs</title>
|
||||
|
||||
<para>Some devices require data for each input or output video frame
|
||||
to be placed in discontiguous memory buffers. In such cases, one
|
||||
video frame has to be addressed using more than one memory address, i.e. one
|
||||
pointer per "plane". A plane is a sub-buffer of the current frame. For
|
||||
examples of such formats see <xref linkend="pixfmt" />.</para>
|
||||
|
||||
<para>Initially, V4L2 API did not support multi-planar buffers and a set of
|
||||
extensions has been introduced to handle them. Those extensions constitute
|
||||
what is being referred to as the "multi-planar API".</para>
|
||||
|
||||
<para>Some of the V4L2 API calls and structures are interpreted differently,
|
||||
depending on whether single- or multi-planar API is being used. An application
|
||||
can choose whether to use one or the other by passing a corresponding buffer
|
||||
type to its ioctl calls. Multi-planar versions of buffer types are suffixed
|
||||
with an `_MPLANE' string. For a list of available multi-planar buffer types
|
||||
see &v4l2-buf-type;.
|
||||
</para>
|
||||
|
||||
<section>
|
||||
<title>Multi-planar formats</title>
|
||||
<para>Multi-planar API introduces new multi-planar formats. Those formats
|
||||
use a separate set of FourCC codes. It is important to distinguish between
|
||||
the multi-planar API and a multi-planar format. Multi-planar API calls can
|
||||
handle all single-planar formats as well (as long as they are passed in
|
||||
multi-planar API structures), while the single-planar API cannot
|
||||
handle multi-planar formats.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Calls that distinguish between single and multi-planar APIs</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>&VIDIOC-QUERYCAP;</term>
|
||||
<listitem><para>Two additional multi-planar capabilities are added. They can
|
||||
be set together with non-multi-planar ones for devices that handle
|
||||
both single- and multi-planar formats.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>&VIDIOC-G-FMT;, &VIDIOC-S-FMT;, &VIDIOC-TRY-FMT;</term>
|
||||
<listitem><para>New structures for describing multi-planar formats are added:
|
||||
&v4l2-pix-format-mplane; and &v4l2-plane-pix-format;. Drivers may
|
||||
define new multi-planar formats, which have distinct FourCC codes from
|
||||
the existing single-planar ones.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>&VIDIOC-QBUF;, &VIDIOC-DQBUF;, &VIDIOC-QUERYBUF;</term>
|
||||
<listitem><para>A new &v4l2-plane; structure for describing planes is added.
|
||||
Arrays of this structure are passed in the new
|
||||
<structfield>m.planes</structfield> field of &v4l2-buffer;.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>&VIDIOC-REQBUFS;</term>
|
||||
<listitem><para>Will allocate multi-planar buffers as requested.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</section>
|
||||
</section>
|
File diff suppressed because it is too large
Load Diff
|
@ -85,6 +85,17 @@ Remote Controller chapter.</contrib>
|
|||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
|
||||
<author>
|
||||
<firstname>Pawel</firstname>
|
||||
<surname>Osciak</surname>
|
||||
<contrib>Designed and documented the multi-planar API.</contrib>
|
||||
<affiliation>
|
||||
<address>
|
||||
<email>pawel AT osciak.com</email>
|
||||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
|
@ -102,7 +113,8 @@ Remote Controller chapter.</contrib>
|
|||
<year>2010</year>
|
||||
<year>2011</year>
|
||||
<holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
|
||||
Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
|
||||
Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab,
|
||||
Pawel Osciak</holder>
|
||||
</copyright>
|
||||
<legalnotice>
|
||||
<para>Except when explicitly stated as GPL, programming examples within
|
||||
|
@ -115,6 +127,13 @@ 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>2.6.39</revnumber>
|
||||
<date>2011-03-01</date>
|
||||
<authorinitials>mcc, po</authorinitials>
|
||||
<revremark>Removed VIDIOC_*_OLD from videodev2.h header and update it to reflect latest changes. Added the <link linkend="planar-apis">multi-planar API</link>.</revremark>
|
||||
</revision>
|
||||
|
||||
<revision>
|
||||
<revnumber>2.6.37</revnumber>
|
||||
<date>2010-08-06</date>
|
||||
|
@ -382,7 +401,7 @@ and discussions on the V4L mailing list.</revremark>
|
|||
</partinfo>
|
||||
|
||||
<title>Video for Linux Two API Specification</title>
|
||||
<subtitle>Revision 2.6.38</subtitle>
|
||||
<subtitle>Revision 2.6.39</subtitle>
|
||||
|
||||
<chapter id="common">
|
||||
&sub-common;
|
||||
|
@ -411,6 +430,7 @@ and discussions on the V4L mailing list.</revremark>
|
|||
<section id="radio"> &sub-dev-radio; </section>
|
||||
<section id="rds"> &sub-dev-rds; </section>
|
||||
<section id="event"> &sub-dev-event; </section>
|
||||
<section id="subdev"> &sub-dev-subdev; </section>
|
||||
</chapter>
|
||||
|
||||
<chapter id="driver">
|
||||
|
@ -478,6 +498,12 @@ and discussions on the V4L mailing list.</revremark>
|
|||
&sub-reqbufs;
|
||||
&sub-s-hw-freq-seek;
|
||||
&sub-streamon;
|
||||
&sub-subdev-enum-frame-interval;
|
||||
&sub-subdev-enum-frame-size;
|
||||
&sub-subdev-enum-mbus-code;
|
||||
&sub-subdev-g-crop;
|
||||
&sub-subdev-g-fmt;
|
||||
&sub-subdev-g-frame-interval;
|
||||
&sub-subscribe-event;
|
||||
<!-- End of ioctls. -->
|
||||
&sub-mmap;
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
* Moved from videodev.h
|
||||
*/
|
||||
#define VIDEO_MAX_FRAME 32
|
||||
#define VIDEO_MAX_PLANES 8
|
||||
|
||||
#ifndef __KERNEL__
|
||||
|
||||
|
@ -158,9 +159,23 @@ enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> {
|
|||
/* Experimental */
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
|
||||
#endif
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10,
|
||||
V4L2_BUF_TYPE_PRIVATE = 0x80,
|
||||
};
|
||||
|
||||
#define V4L2_TYPE_IS_MULTIPLANAR(type) \
|
||||
((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE \
|
||||
|| (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
|
||||
|
||||
#define V4L2_TYPE_IS_OUTPUT(type) \
|
||||
((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT \
|
||||
|| (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE \
|
||||
|| (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)
|
||||
|
||||
enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link> {
|
||||
V4L2_TUNER_RADIO = 1,
|
||||
V4L2_TUNER_ANALOG_TV = 2,
|
||||
|
@ -246,6 +261,11 @@ struct <link linkend="v4l2-capability">v4l2_capability</link> {
|
|||
#define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek */
|
||||
#define V4L2_CAP_RDS_OUTPUT 0x00000800 /* Is an RDS encoder */
|
||||
|
||||
/* Is a video capture device that supports multiplanar formats */
|
||||
#define V4L2_CAP_VIDEO_CAPTURE_MPLANE 0x00001000
|
||||
/* Is a video output device that supports multiplanar formats */
|
||||
#define V4L2_CAP_VIDEO_OUTPUT_MPLANE 0x00002000
|
||||
|
||||
#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
|
||||
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
|
||||
#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */
|
||||
|
@ -320,6 +340,13 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
|
|||
#define <link linkend="V4L2-PIX-FMT-NV16">V4L2_PIX_FMT_NV16</link> v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */
|
||||
#define <link linkend="V4L2-PIX-FMT-NV61">V4L2_PIX_FMT_NV61</link> v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */
|
||||
|
||||
/* two non contiguous planes - one Y, one Cr + Cb interleaved */
|
||||
#define <link linkend="V4L2-PIX-FMT-NV12M">V4L2_PIX_FMT_NV12M</link> v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */
|
||||
#define <link linkend="V4L2-PIX-FMT-NV12MT">V4L2_PIX_FMT_NV12MT</link> v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */
|
||||
|
||||
/* three non contiguous planes - Y, Cb, Cr */
|
||||
#define <link linkend="V4L2-PIX-FMT-YUV420M">V4L2_PIX_FMT_YUV420M</link> v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420 planar */
|
||||
|
||||
/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
|
||||
#define <link linkend="V4L2-PIX-FMT-SBGGR8">V4L2_PIX_FMT_SBGGR8</link> v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */
|
||||
#define <link linkend="V4L2-PIX-FMT-SGBRG8">V4L2_PIX_FMT_SGBRG8</link> v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */
|
||||
|
@ -518,6 +545,62 @@ struct <link linkend="v4l2-requestbuffers">v4l2_requestbuffers</link> {
|
|||
__u32 reserved[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct <link linkend="v4l2-plane">v4l2_plane</link> - plane info for multi-planar buffers
|
||||
* @bytesused: number of bytes occupied by data in the plane (payload)
|
||||
* @length: size of this plane (NOT the payload) in bytes
|
||||
* @mem_offset: when memory in the associated struct <link linkend="v4l2-buffer">v4l2_buffer</link> is
|
||||
* V4L2_MEMORY_MMAP, equals the offset from the start of
|
||||
* the device memory for this plane (or is a "cookie" that
|
||||
* should be passed to mmap() called on the video node)
|
||||
* @userptr: when memory is V4L2_MEMORY_USERPTR, a userspace pointer
|
||||
* pointing to this plane
|
||||
* @data_offset: offset in the plane to the start of data; usually 0,
|
||||
* unless there is a header in front of the data
|
||||
*
|
||||
* Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer
|
||||
* with two planes can have one plane for Y, and another for interleaved CbCr
|
||||
* components. Each plane can reside in a separate memory buffer, or even in
|
||||
* a completely separate memory node (e.g. in embedded devices).
|
||||
*/
|
||||
struct <link linkend="v4l2-plane">v4l2_plane</link> {
|
||||
__u32 bytesused;
|
||||
__u32 length;
|
||||
union {
|
||||
__u32 mem_offset;
|
||||
unsigned long userptr;
|
||||
} m;
|
||||
__u32 data_offset;
|
||||
__u32 reserved[11];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct <link linkend="v4l2-buffer">v4l2_buffer</link> - video buffer info
|
||||
* @index: id number of the buffer
|
||||
* @type: buffer type (type == *_MPLANE for multiplanar buffers)
|
||||
* @bytesused: number of bytes occupied by data in the buffer (payload);
|
||||
* unused (set to 0) for multiplanar buffers
|
||||
* @flags: buffer informational flags
|
||||
* @field: field order of the image in the buffer
|
||||
* @timestamp: frame timestamp
|
||||
* @timecode: frame timecode
|
||||
* @sequence: sequence count of this frame
|
||||
* @memory: the method, in which the actual video data is passed
|
||||
* @offset: for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP;
|
||||
* offset from the start of the device memory for this plane,
|
||||
* (or a "cookie" that should be passed to mmap() as offset)
|
||||
* @userptr: for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;
|
||||
* a userspace pointer pointing to this buffer
|
||||
* @planes: for multiplanar buffers; userspace pointer to the array of plane
|
||||
* info structs for this buffer
|
||||
* @length: size in bytes of the buffer (NOT its payload) for single-plane
|
||||
* buffers (when type != *_MPLANE); number of elements in the
|
||||
* planes array for multi-plane buffers
|
||||
* @input: input number from which the video data has has been captured
|
||||
*
|
||||
* Contains data exchanged by application and driver using one of the Streaming
|
||||
* I/O methods.
|
||||
*/
|
||||
struct <link linkend="v4l2-buffer">v4l2_buffer</link> {
|
||||
__u32 index;
|
||||
enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
|
||||
|
@ -533,6 +616,7 @@ struct <link linkend="v4l2-buffer">v4l2_buffer</link> {
|
|||
union {
|
||||
__u32 offset;
|
||||
unsigned long userptr;
|
||||
struct <link linkend="v4l2-plane">v4l2_plane</link> *planes;
|
||||
} m;
|
||||
__u32 length;
|
||||
__u32 input;
|
||||
|
@ -1623,12 +1707,56 @@ struct <link linkend="v4l2-mpeg-vbi-fmt-ivtv">v4l2_mpeg_vbi_fmt_ivtv</link> {
|
|||
* A G G R E G A T E S T R U C T U R E S
|
||||
*/
|
||||
|
||||
/* Stream data format
|
||||
/**
|
||||
* struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link> - additional, per-plane format definition
|
||||
* @sizeimage: maximum size in bytes required for data, for which
|
||||
* this plane will be used
|
||||
* @bytesperline: distance in bytes between the leftmost pixels in two
|
||||
* adjacent lines
|
||||
*/
|
||||
struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link> {
|
||||
__u32 sizeimage;
|
||||
__u16 bytesperline;
|
||||
__u16 reserved[7];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link> - multiplanar format definition
|
||||
* @width: image width in pixels
|
||||
* @height: image height in pixels
|
||||
* @pixelformat: little endian four character code (fourcc)
|
||||
* @field: field order (for interlaced video)
|
||||
* @colorspace: supplemental to pixelformat
|
||||
* @plane_fmt: per-plane information
|
||||
* @num_planes: number of planes for this format
|
||||
*/
|
||||
struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link> {
|
||||
__u32 width;
|
||||
__u32 height;
|
||||
__u32 pixelformat;
|
||||
enum <link linkend="v4l2-field">v4l2_field</link> field;
|
||||
enum <link linkend="v4l2-colorspace">v4l2_colorspace</link> colorspace;
|
||||
|
||||
struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link> plane_fmt[VIDEO_MAX_PLANES];
|
||||
__u8 num_planes;
|
||||
__u8 reserved[11];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* struct <link linkend="v4l2-format">v4l2_format</link> - stream data format
|
||||
* @type: type of the data stream
|
||||
* @pix: definition of an image format
|
||||
* @pix_mp: definition of a multiplanar image format
|
||||
* @win: definition of an overlaid image
|
||||
* @vbi: raw VBI capture or output parameters
|
||||
* @sliced: sliced VBI capture or output parameters
|
||||
* @raw_data: placeholder for future extensions and custom formats
|
||||
*/
|
||||
struct <link linkend="v4l2-format">v4l2_format</link> {
|
||||
enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
|
||||
union {
|
||||
struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
|
||||
struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link> pix_mp; /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
|
||||
struct <link linkend="v4l2-window">v4l2_window</link> win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
|
||||
struct <link linkend="v4l2-vbi-format">v4l2_vbi_format</link> vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */
|
||||
struct <link linkend="v4l2-sliced-vbi-format">v4l2_sliced_vbi_format</link> sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
|
||||
|
@ -1636,7 +1764,6 @@ struct <link linkend="v4l2-format">v4l2_format</link> {
|
|||
} fmt;
|
||||
};
|
||||
|
||||
|
||||
/* Stream type-dependent parameters
|
||||
*/
|
||||
struct <link linkend="v4l2-streamparm">v4l2_streamparm</link> {
|
||||
|
@ -1809,16 +1936,6 @@ struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
|
|||
/* Reminder: when adding new ioctls please add support for them to
|
||||
drivers/media/video/v4l2-compat-ioctl32.c as well! */
|
||||
|
||||
#ifdef __OLD_VIDIOC_
|
||||
/* for compatibility, will go away some day */
|
||||
#define VIDIOC_OVERLAY_OLD _IOWR('V', 14, int)
|
||||
#define VIDIOC_S_PARM_OLD _IOW('V', 22, struct <link linkend="v4l2-streamparm">v4l2_streamparm</link>)
|
||||
#define VIDIOC_S_CTRL_OLD _IOW('V', 28, struct <link linkend="v4l2-control">v4l2_control</link>)
|
||||
#define VIDIOC_G_AUDIO_OLD _IOWR('V', 33, struct <link linkend="v4l2-audio">v4l2_audio</link>)
|
||||
#define VIDIOC_G_AUDOUT_OLD _IOWR('V', 49, struct <link linkend="v4l2-audioout">v4l2_audioout</link>)
|
||||
#define VIDIOC_CROPCAP_OLD _IOR('V', 58, struct <link linkend="v4l2-cropcap">v4l2_cropcap</link>)
|
||||
#endif
|
||||
|
||||
#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */
|
||||
|
||||
#endif /* __LINUX_VIDEODEV2_H */
|
||||
|
|
|
@ -76,7 +76,9 @@ pixelformat</structfield> field.</entry>
|
|||
<entry>Type of the data stream, set by the application.
|
||||
Only these types are valid here:
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>,
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>,
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>, and custom (driver
|
||||
defined) types with code <constant>V4L2_BUF_TYPE_PRIVATE</constant>
|
||||
and higher.</entry>
|
||||
|
|
|
@ -60,11 +60,13 @@ application.</para>
|
|||
<structfield>type</structfield> field of a struct
|
||||
<structname>v4l2_format</structname> to the respective buffer (stream)
|
||||
type. For example video capture devices use
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>. When the application
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> or
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>. When the application
|
||||
calls the <constant>VIDIOC_G_FMT</constant> ioctl with a pointer to
|
||||
this structure the driver fills the respective member of the
|
||||
<structfield>fmt</structfield> union. In case of video capture devices
|
||||
that is the &v4l2-pix-format; <structfield>pix</structfield> member.
|
||||
that is either the &v4l2-pix-format; <structfield>pix</structfield> or
|
||||
the &v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member.
|
||||
When the requested buffer type is not supported drivers return an
|
||||
&EINVAL;.</para>
|
||||
|
||||
|
@ -131,6 +133,15 @@ this ioctl.</para>
|
|||
<entry>Definition of an image format, see <xref
|
||||
linkend="pixfmt" />, used by video capture and output
|
||||
devices.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>&v4l2-pix-format-mplane;</entry>
|
||||
<entry><structfield>pix_mp</structfield></entry>
|
||||
<entry>Definition of an image format, see <xref
|
||||
linkend="pixfmt" />, used by video capture and output
|
||||
devices that support the <link linkend="planar-apis">multi-planar
|
||||
version of the API</link>.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
|
|
|
@ -64,7 +64,8 @@ zero to the number of buffers allocated with &VIDIOC-REQBUFS;
|
|||
contents of the struct <structname>v4l2_buffer</structname> returned
|
||||
by a &VIDIOC-QUERYBUF; ioctl will do as well. When the buffer is
|
||||
intended for output (<structfield>type</structfield> is
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> or
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
|
||||
<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>, or
|
||||
<constant>V4L2_BUF_TYPE_VBI_OUTPUT</constant>) applications must also
|
||||
initialize the <structfield>bytesused</structfield>,
|
||||
<structfield>field</structfield> and
|
||||
|
@ -75,7 +76,11 @@ supports capturing from specific video inputs and you want to specify a video
|
|||
input, then <structfield>flags</structfield> should be set to
|
||||
<constant>V4L2_BUF_FLAG_INPUT</constant> and the field
|
||||
<structfield>input</structfield> must be initialized to the desired input.
|
||||
The <structfield>reserved</structfield> field must be set to 0.
|
||||
The <structfield>reserved</structfield> field must be set to 0. When using
|
||||
the <link linkend="planar-apis">multi-planar API</link>, the
|
||||
<structfield>m.planes</structfield> field must contain a userspace pointer
|
||||
to a filled-in array of &v4l2-plane; and the <structfield>length</structfield>
|
||||
field must be set to the number of elements in that array.
|
||||
</para>
|
||||
|
||||
<para>To enqueue a <link linkend="mmap">memory mapped</link>
|
||||
|
@ -93,10 +98,13 @@ structure the driver sets the
|
|||
buffer applications set the <structfield>memory</structfield>
|
||||
field to <constant>V4L2_MEMORY_USERPTR</constant>, the
|
||||
<structfield>m.userptr</structfield> field to the address of the
|
||||
buffer and <structfield>length</structfield> to its size.
|
||||
When <constant>VIDIOC_QBUF</constant> is called with a pointer to this
|
||||
structure the driver sets the <constant>V4L2_BUF_FLAG_QUEUED</constant>
|
||||
flag and clears the <constant>V4L2_BUF_FLAG_MAPPED</constant> and
|
||||
buffer and <structfield>length</structfield> to its size. When the multi-planar
|
||||
API is used, <structfield>m.userptr</structfield> and
|
||||
<structfield>length</structfield> members of the passed array of &v4l2-plane;
|
||||
have to be used instead. When <constant>VIDIOC_QBUF</constant> is called with
|
||||
a pointer to this structure the driver sets the
|
||||
<constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
|
||||
<constant>V4L2_BUF_FLAG_MAPPED</constant> and
|
||||
<constant>V4L2_BUF_FLAG_DONE</constant> flags in the
|
||||
<structfield>flags</structfield> field, or it returns an error code.
|
||||
This ioctl locks the memory pages of the buffer in physical memory,
|
||||
|
@ -115,7 +123,9 @@ remaining fields or returns an error code. The driver may also set
|
|||
<constant>V4L2_BUF_FLAG_ERROR</constant> in the <structfield>flags</structfield>
|
||||
field. It indicates a non-critical (recoverable) streaming error. In such case
|
||||
the application may continue as normal, but should be aware that data in the
|
||||
dequeued buffer might be corrupted.</para>
|
||||
dequeued buffer might be corrupted. When using the multi-planar API, the
|
||||
planes array does not have to be passed; the <structfield>m.planes</structfield>
|
||||
member must be set to NULL in that case.</para>
|
||||
|
||||
<para>By default <constant>VIDIOC_DQBUF</constant> blocks when no
|
||||
buffer is in the outgoing queue. When the
|
||||
|
|
|
@ -61,6 +61,10 @@ buffer at any time after buffers have been allocated with the
|
|||
to the number of buffers allocated with &VIDIOC-REQBUFS;
|
||||
(&v4l2-requestbuffers; <structfield>count</structfield>) minus one.
|
||||
The <structfield>reserved</structfield> field should to set to 0.
|
||||
When using the <link linkend="planar-apis">multi-planar API</link>, the
|
||||
<structfield>m.planes</structfield> field must contain a userspace pointer to an
|
||||
array of &v4l2-plane; and the <structfield>length</structfield> field has
|
||||
to be set to the number of elements in that array.
|
||||
After calling <constant>VIDIOC_QUERYBUF</constant> with a pointer to
|
||||
this structure drivers return an error code or fill the rest of
|
||||
the structure.</para>
|
||||
|
@ -70,11 +74,13 @@ the structure.</para>
|
|||
<constant>V4L2_BUF_FLAG_QUEUED</constant> and
|
||||
<constant>V4L2_BUF_FLAG_DONE</constant> flags will be valid. The
|
||||
<structfield>memory</structfield> field will be set to the current
|
||||
I/O method, the <structfield>m.offset</structfield>
|
||||
I/O method. For the single-planar API, the <structfield>m.offset</structfield>
|
||||
contains the offset of the buffer from the start of the device memory,
|
||||
the <structfield>length</structfield> field its size. The driver may
|
||||
or may not set the remaining fields and flags, they are meaningless in
|
||||
this context.</para>
|
||||
the <structfield>length</structfield> field its size. For the multi-planar API,
|
||||
fields <structfield>m.mem_offset</structfield> and
|
||||
<structfield>length</structfield> in the <structfield>m.planes</structfield>
|
||||
array elements will be used instead. The driver may or may not set the remaining
|
||||
fields and flags, they are meaningless in this context.</para>
|
||||
|
||||
<para>The <structname>v4l2_buffer</structname> structure is
|
||||
specified in <xref linkend="buffer" />.</para>
|
||||
|
|
|
@ -142,15 +142,29 @@ this array to zero.</entry>
|
|||
<row>
|
||||
<entry><constant>V4L2_CAP_VIDEO_CAPTURE</constant></entry>
|
||||
<entry>0x00000001</entry>
|
||||
<entry>The device supports the <link
|
||||
<entry>The device supports the single-planar API through the <link
|
||||
linkend="capture">Video Capture</link> interface.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CAP_VIDEO_CAPTURE_MPLANE</constant></entry>
|
||||
<entry>0x00001000</entry>
|
||||
<entry>The device supports the
|
||||
<link linkend="planar-apis">multi-planar API</link> through the
|
||||
<link linkend="capture">Video Capture</link> interface.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CAP_VIDEO_OUTPUT</constant></entry>
|
||||
<entry>0x00000002</entry>
|
||||
<entry>The device supports the <link
|
||||
<entry>The device supports the single-planar API through the <link
|
||||
linkend="output">Video Output</link> interface.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CAP_VIDEO_OUTPUT_MPLANE</constant></entry>
|
||||
<entry>0x00002000</entry>
|
||||
<entry>The device supports the
|
||||
<link linkend="planar-apis">multi-planar API</link> through the
|
||||
<link linkend="output">Video Output</link> interface.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CAP_VIDEO_OVERLAY</constant></entry>
|
||||
<entry>0x00000004</entry>
|
||||
|
|
|
@ -93,6 +93,15 @@ synchronize with other events.</para>
|
|||
been allocated (memory mapping) or enqueued (output) yet.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EPIPE</errorcode></term>
|
||||
<listitem>
|
||||
<para>The driver implements <link
|
||||
linkend="pad-level-formats">pad-level format configuration</link> and
|
||||
the pipeline configuration is invalid.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
<refentry id="vidioc-subdev-enum-frame-interval">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refname>
|
||||
<refpurpose>Enumerate frame intervals</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct v4l2_subdev_frame_interval_enum *
|
||||
<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>&fd;</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<note>
|
||||
<title>Experimental</title>
|
||||
<para>This is an <link linkend="experimental">experimental</link>
|
||||
interface and may change in the future.</para>
|
||||
</note>
|
||||
|
||||
<para>This ioctl lets applications enumerate available frame intervals on a
|
||||
given sub-device pad. Frame intervals only makes sense for sub-devices that
|
||||
can control the frame period on their own. This includes, for instance,
|
||||
image sensors and TV tuners.</para>
|
||||
|
||||
<para>For the common use case of image sensors, the frame intervals
|
||||
available on the sub-device output pad depend on the frame format and size
|
||||
on the same pad. Applications must thus specify the desired format and size
|
||||
when enumerating frame intervals.</para>
|
||||
|
||||
<para>To enumerate frame intervals applications initialize the
|
||||
<structfield>index</structfield>, <structfield>pad</structfield>,
|
||||
<structfield>code</structfield>, <structfield>width</structfield> and
|
||||
<structfield>height</structfield> fields of
|
||||
&v4l2-subdev-frame-interval-enum; and call the
|
||||
<constant>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</constant> ioctl with a pointer
|
||||
to this structure. Drivers fill the rest of the structure or return
|
||||
an &EINVAL; if one of the input fields is invalid. All frame intervals are
|
||||
enumerable by beginning at index zero and incrementing by one until
|
||||
<errorcode>EINVAL</errorcode> is returned.</para>
|
||||
|
||||
<para>Available frame intervals may depend on the current 'try' formats
|
||||
at other pads of the sub-device, as well as on the current active links. See
|
||||
&VIDIOC-SUBDEV-G-FMT; for more information about the try formats.</para>
|
||||
|
||||
<para>Sub-devices that support the frame interval enumeration ioctl should
|
||||
implemented it on a single pad only. Its behaviour when supported on
|
||||
multiple pads of the same sub-device is not defined.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="v4l2-subdev-frame-interval-enum">
|
||||
<title>struct <structname>v4l2_subdev_frame_interval_enum</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>index</structfield></entry>
|
||||
<entry>Number of the format in the enumeration, set by the
|
||||
application.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>pad</structfield></entry>
|
||||
<entry>Pad number as reported by the media controller API.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>code</structfield></entry>
|
||||
<entry>The media bus format code, as defined in
|
||||
<xref linkend="v4l2-mbus-format" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>width</structfield></entry>
|
||||
<entry>Frame width, in pixels.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>height</structfield></entry>
|
||||
<entry>Frame height, in pixels.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>&v4l2-fract;</entry>
|
||||
<entry><structfield>interval</structfield></entry>
|
||||
<entry>Period, in seconds, between consecutive video frames.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[9]</entry>
|
||||
<entry>Reserved for future extensions. Applications and drivers must
|
||||
set the array to zero.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &v4l2-subdev-frame-interval-enum;
|
||||
<structfield>pad</structfield> references a non-existing pad, one of
|
||||
the <structfield>code</structfield>, <structfield>width</structfield>
|
||||
or <structfield>height</structfield> fields are invalid for the given
|
||||
pad or the <structfield>index</structfield> field is out of bounds.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,154 @@
|
|||
<refentry id="vidioc-subdev-enum-frame-size">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_FRAME_SIZE</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</refname>
|
||||
<refpurpose>Enumerate media bus frame sizes</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct v4l2_subdev_frame_size_enum *
|
||||
<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>&fd;</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<note>
|
||||
<title>Experimental</title>
|
||||
<para>This is an <link linkend="experimental">experimental</link>
|
||||
interface and may change in the future.</para>
|
||||
</note>
|
||||
|
||||
<para>This ioctl allows applications to enumerate all frame sizes
|
||||
supported by a sub-device on the given pad for the given media bus format.
|
||||
Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE;
|
||||
ioctl.</para>
|
||||
|
||||
<para>To enumerate frame sizes applications initialize the
|
||||
<structfield>pad</structfield>, <structfield>code</structfield> and
|
||||
<structfield>index</structfield> fields of the
|
||||
&v4l2-subdev-mbus-code-enum; and call the
|
||||
<constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant> ioctl with a pointer to
|
||||
the structure. Drivers fill the minimum and maximum frame sizes or return
|
||||
an &EINVAL; if one of the input parameters is invalid.</para>
|
||||
|
||||
<para>Sub-devices that only support discrete frame sizes (such as most
|
||||
sensors) will return one or more frame sizes with identical minimum and
|
||||
maximum values.</para>
|
||||
|
||||
<para>Not all possible sizes in given [minimum, maximum] ranges need to be
|
||||
supported. For instance, a scaler that uses a fixed-point scaling ratio
|
||||
might not be able to produce every frame size between the minimum and
|
||||
maximum values. Applications must use the &VIDIOC-SUBDEV-S-FMT; ioctl to
|
||||
try the sub-device for an exact supported frame size.</para>
|
||||
|
||||
<para>Available frame sizes may depend on the current 'try' formats at other
|
||||
pads of the sub-device, as well as on the current active links and the
|
||||
current values of V4L2 controls. See &VIDIOC-SUBDEV-G-FMT; for more
|
||||
information about try formats.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="v4l2-subdev-frame-size-enum">
|
||||
<title>struct <structname>v4l2_subdev_frame_size_enum</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>index</structfield></entry>
|
||||
<entry>Number of the format in the enumeration, set by the
|
||||
application.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>pad</structfield></entry>
|
||||
<entry>Pad number as reported by the media controller API.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>code</structfield></entry>
|
||||
<entry>The media bus format code, as defined in
|
||||
<xref linkend="v4l2-mbus-format" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>min_width</structfield></entry>
|
||||
<entry>Minimum frame width, in pixels.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>max_width</structfield></entry>
|
||||
<entry>Maximum frame width, in pixels.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>min_height</structfield></entry>
|
||||
<entry>Minimum frame height, in pixels.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>max_height</structfield></entry>
|
||||
<entry>Maximum frame height, in pixels.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[9]</entry>
|
||||
<entry>Reserved for future extensions. Applications and drivers must
|
||||
set the array to zero.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &v4l2-subdev-frame-size-enum; <structfield>pad</structfield>
|
||||
references a non-existing pad, the <structfield>code</structfield> is
|
||||
invalid for the given pad or the <structfield>index</structfield>
|
||||
field is out of bounds.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,119 @@
|
|||
<refentry id="vidioc-subdev-enum-mbus-code">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_MBUS_CODE</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>VIDIOC_SUBDEV_ENUM_MBUS_CODE</refname>
|
||||
<refpurpose>Enumerate media bus formats</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct v4l2_subdev_mbus_code_enum *
|
||||
<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>&fd;</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>VIDIOC_SUBDEV_ENUM_MBUS_CODE</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<note>
|
||||
<title>Experimental</title>
|
||||
<para>This is an <link linkend="experimental">experimental</link>
|
||||
interface and may change in the future.</para>
|
||||
</note>
|
||||
|
||||
<para>To enumerate media bus formats available at a given sub-device pad
|
||||
applications initialize the <structfield>pad</structfield> and
|
||||
<structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and
|
||||
call the <constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant> ioctl with a
|
||||
pointer to this structure. Drivers fill the rest of the structure or return
|
||||
an &EINVAL; if either the <structfield>pad</structfield> or
|
||||
<structfield>index</structfield> are invalid. All media bus formats are
|
||||
enumerable by beginning at index zero and incrementing by one until
|
||||
<errorcode>EINVAL</errorcode> is returned.</para>
|
||||
|
||||
<para>Available media bus formats may depend on the current 'try' formats
|
||||
at other pads of the sub-device, as well as on the current active links. See
|
||||
&VIDIOC-SUBDEV-G-FMT; for more information about the try formats.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="v4l2-subdev-mbus-code-enum">
|
||||
<title>struct <structname>v4l2_subdev_mbus_code_enum</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>pad</structfield></entry>
|
||||
<entry>Pad number as reported by the media controller API.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>index</structfield></entry>
|
||||
<entry>Number of the format in the enumeration, set by the
|
||||
application.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>code</structfield></entry>
|
||||
<entry>The media bus format code, as defined in
|
||||
<xref linkend="v4l2-mbus-format" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[9]</entry>
|
||||
<entry>Reserved for future extensions. Applications and drivers must
|
||||
set the array to zero.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &v4l2-subdev-mbus-code-enum; <structfield>pad</structfield>
|
||||
references a non-existing pad, or the <structfield>index</structfield>
|
||||
field is out of bounds.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,155 @@
|
|||
<refentry id="vidioc-subdev-g-crop">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>VIDIOC_SUBDEV_G_CROP</refname>
|
||||
<refname>VIDIOC_SUBDEV_S_CROP</refname>
|
||||
<refpurpose>Get or set the crop rectangle on a subdev pad</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct v4l2_subdev_crop *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>const struct v4l2_subdev_crop *<parameter>argp</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>&fd;</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<note>
|
||||
<title>Experimental</title>
|
||||
<para>This is an <link linkend="experimental">experimental</link>
|
||||
interface and may change in the future.</para>
|
||||
</note>
|
||||
|
||||
<para>To retrieve the current crop rectangle applications set the
|
||||
<structfield>pad</structfield> field of a &v4l2-subdev-crop; to the
|
||||
desired pad number as reported by the media API and the
|
||||
<structfield>which</structfield> field to
|
||||
<constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. They then call the
|
||||
<constant>VIDIOC_SUBDEV_G_CROP</constant> ioctl with a pointer to this
|
||||
structure. The driver fills the members of the <structfield>rect</structfield>
|
||||
field or returns &EINVAL; if the input arguments are invalid, or if cropping
|
||||
is not supported on the given pad.</para>
|
||||
|
||||
<para>To change the current crop rectangle applications set both the
|
||||
<structfield>pad</structfield> and <structfield>which</structfield> fields
|
||||
and all members of the <structfield>rect</structfield> field. They then call
|
||||
the <constant>VIDIOC_SUBDEV_S_CROP</constant> ioctl with a pointer to this
|
||||
structure. The driver verifies the requested crop rectangle, adjusts it
|
||||
based on the hardware capabilities and configures the device. Upon return
|
||||
the &v4l2-subdev-crop; contains the current format as would be returned
|
||||
by a <constant>VIDIOC_SUBDEV_G_CROP</constant> call.</para>
|
||||
|
||||
<para>Applications can query the device capabilities by setting the
|
||||
<structfield>which</structfield> to
|
||||
<constant>V4L2_SUBDEV_FORMAT_TRY</constant>. When set, 'try' crop
|
||||
rectangles are not applied to the device by the driver, but are mangled
|
||||
exactly as active crop rectangles and stored in the sub-device file handle.
|
||||
Two applications querying the same sub-device would thus not interact with
|
||||
each other.</para>
|
||||
|
||||
<para>Drivers must not return an error solely because the requested crop
|
||||
rectangle doesn't match the device capabilities. They must instead modify
|
||||
the rectangle to match what the hardware can provide. The modified format
|
||||
should be as close as possible to the original request.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="v4l2-subdev-crop">
|
||||
<title>struct <structname>v4l2_subdev_crop</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>pad</structfield></entry>
|
||||
<entry>Pad number as reported by the media framework.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>which</structfield></entry>
|
||||
<entry>Crop rectangle to get or set, from
|
||||
&v4l2-subdev-format-whence;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>&v4l2-rect;</entry>
|
||||
<entry><structfield>rect</structfield></entry>
|
||||
<entry>Crop rectangle boundaries, in pixels.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[8]</entry>
|
||||
<entry>Reserved for future extensions. Applications and drivers must
|
||||
set the array to zero.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EBUSY</errorcode></term>
|
||||
<listitem>
|
||||
<para>The crop rectangle can't be changed because the pad is currently
|
||||
busy. This can be caused, for instance, by an active video stream on
|
||||
the pad. The ioctl must not be retried without performing another
|
||||
action to fix the problem first. Only returned by
|
||||
<constant>VIDIOC_SUBDEV_S_CROP</constant></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &v4l2-subdev-crop; <structfield>pad</structfield>
|
||||
references a non-existing pad, the <structfield>which</structfield>
|
||||
field references a non-existing format, or cropping is not supported
|
||||
on the given subdev pad.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,180 @@
|
|||
<refentry id="vidioc-subdev-g-fmt">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>VIDIOC_SUBDEV_G_FMT</refname>
|
||||
<refname>VIDIOC_SUBDEV_S_FMT</refname>
|
||||
<refpurpose>Get or set the data format on a subdev pad</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct v4l2_subdev_format *<parameter>argp</parameter>
|
||||
</paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>&fd;</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<note>
|
||||
<title>Experimental</title>
|
||||
<para>This is an <link linkend="experimental">experimental</link>
|
||||
interface and may change in the future.</para>
|
||||
</note>
|
||||
|
||||
<para>These ioctls are used to negotiate the frame format at specific
|
||||
subdev pads in the image pipeline.</para>
|
||||
|
||||
<para>To retrieve the current format applications set the
|
||||
<structfield>pad</structfield> field of a &v4l2-subdev-format; to the
|
||||
desired pad number as reported by the media API and the
|
||||
<structfield>which</structfield> field to
|
||||
<constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. When they call the
|
||||
<constant>VIDIOC_SUBDEV_G_FMT</constant> ioctl with a pointer to this
|
||||
structure the driver fills the members of the <structfield>format</structfield>
|
||||
field.</para>
|
||||
|
||||
<para>To change the current format applications set both the
|
||||
<structfield>pad</structfield> and <structfield>which</structfield> fields
|
||||
and all members of the <structfield>format</structfield> field. When they
|
||||
call the <constant>VIDIOC_SUBDEV_S_FMT</constant> ioctl with a pointer to this
|
||||
structure the driver verifies the requested format, adjusts it based on the
|
||||
hardware capabilities and configures the device. Upon return the
|
||||
&v4l2-subdev-format; contains the current format as would be returned by a
|
||||
<constant>VIDIOC_SUBDEV_G_FMT</constant> call.</para>
|
||||
|
||||
<para>Applications can query the device capabilities by setting the
|
||||
<structfield>which</structfield> to
|
||||
<constant>V4L2_SUBDEV_FORMAT_TRY</constant>. When set, 'try' formats are not
|
||||
applied to the device by the driver, but are changed exactly as active
|
||||
formats and stored in the sub-device file handle. Two applications querying
|
||||
the same sub-device would thus not interact with each other.</para>
|
||||
|
||||
<para>For instance, to try a format at the output pad of a sub-device,
|
||||
applications would first set the try format at the sub-device input with the
|
||||
<constant>VIDIOC_SUBDEV_S_FMT</constant> ioctl. They would then either
|
||||
retrieve the default format at the output pad with the
|
||||
<constant>VIDIOC_SUBDEV_G_FMT</constant> ioctl, or set the desired output
|
||||
pad format with the <constant>VIDIOC_SUBDEV_S_FMT</constant> ioctl and check
|
||||
the returned value.</para>
|
||||
|
||||
<para>Try formats do not depend on active formats, but can depend on the
|
||||
current links configuration or sub-device controls value. For instance, a
|
||||
low-pass noise filter might crop pixels at the frame boundaries, modifying
|
||||
its output frame size.</para>
|
||||
|
||||
<para>Drivers must not return an error solely because the requested format
|
||||
doesn't match the device capabilities. They must instead modify the format
|
||||
to match what the hardware can provide. The modified format should be as
|
||||
close as possible to the original request.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="v4l2-subdev-format">
|
||||
<title>struct <structname>v4l2_subdev_format</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>pad</structfield></entry>
|
||||
<entry>Pad number as reported by the media controller API.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>which</structfield></entry>
|
||||
<entry>Format to modified, from &v4l2-subdev-format-whence;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>&v4l2-mbus-framefmt;</entry>
|
||||
<entry><structfield>format</structfield></entry>
|
||||
<entry>Definition of an image format, see <xref
|
||||
linkend="v4l2-mbus-framefmt" /> for details.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[8]</entry>
|
||||
<entry>Reserved for future extensions. Applications and drivers must
|
||||
set the array to zero.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table pgwide="1" frame="none" id="v4l2-subdev-format-whence">
|
||||
<title>enum <structname>v4l2_subdev_format_whence</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-def;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>V4L2_SUBDEV_FORMAT_TRY</entry>
|
||||
<entry>0</entry>
|
||||
<entry>Try formats, used for querying device capabilities.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>V4L2_SUBDEV_FORMAT_ACTIVE</entry>
|
||||
<entry>1</entry>
|
||||
<entry>Active formats, applied to the hardware.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EBUSY</errorcode></term>
|
||||
<listitem>
|
||||
<para>The format can't be changed because the pad is currently busy.
|
||||
This can be caused, for instance, by an active video stream on the
|
||||
pad. The ioctl must not be retried without performing another action
|
||||
to fix the problem first. Only returned by
|
||||
<constant>VIDIOC_SUBDEV_S_FMT</constant></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &v4l2-subdev-format; <structfield>pad</structfield>
|
||||
references a non-existing pad, or the <structfield>which</structfield>
|
||||
field references a non-existing format.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -0,0 +1,141 @@
|
|||
<refentry id="vidioc-subdev-g-frame-interval">
|
||||
<refmeta>
|
||||
<refentrytitle>ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>VIDIOC_SUBDEV_G_FRAME_INTERVAL</refname>
|
||||
<refname>VIDIOC_SUBDEV_S_FRAME_INTERVAL</refname>
|
||||
<refpurpose>Get or set the frame interval on a subdev pad</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcprototype>
|
||||
<funcdef>int <function>ioctl</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
<paramdef>int <parameter>request</parameter></paramdef>
|
||||
<paramdef>struct v4l2_subdev_frame_interval *<parameter>argp</parameter>
|
||||
</paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Arguments</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><parameter>fd</parameter></term>
|
||||
<listitem>
|
||||
<para>&fd;</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><parameter>argp</parameter></term>
|
||||
<listitem>
|
||||
<para></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<note>
|
||||
<title>Experimental</title>
|
||||
<para>This is an <link linkend="experimental">experimental</link>
|
||||
interface and may change in the future.</para>
|
||||
</note>
|
||||
|
||||
<para>These ioctls are used to get and set the frame interval at specific
|
||||
subdev pads in the image pipeline. The frame interval only makes sense for
|
||||
sub-devices that can control the frame period on their own. This includes,
|
||||
for instance, image sensors and TV tuners. Sub-devices that don't support
|
||||
frame intervals must not implement these ioctls.</para>
|
||||
|
||||
<para>To retrieve the current frame interval applications set the
|
||||
<structfield>pad</structfield> field of a &v4l2-subdev-frame-interval; to
|
||||
the desired pad number as reported by the media controller API. When they
|
||||
call the <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> ioctl with a
|
||||
pointer to this structure the driver fills the members of the
|
||||
<structfield>interval</structfield> field.</para>
|
||||
|
||||
<para>To change the current frame interval applications set both the
|
||||
<structfield>pad</structfield> field and all members of the
|
||||
<structfield>interval</structfield> field. When they call the
|
||||
<constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant> ioctl with a pointer to
|
||||
this structure the driver verifies the requested interval, adjusts it based
|
||||
on the hardware capabilities and configures the device. Upon return the
|
||||
&v4l2-subdev-frame-interval; contains the current frame interval as would be
|
||||
returned by a <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> call.
|
||||
</para>
|
||||
|
||||
<para>Drivers must not return an error solely because the requested interval
|
||||
doesn't match the device capabilities. They must instead modify the interval
|
||||
to match what the hardware can provide. The modified interval should be as
|
||||
close as possible to the original request.</para>
|
||||
|
||||
<para>Sub-devices that support the frame interval ioctls should implement
|
||||
them on a single pad only. Their behaviour when supported on multiple pads
|
||||
of the same sub-device is not defined.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="v4l2-subdev-frame-interval">
|
||||
<title>struct <structname>v4l2_subdev_frame_interval</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>pad</structfield></entry>
|
||||
<entry>Pad number as reported by the media controller API.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>&v4l2-fract;</entry>
|
||||
<entry><structfield>interval</structfield></entry>
|
||||
<entry>Period, in seconds, between consecutive video frames.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>reserved</structfield>[9]</entry>
|
||||
<entry>Reserved for future extensions. Applications and drivers must
|
||||
set the array to zero.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errorcode>EBUSY</errorcode></term>
|
||||
<listitem>
|
||||
<para>The frame interval can't be changed because the pad is currently
|
||||
busy. This can be caused, for instance, by an active video stream on
|
||||
the pad. The ioctl must not be retried without performing another
|
||||
action to fix the problem first. Only returned by
|
||||
<constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The &v4l2-subdev-frame-interval; <structfield>pad</structfield>
|
||||
references a non-existing pad, or the pad doesn't support frame
|
||||
intervals.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -556,6 +556,9 @@ sub ngene {
|
|||
my $hash1 = "d798d5a757121174f0dbc5f2833c0c85";
|
||||
my $file2 = "ngene_17.fw";
|
||||
my $hash2 = "26b687136e127b8ac24b81e0eeafc20b";
|
||||
my $url2 = "http://l4m-daten.de/downloads/firmware/dvb-s2/linux/all/";
|
||||
my $file3 = "ngene_18.fw";
|
||||
my $hash3 = "ebce3ea769a53e3e0b0197c3b3f127e3";
|
||||
|
||||
checkstandard();
|
||||
|
||||
|
@ -565,7 +568,10 @@ sub ngene {
|
|||
wgetfile($file2, $url . $file2);
|
||||
verify($file2, $hash2);
|
||||
|
||||
"$file1, $file2";
|
||||
wgetfile($file3, $url2 . $file3);
|
||||
verify($file3, $hash3);
|
||||
|
||||
"$file1, $file2, $file3";
|
||||
}
|
||||
|
||||
sub az6027{
|
||||
|
|
|
@ -4,7 +4,7 @@ following file(s) to this directory.
|
|||
for DM04+/QQBOX LME2510C (Sharp 7395 Tuner)
|
||||
-------------------------------------------
|
||||
|
||||
The Sharp 7395 driver can be found in windows/system32/driver
|
||||
The Sharp 7395 driver can be found in windows/system32/drivers
|
||||
|
||||
US2A0D.sys (dated 17 Mar 2009)
|
||||
|
||||
|
@ -44,7 +44,7 @@ and run
|
|||
|
||||
|
||||
Other LG firmware can be extracted manually from US280D.sys
|
||||
only found in windows/system32/driver.
|
||||
only found in windows/system32/drivers
|
||||
|
||||
dd if=US280D.sys ibs=1 skip=42360 count=3924 of=dvb-usb-lme2510-lg.fw
|
||||
|
||||
|
@ -55,4 +55,16 @@ dd if=US280D.sys ibs=1 skip=35200 count=3850 of=dvb-usb-lme2510c-lg.fw
|
|||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
The Sharp 0194 tuner driver can be found in windows/system32/drivers
|
||||
|
||||
US290D.sys (dated 09 Apr 2009)
|
||||
|
||||
For LME2510
|
||||
dd if=US290D.sys ibs=1 skip=36856 count=3976 of=dvb-usb-lme2510-s0194.fw
|
||||
|
||||
|
||||
For LME2510C
|
||||
dd if=US290D.sys ibs=1 skip=33152 count=3697 of=dvb-usb-lme2510c-s0194.fw
|
||||
|
||||
|
||||
Copy the firmware file(s) to /lib/firmware
|
||||
|
|
|
@ -108,42 +108,6 @@ Who: Pavel Machek <pavel@ucw.cz>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: Video4Linux obsolete drivers using V4L1 API
|
||||
When: kernel 2.6.39
|
||||
Files: drivers/staging/se401/* drivers/staging/usbvideo/*
|
||||
Check: drivers/staging/se401/se401.c drivers/staging/usbvideo/usbvideo.c
|
||||
Why: There are some drivers still using V4L1 API, despite all efforts we've done
|
||||
to migrate. Those drivers are for obsolete hardware that the old maintainer
|
||||
didn't care (or not have the hardware anymore), and that no other developer
|
||||
could find any hardware to buy. They probably have no practical usage today,
|
||||
and people with such old hardware could probably keep using an older version
|
||||
of the kernel. Those drivers will be moved to staging on 2.6.38 and, if nobody
|
||||
cares enough to port and test them with V4L2 API, they'll be removed on 2.6.39.
|
||||
Who: Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: Video4Linux: Remove obsolete ioctl's
|
||||
When: kernel 2.6.39
|
||||
Files: include/media/videodev2.h
|
||||
Why: Some ioctl's were defined wrong on 2.6.2 and 2.6.6, using the wrong
|
||||
type of R/W arguments. They were fixed, but the old ioctl names are
|
||||
still there, maintained to avoid breaking binary compatibility:
|
||||
#define VIDIOC_OVERLAY_OLD _IOWR('V', 14, int)
|
||||
#define VIDIOC_S_PARM_OLD _IOW('V', 22, struct v4l2_streamparm)
|
||||
#define VIDIOC_S_CTRL_OLD _IOW('V', 28, struct v4l2_control)
|
||||
#define VIDIOC_G_AUDIO_OLD _IOWR('V', 33, struct v4l2_audio)
|
||||
#define VIDIOC_G_AUDOUT_OLD _IOWR('V', 49, struct v4l2_audioout)
|
||||
#define VIDIOC_CROPCAP_OLD _IOR('V', 58, struct v4l2_cropcap)
|
||||
There's no sense on preserving those forever, as it is very doubtful
|
||||
that someone would try to use a such old binary with a modern kernel.
|
||||
Removing them will allow us to remove some magic done at the V4L ioctl
|
||||
handler.
|
||||
|
||||
Who: Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: sys_sysctl
|
||||
When: September 2010
|
||||
Option: CONFIG_SYSCTL_SYSCALL
|
||||
|
|
|
@ -273,6 +273,7 @@ Code Seq#(hex) Include File Comments
|
|||
'z' 40-7F CAN bus card conflict!
|
||||
<mailto:oe@port.de>
|
||||
'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict!
|
||||
'|' 00-7F linux/media.h
|
||||
0x80 00-1F linux/fb.h
|
||||
0x89 00-06 arch/x86/include/asm/sockios.h
|
||||
0x89 0B-DF linux/sockios.h
|
||||
|
|
|
@ -0,0 +1,353 @@
|
|||
Linux kernel media framework
|
||||
============================
|
||||
|
||||
This document describes the Linux kernel media framework, its data structures,
|
||||
functions and their usage.
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The media controller API is documented in DocBook format in
|
||||
Documentation/DocBook/v4l/media-controller.xml. This document will focus on
|
||||
the kernel-side implementation of the media framework.
|
||||
|
||||
|
||||
Abstract media device model
|
||||
---------------------------
|
||||
|
||||
Discovering a device internal topology, and configuring it at runtime, is one
|
||||
of the goals of the media framework. To achieve this, hardware devices are
|
||||
modeled as an oriented graph of building blocks called entities connected
|
||||
through pads.
|
||||
|
||||
An entity is a basic media hardware building block. It can correspond to
|
||||
a large variety of logical blocks such as physical hardware devices
|
||||
(CMOS sensor for instance), logical hardware devices (a building block
|
||||
in a System-on-Chip image processing pipeline), DMA channels or physical
|
||||
connectors.
|
||||
|
||||
A pad is a connection endpoint through which an entity can interact with
|
||||
other entities. Data (not restricted to video) produced by an entity
|
||||
flows from the entity's output to one or more entity inputs. Pads should
|
||||
not be confused with physical pins at chip boundaries.
|
||||
|
||||
A link is a point-to-point oriented connection between two pads, either
|
||||
on the same entity or on different entities. Data flows from a source
|
||||
pad to a sink pad.
|
||||
|
||||
|
||||
Media device
|
||||
------------
|
||||
|
||||
A media device is represented by a struct media_device instance, defined in
|
||||
include/media/media-device.h. Allocation of the structure is handled by the
|
||||
media device driver, usually by embedding the media_device instance in a
|
||||
larger driver-specific structure.
|
||||
|
||||
Drivers register media device instances by calling
|
||||
|
||||
media_device_register(struct media_device *mdev);
|
||||
|
||||
The caller is responsible for initializing the media_device structure before
|
||||
registration. The following fields must be set:
|
||||
|
||||
- dev must point to the parent device (usually a pci_dev, usb_interface or
|
||||
platform_device instance).
|
||||
|
||||
- model must be filled with the device model name as a NUL-terminated UTF-8
|
||||
string. The device/model revision must not be stored in this field.
|
||||
|
||||
The following fields are optional:
|
||||
|
||||
- serial is a unique serial number stored as a NUL-terminated ASCII string.
|
||||
The field is big enough to store a GUID in text form. If the hardware
|
||||
doesn't provide a unique serial number this field must be left empty.
|
||||
|
||||
- bus_info represents the location of the device in the system as a
|
||||
NUL-terminated ASCII string. For PCI/PCIe devices bus_info must be set to
|
||||
"PCI:" (or "PCIe:") followed by the value of pci_name(). For USB devices,
|
||||
the usb_make_path() function must be used. This field is used by
|
||||
applications to distinguish between otherwise identical devices that don't
|
||||
provide a serial number.
|
||||
|
||||
- hw_revision is the hardware device revision in a driver-specific format.
|
||||
When possible the revision should be formatted with the KERNEL_VERSION
|
||||
macro.
|
||||
|
||||
- driver_version is formatted with the KERNEL_VERSION macro. The version
|
||||
minor must be incremented when new features are added to the userspace API
|
||||
without breaking binary compatibility. The version major must be
|
||||
incremented when binary compatibility is broken.
|
||||
|
||||
Upon successful registration a character device named media[0-9]+ is created.
|
||||
The device major and minor numbers are dynamic. The model name is exported as
|
||||
a sysfs attribute.
|
||||
|
||||
Drivers unregister media device instances by calling
|
||||
|
||||
media_device_unregister(struct media_device *mdev);
|
||||
|
||||
Unregistering a media device that hasn't been registered is *NOT* safe.
|
||||
|
||||
|
||||
Entities, pads and links
|
||||
------------------------
|
||||
|
||||
- Entities
|
||||
|
||||
Entities are represented by a struct media_entity instance, defined in
|
||||
include/media/media-entity.h. The structure is usually embedded into a
|
||||
higher-level structure, such as a v4l2_subdev or video_device instance,
|
||||
although drivers can allocate entities directly.
|
||||
|
||||
Drivers initialize entities by calling
|
||||
|
||||
media_entity_init(struct media_entity *entity, u16 num_pads,
|
||||
struct media_pad *pads, u16 extra_links);
|
||||
|
||||
The media_entity name, type, flags, revision and group_id fields can be
|
||||
initialized before or after calling media_entity_init. Entities embedded in
|
||||
higher-level standard structures can have some of those fields set by the
|
||||
higher-level framework.
|
||||
|
||||
As the number of pads is known in advance, the pads array is not allocated
|
||||
dynamically but is managed by the entity driver. Most drivers will embed the
|
||||
pads array in a driver-specific structure, avoiding dynamic allocation.
|
||||
|
||||
Drivers must set the direction of every pad in the pads array before calling
|
||||
media_entity_init. The function will initialize the other pads fields.
|
||||
|
||||
Unlike the number of pads, the total number of links isn't always known in
|
||||
advance by the entity driver. As an initial estimate, media_entity_init
|
||||
pre-allocates a number of links equal to the number of pads plus an optional
|
||||
number of extra links. The links array will be reallocated if it grows beyond
|
||||
the initial estimate.
|
||||
|
||||
Drivers register entities with a media device by calling
|
||||
|
||||
media_device_register_entity(struct media_device *mdev,
|
||||
struct media_entity *entity);
|
||||
|
||||
Entities are identified by a unique positive integer ID. Drivers can provide an
|
||||
ID by filling the media_entity id field prior to registration, or request the
|
||||
media controller framework to assign an ID automatically. Drivers that provide
|
||||
IDs manually must ensure that all IDs are unique. IDs are not guaranteed to be
|
||||
contiguous even when they are all assigned automatically by the framework.
|
||||
|
||||
Drivers unregister entities by calling
|
||||
|
||||
media_device_unregister_entity(struct media_entity *entity);
|
||||
|
||||
Unregistering an entity will not change the IDs of the other entities, and the
|
||||
ID will never be reused for a newly registered entity.
|
||||
|
||||
When a media device is unregistered, all its entities are unregistered
|
||||
automatically. No manual entities unregistration is then required.
|
||||
|
||||
Drivers free resources associated with an entity by calling
|
||||
|
||||
media_entity_cleanup(struct media_entity *entity);
|
||||
|
||||
This function must be called during the cleanup phase after unregistering the
|
||||
entity. Note that the media_entity instance itself must be freed explicitly by
|
||||
the driver if required.
|
||||
|
||||
Entities have flags that describe the entity capabilities and state.
|
||||
|
||||
MEDIA_ENT_FL_DEFAULT indicates the default entity for a given type.
|
||||
This can be used to report the default audio and video devices or the
|
||||
default camera sensor.
|
||||
|
||||
Logical entity groups can be defined by setting the group ID of all member
|
||||
entities to the same non-zero value. An entity group serves no purpose in the
|
||||
kernel, but is reported to userspace during entities enumeration. The group_id
|
||||
field belongs to the media device driver and must not by touched by entity
|
||||
drivers.
|
||||
|
||||
Media device drivers should define groups if several entities are logically
|
||||
bound together. Example usages include reporting
|
||||
|
||||
- ALSA, VBI and video nodes that carry the same media stream
|
||||
- lens and flash controllers associated with a sensor
|
||||
|
||||
- Pads
|
||||
|
||||
Pads are represented by a struct media_pad instance, defined in
|
||||
include/media/media-entity.h. Each entity stores its pads in a pads array
|
||||
managed by the entity driver. Drivers usually embed the array in a
|
||||
driver-specific structure.
|
||||
|
||||
Pads are identified by their entity and their 0-based index in the pads array.
|
||||
Both information are stored in the media_pad structure, making the media_pad
|
||||
pointer the canonical way to store and pass link references.
|
||||
|
||||
Pads have flags that describe the pad capabilities and state.
|
||||
|
||||
MEDIA_PAD_FL_SINK indicates that the pad supports sinking data.
|
||||
MEDIA_PAD_FL_SOURCE indicates that the pad supports sourcing data.
|
||||
|
||||
One and only one of MEDIA_PAD_FL_SINK and MEDIA_PAD_FL_SOURCE must be set for
|
||||
each pad.
|
||||
|
||||
- Links
|
||||
|
||||
Links are represented by a struct media_link instance, defined in
|
||||
include/media/media-entity.h. Each entity stores all links originating at or
|
||||
targetting any of its pads in a links array. A given link is thus stored
|
||||
twice, once in the source entity and once in the target entity. The array is
|
||||
pre-allocated and grows dynamically as needed.
|
||||
|
||||
Drivers create links by calling
|
||||
|
||||
media_entity_create_link(struct media_entity *source, u16 source_pad,
|
||||
struct media_entity *sink, u16 sink_pad,
|
||||
u32 flags);
|
||||
|
||||
An entry in the link array of each entity is allocated and stores pointers
|
||||
to source and sink pads.
|
||||
|
||||
Links have flags that describe the link capabilities and state.
|
||||
|
||||
MEDIA_LNK_FL_ENABLED indicates that the link is enabled and can be used
|
||||
to transfer media data. When two or more links target a sink pad, only
|
||||
one of them can be enabled at a time.
|
||||
MEDIA_LNK_FL_IMMUTABLE indicates that the link enabled state can't be
|
||||
modified at runtime. If MEDIA_LNK_FL_IMMUTABLE is set, then
|
||||
MEDIA_LNK_FL_ENABLED must also be set since an immutable link is always
|
||||
enabled.
|
||||
|
||||
|
||||
Graph traversal
|
||||
---------------
|
||||
|
||||
The media framework provides APIs to iterate over entities in a graph.
|
||||
|
||||
To iterate over all entities belonging to a media device, drivers can use the
|
||||
media_device_for_each_entity macro, defined in include/media/media-device.h.
|
||||
|
||||
struct media_entity *entity;
|
||||
|
||||
media_device_for_each_entity(entity, mdev) {
|
||||
/* entity will point to each entity in turn */
|
||||
...
|
||||
}
|
||||
|
||||
Drivers might also need to iterate over all entities in a graph that can be
|
||||
reached only through enabled links starting at a given entity. The media
|
||||
framework provides a depth-first graph traversal API for that purpose.
|
||||
|
||||
Note that graphs with cycles (whether directed or undirected) are *NOT*
|
||||
supported by the graph traversal API. To prevent infinite loops, the graph
|
||||
traversal code limits the maximum depth to MEDIA_ENTITY_ENUM_MAX_DEPTH,
|
||||
currently defined as 16.
|
||||
|
||||
Drivers initiate a graph traversal by calling
|
||||
|
||||
media_entity_graph_walk_start(struct media_entity_graph *graph,
|
||||
struct media_entity *entity);
|
||||
|
||||
The graph structure, provided by the caller, is initialized to start graph
|
||||
traversal at the given entity.
|
||||
|
||||
Drivers can then retrieve the next entity by calling
|
||||
|
||||
media_entity_graph_walk_next(struct media_entity_graph *graph);
|
||||
|
||||
When the graph traversal is complete the function will return NULL.
|
||||
|
||||
Graph traversal can be interrupted at any moment. No cleanup function call is
|
||||
required and the graph structure can be freed normally.
|
||||
|
||||
Helper functions can be used to find a link between two given pads, or a pad
|
||||
connected to another pad through an enabled link
|
||||
|
||||
media_entity_find_link(struct media_pad *source,
|
||||
struct media_pad *sink);
|
||||
|
||||
media_entity_remote_source(struct media_pad *pad);
|
||||
|
||||
Refer to the kerneldoc documentation for more information.
|
||||
|
||||
|
||||
Use count and power handling
|
||||
----------------------------
|
||||
|
||||
Due to the wide differences between drivers regarding power management needs,
|
||||
the media controller does not implement power management. However, the
|
||||
media_entity structure includes a use_count field that media drivers can use to
|
||||
track the number of users of every entity for power management needs.
|
||||
|
||||
The use_count field is owned by media drivers and must not be touched by entity
|
||||
drivers. Access to the field must be protected by the media device graph_mutex
|
||||
lock.
|
||||
|
||||
|
||||
Links setup
|
||||
-----------
|
||||
|
||||
Link properties can be modified at runtime by calling
|
||||
|
||||
media_entity_setup_link(struct media_link *link, u32 flags);
|
||||
|
||||
The flags argument contains the requested new link flags.
|
||||
|
||||
The only configurable property is the ENABLED link flag to enable/disable a
|
||||
link. Links marked with the IMMUTABLE link flag can not be enabled or disabled.
|
||||
|
||||
When a link is enabled or disabled, the media framework calls the
|
||||
link_setup operation for the two entities at the source and sink of the link,
|
||||
in that order. If the second link_setup call fails, another link_setup call is
|
||||
made on the first entity to restore the original link flags.
|
||||
|
||||
Media device drivers can be notified of link setup operations by setting the
|
||||
media_device::link_notify pointer to a callback function. If provided, the
|
||||
notification callback will be called before enabling and after disabling
|
||||
links.
|
||||
|
||||
Entity drivers must implement the link_setup operation if any of their links
|
||||
is non-immutable. The operation must either configure the hardware or store
|
||||
the configuration information to be applied later.
|
||||
|
||||
Link configuration must not have any side effect on other links. If an enabled
|
||||
link at a sink pad prevents another link at the same pad from being disabled,
|
||||
the link_setup operation must return -EBUSY and can't implicitly disable the
|
||||
first enabled link.
|
||||
|
||||
|
||||
Pipelines and media streams
|
||||
---------------------------
|
||||
|
||||
When starting streaming, drivers must notify all entities in the pipeline to
|
||||
prevent link states from being modified during streaming by calling
|
||||
|
||||
media_entity_pipeline_start(struct media_entity *entity,
|
||||
struct media_pipeline *pipe);
|
||||
|
||||
The function will mark all entities connected to the given entity through
|
||||
enabled links, either directly or indirectly, as streaming.
|
||||
|
||||
The media_pipeline instance pointed to by the pipe argument will be stored in
|
||||
every entity in the pipeline. Drivers should embed the media_pipeline structure
|
||||
in higher-level pipeline structures and can then access the pipeline through
|
||||
the media_entity pipe field.
|
||||
|
||||
Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must
|
||||
be identical for all nested calls to the function.
|
||||
|
||||
When stopping the stream, drivers must notify the entities with
|
||||
|
||||
media_entity_pipeline_stop(struct media_entity *entity);
|
||||
|
||||
If multiple calls to media_entity_pipeline_start() have been made the same
|
||||
number of media_entity_pipeline_stop() calls are required to stop streaming. The
|
||||
media_entity pipe field is reset to NULL on the last nested stop call.
|
||||
|
||||
Link configuration will fail with -EBUSY by default if either end of the link is
|
||||
a streaming entity. Links that can be modified while streaming must be marked
|
||||
with the MEDIA_LNK_FL_DYNAMIC flag.
|
||||
|
||||
If other operations need to be disallowed on streaming entities (such as
|
||||
changing entities configuration parameters) drivers can explictly check the
|
||||
media_entity stream_count field to find out if an entity is streaming. This
|
||||
operation must be done with the media_device graph_mutex held.
|
|
@ -36,8 +36,7 @@ Additional features for the PVR-350 (CX23415 based):
|
|||
* Provides comprehensive OSD (On Screen Display: ie. graphics overlaying the
|
||||
video signal)
|
||||
* Provides a framebuffer (allowing X applications to appear on the video
|
||||
device) (this framebuffer is not yet part of the kernel. In the meantime it
|
||||
is available from www.ivtvdriver.org).
|
||||
device)
|
||||
* Supports raw YUV output.
|
||||
|
||||
IMPORTANT: In case of problems first read this page:
|
||||
|
|
|
@ -103,6 +103,7 @@ spca561 046d:092d Logitech QC Elch2
|
|||
spca561 046d:092e Logitech QC Elch2
|
||||
spca561 046d:092f Logitech QuickCam Express Plus
|
||||
sunplus 046d:0960 Logitech ClickSmart 420
|
||||
nw80x 046d:d001 Logitech QuickCam Pro (dark focus ring)
|
||||
sunplus 0471:0322 Philips DMVC1300K
|
||||
zc3xx 0471:0325 Philips SPC 200 NC
|
||||
zc3xx 0471:0326 Philips SPC 300 NC
|
||||
|
@ -150,10 +151,12 @@ sunplus 04fc:5330 Digitrex 2110
|
|||
sunplus 04fc:5360 Sunplus Generic
|
||||
spca500 04fc:7333 PalmPixDC85
|
||||
sunplus 04fc:ffff Pure DigitalDakota
|
||||
nw80x 0502:d001 DVC V6
|
||||
spca501 0506:00df 3Com HomeConnect Lite
|
||||
sunplus 052b:1507 Megapixel 5 Pretec DC-1007
|
||||
sunplus 052b:1513 Megapix V4
|
||||
sunplus 052b:1803 MegaImage VI
|
||||
nw80x 052b:d001 EZCam Pro p35u
|
||||
tv8532 0545:808b Veo Stingray
|
||||
tv8532 0545:8333 Veo Stingray
|
||||
sunplus 0546:3155 Polaroid PDC3070
|
||||
|
@ -177,6 +180,7 @@ sunplus 055f:c530 Mustek Gsmart LCD 3
|
|||
sunplus 055f:c540 Gsmart D30
|
||||
sunplus 055f:c630 Mustek MDC4000
|
||||
sunplus 055f:c650 Mustek MDC5500Z
|
||||
nw80x 055f:d001 Mustek Wcam 300 mini
|
||||
zc3xx 055f:d003 Mustek WCam300A
|
||||
zc3xx 055f:d004 Mustek WCam300 AN
|
||||
conex 0572:0041 Creative Notebook cx11646
|
||||
|
@ -195,14 +199,20 @@ gl860 05e3:0503 Genesys Logic PC Camera
|
|||
gl860 05e3:f191 Genesys Logic PC Camera
|
||||
spca561 060b:a001 Maxell Compact Pc PM3
|
||||
zc3xx 0698:2003 CTX M730V built in
|
||||
nw80x 06a5:0000 Typhoon Webcam 100 USB
|
||||
nw80x 06a5:d001 Divio based webcams
|
||||
nw80x 06a5:d800 Divio Chicony TwinkleCam, Trust SpaceCam
|
||||
spca500 06bd:0404 Agfa CL20
|
||||
spca500 06be:0800 Optimedia
|
||||
nw80x 06be:d001 EZCam Pro p35u
|
||||
sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom
|
||||
spca506 06e1:a190 ADS Instant VCD
|
||||
ov534 06f8:3002 Hercules Blog Webcam
|
||||
ov534_9 06f8:3003 Hercules Dualpix HD Weblog
|
||||
sonixj 06f8:3004 Hercules Classic Silver
|
||||
sonixj 06f8:3008 Hercules Deluxe Optical Glass
|
||||
pac7302 06f8:3009 Hercules Classic Link
|
||||
nw80x 0728:d001 AVerMedia Camguard
|
||||
spca508 0733:0110 ViewQuest VQ110
|
||||
spca501 0733:0401 Intel Create and Share
|
||||
spca501 0733:0402 ViewQuest M318B
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
OMAP 3 Image Signal Processor (ISP) driver
|
||||
|
||||
Copyright (C) 2010 Nokia Corporation
|
||||
Copyright (C) 2009 Texas Instruments, Inc.
|
||||
|
||||
Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Sakari Ailus <sakari.ailus@iki.fi>
|
||||
David Cohen <dacohen@gmail.com>
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This file documents the Texas Instruments OMAP 3 Image Signal Processor (ISP)
|
||||
driver located under drivers/media/video/omap3isp. The original driver was
|
||||
written by Texas Instruments but since that it has been rewritten (twice) at
|
||||
Nokia.
|
||||
|
||||
The driver has been successfully used on the following versions of OMAP 3:
|
||||
|
||||
3430
|
||||
3530
|
||||
3630
|
||||
|
||||
The driver implements V4L2, Media controller and v4l2_subdev interfaces.
|
||||
Sensor, lens and flash drivers using the v4l2_subdev interface in the kernel
|
||||
are supported.
|
||||
|
||||
|
||||
Split to subdevs
|
||||
================
|
||||
|
||||
The OMAP 3 ISP is split into V4L2 subdevs, each of the blocks inside the ISP
|
||||
having one subdev to represent it. Each of the subdevs provide a V4L2 subdev
|
||||
interface to userspace.
|
||||
|
||||
OMAP3 ISP CCP2
|
||||
OMAP3 ISP CSI2a
|
||||
OMAP3 ISP CCDC
|
||||
OMAP3 ISP preview
|
||||
OMAP3 ISP resizer
|
||||
OMAP3 ISP AEWB
|
||||
OMAP3 ISP AF
|
||||
OMAP3 ISP histogram
|
||||
|
||||
Each possible link in the ISP is modelled by a link in the Media controller
|
||||
interface. For an example program see [2].
|
||||
|
||||
|
||||
Controlling the OMAP 3 ISP
|
||||
==========================
|
||||
|
||||
In general, the settings given to the OMAP 3 ISP take effect at the beginning
|
||||
of the following frame. This is done when the module becomes idle during the
|
||||
vertical blanking period on the sensor. In memory-to-memory operation the pipe
|
||||
is run one frame at a time. Applying the settings is done between the frames.
|
||||
|
||||
All the blocks in the ISP, excluding the CSI-2 and possibly the CCP2 receiver,
|
||||
insist on receiving complete frames. Sensors must thus never send the ISP
|
||||
partial frames.
|
||||
|
||||
Autoidle does have issues with some ISP blocks on the 3430, at least.
|
||||
Autoidle is only enabled on 3630 when the omap3isp module parameter autoidle
|
||||
is non-zero.
|
||||
|
||||
|
||||
Events
|
||||
======
|
||||
|
||||
The OMAP 3 ISP driver does support the V4L2 event interface on CCDC and
|
||||
statistics (AEWB, AF and histogram) subdevs.
|
||||
|
||||
The CCDC subdev produces V4L2_EVENT_OMAP3ISP_HS_VS type event on HS_VS
|
||||
interrupt which is used to signal frame start. The event is triggered exactly
|
||||
when the reception of the first line of the frame starts in the CCDC module.
|
||||
The event can be subscribed on the CCDC subdev.
|
||||
|
||||
(When using parallel interface one must pay account to correct configuration
|
||||
of the VS signal polarity. This is automatically correct when using the serial
|
||||
receivers.)
|
||||
|
||||
Each of the statistics subdevs is able to produce events. An event is
|
||||
generated whenever a statistics buffer can be dequeued by a user space
|
||||
application using the VIDIOC_OMAP3ISP_STAT_REQ IOCTL. The events available
|
||||
are:
|
||||
|
||||
V4L2_EVENT_OMAP3ISP_AEWB
|
||||
V4L2_EVENT_OMAP3ISP_AF
|
||||
V4L2_EVENT_OMAP3ISP_HIST
|
||||
|
||||
The type of the event data is struct omap3isp_stat_event_status for these
|
||||
ioctls. If there is an error calculating the statistics, there will be an
|
||||
event as usual, but no related statistics buffer. In this case
|
||||
omap3isp_stat_event_status.buf_err is set to non-zero.
|
||||
|
||||
|
||||
Private IOCTLs
|
||||
==============
|
||||
|
||||
The OMAP 3 ISP driver supports standard V4L2 IOCTLs and controls where
|
||||
possible and practical. Much of the functions provided by the ISP, however,
|
||||
does not fall under the standard IOCTLs --- gamma tables and configuration of
|
||||
statistics collection are examples of such.
|
||||
|
||||
In general, there is a private ioctl for configuring each of the blocks
|
||||
containing hardware-dependent functions.
|
||||
|
||||
The following private IOCTLs are supported:
|
||||
|
||||
VIDIOC_OMAP3ISP_CCDC_CFG
|
||||
VIDIOC_OMAP3ISP_PRV_CFG
|
||||
VIDIOC_OMAP3ISP_AEWB_CFG
|
||||
VIDIOC_OMAP3ISP_HIST_CFG
|
||||
VIDIOC_OMAP3ISP_AF_CFG
|
||||
VIDIOC_OMAP3ISP_STAT_REQ
|
||||
VIDIOC_OMAP3ISP_STAT_EN
|
||||
|
||||
The parameter structures used by these ioctls are described in
|
||||
include/linux/omap3isp.h. The detailed functions of the ISP itself related to
|
||||
a given ISP block is described in the Technical Reference Manuals (TRMs) ---
|
||||
see the end of the document for those.
|
||||
|
||||
While it is possible to use the ISP driver without any use of these private
|
||||
IOCTLs it is not possible to obtain optimal image quality this way. The AEWB,
|
||||
AF and histogram modules cannot be used without configuring them using the
|
||||
appropriate private IOCTLs.
|
||||
|
||||
|
||||
CCDC and preview block IOCTLs
|
||||
=============================
|
||||
|
||||
The VIDIOC_OMAP3ISP_CCDC_CFG and VIDIOC_OMAP3ISP_PRV_CFG IOCTLs are used to
|
||||
configure, enable and disable functions in the CCDC and preview blocks,
|
||||
respectively. Both IOCTLs control several functions in the blocks they
|
||||
control. VIDIOC_OMAP3ISP_CCDC_CFG IOCTL accepts a pointer to struct
|
||||
omap3isp_ccdc_update_config as its argument. Similarly VIDIOC_OMAP3ISP_PRV_CFG
|
||||
accepts a pointer to struct omap3isp_prev_update_config. The definition of
|
||||
both structures is available in [1].
|
||||
|
||||
The update field in the structures tells whether to update the configuration
|
||||
for the specific function and the flag tells whether to enable or disable the
|
||||
function.
|
||||
|
||||
The update and flag bit masks accept the following values. Each separate
|
||||
functions in the CCDC and preview blocks is associated with a flag (either
|
||||
disable or enable; part of the flag field in the structure) and a pointer to
|
||||
configuration data for the function.
|
||||
|
||||
Valid values for the update and flag fields are listed here for
|
||||
VIDIOC_OMAP3ISP_CCDC_CFG. Values may be or'ed to configure more than one
|
||||
function in the same IOCTL call.
|
||||
|
||||
OMAP3ISP_CCDC_ALAW
|
||||
OMAP3ISP_CCDC_LPF
|
||||
OMAP3ISP_CCDC_BLCLAMP
|
||||
OMAP3ISP_CCDC_BCOMP
|
||||
OMAP3ISP_CCDC_FPC
|
||||
OMAP3ISP_CCDC_CULL
|
||||
OMAP3ISP_CCDC_CONFIG_LSC
|
||||
OMAP3ISP_CCDC_TBL_LSC
|
||||
|
||||
The corresponding values for the VIDIOC_OMAP3ISP_PRV_CFG are here:
|
||||
|
||||
OMAP3ISP_PREV_LUMAENH
|
||||
OMAP3ISP_PREV_INVALAW
|
||||
OMAP3ISP_PREV_HRZ_MED
|
||||
OMAP3ISP_PREV_CFA
|
||||
OMAP3ISP_PREV_CHROMA_SUPP
|
||||
OMAP3ISP_PREV_WB
|
||||
OMAP3ISP_PREV_BLKADJ
|
||||
OMAP3ISP_PREV_RGB2RGB
|
||||
OMAP3ISP_PREV_COLOR_CONV
|
||||
OMAP3ISP_PREV_YC_LIMIT
|
||||
OMAP3ISP_PREV_DEFECT_COR
|
||||
OMAP3ISP_PREV_GAMMABYPASS
|
||||
OMAP3ISP_PREV_DRK_FRM_CAPTURE
|
||||
OMAP3ISP_PREV_DRK_FRM_SUBTRACT
|
||||
OMAP3ISP_PREV_LENS_SHADING
|
||||
OMAP3ISP_PREV_NF
|
||||
OMAP3ISP_PREV_GAMMA
|
||||
|
||||
The associated configuration pointer for the function may not be NULL when
|
||||
enabling the function. When disabling a function the configuration pointer is
|
||||
ignored.
|
||||
|
||||
|
||||
Statistic blocks IOCTLs
|
||||
=======================
|
||||
|
||||
The statistics subdevs do offer more dynamic configuration options than the
|
||||
other subdevs. They can be enabled, disable and reconfigured when the pipeline
|
||||
is in streaming state.
|
||||
|
||||
The statistics blocks always get the input image data from the CCDC (as the
|
||||
histogram memory read isn't implemented). The statistics are dequeueable by
|
||||
the user from the statistics subdev nodes using private IOCTLs.
|
||||
|
||||
The private IOCTLs offered by the AEWB, AF and histogram subdevs are heavily
|
||||
reflected by the register level interface offered by the ISP hardware. There
|
||||
are aspects that are purely related to the driver implementation and these are
|
||||
discussed next.
|
||||
|
||||
VIDIOC_OMAP3ISP_STAT_EN
|
||||
-----------------------
|
||||
|
||||
This private IOCTL enables/disables a statistic module. If this request is
|
||||
done before streaming, it will take effect as soon as the pipeline starts to
|
||||
stream. If the pipeline is already streaming, it will take effect as soon as
|
||||
the CCDC becomes idle.
|
||||
|
||||
VIDIOC_OMAP3ISP_AEWB_CFG, VIDIOC_OMAP3ISP_HIST_CFG and VIDIOC_OMAP3ISP_AF_CFG
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Those IOCTLs are used to configure the modules. They require user applications
|
||||
to have an in-depth knowledge of the hardware. Most of the fields explanation
|
||||
can be found on OMAP's TRMs. The two following fields common to all the above
|
||||
configure private IOCTLs require explanation for better understanding as they
|
||||
are not part of the TRM.
|
||||
|
||||
omap3isp_[h3a_af/h3a_aewb/hist]_config.buf_size:
|
||||
|
||||
The modules handle their buffers internally. The necessary buffer size for the
|
||||
module's data output depends on the requested configuration. Although the
|
||||
driver supports reconfiguration while streaming, it does not support a
|
||||
reconfiguration which requires bigger buffer size than what is already
|
||||
internally allocated if the module is enabled. It will return -EBUSY on this
|
||||
case. In order to avoid such condition, either disable/reconfigure/enable the
|
||||
module or request the necessary buffer size during the first configuration
|
||||
while the module is disabled.
|
||||
|
||||
The internal buffer size allocation considers the requested configuration's
|
||||
minimum buffer size and the value set on buf_size field. If buf_size field is
|
||||
out of [minimum, maximum] buffer size range, it's clamped to fit in there.
|
||||
The driver then selects the biggest value. The corrected buf_size value is
|
||||
written back to user application.
|
||||
|
||||
omap3isp_[h3a_af/h3a_aewb/hist]_config.config_counter:
|
||||
|
||||
As the configuration doesn't take effect synchronously to the request, the
|
||||
driver must provide a way to track this information to provide more accurate
|
||||
data. After a configuration is requested, the config_counter returned to user
|
||||
space application will be an unique value associated to that request. When
|
||||
user application receives an event for buffer availability or when a new
|
||||
buffer is requested, this config_counter is used to match a buffer data and a
|
||||
configuration.
|
||||
|
||||
VIDIOC_OMAP3ISP_STAT_REQ
|
||||
------------------------
|
||||
|
||||
Send to user space the oldest data available in the internal buffer queue and
|
||||
discards such buffer afterwards. The field omap3isp_stat_data.frame_number
|
||||
matches with the video buffer's field_count.
|
||||
|
||||
|
||||
Technical reference manuals (TRMs) and other documentation
|
||||
==========================================================
|
||||
|
||||
OMAP 3430 TRM:
|
||||
<URL:http://focus.ti.com/pdfs/wtbu/OMAP34xx_ES3.1.x_PUBLIC_TRM_vZM.zip>
|
||||
Referenced 2011-03-05.
|
||||
|
||||
OMAP 35xx TRM:
|
||||
<URL:http://www.ti.com/litv/pdf/spruf98o> Referenced 2011-03-05.
|
||||
|
||||
OMAP 3630 TRM:
|
||||
<URL:http://focus.ti.com/pdfs/wtbu/OMAP36xx_ES1.x_PUBLIC_TRM_vQ.zip>
|
||||
Referenced 2011-03-05.
|
||||
|
||||
DM 3730 TRM:
|
||||
<URL:http://www.ti.com/litv/pdf/sprugn4h> Referenced 2011-03-06.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
[1] include/linux/omap3isp.h
|
||||
|
||||
[2] http://git.ideasonboard.org/?p=media-ctl.git;a=summary
|
|
@ -71,6 +71,10 @@ sub-device instances, the video_device struct stores V4L2 device node data
|
|||
and in the future a v4l2_fh struct will keep track of filehandle instances
|
||||
(this is not yet implemented).
|
||||
|
||||
The V4L2 framework also optionally integrates with the media framework. If a
|
||||
driver sets the struct v4l2_device mdev field, sub-devices and video nodes
|
||||
will automatically appear in the media framework as entities.
|
||||
|
||||
|
||||
struct v4l2_device
|
||||
------------------
|
||||
|
@ -83,11 +87,20 @@ You must register the device instance:
|
|||
|
||||
v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
|
||||
|
||||
Registration will initialize the v4l2_device struct and link dev->driver_data
|
||||
to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived
|
||||
from dev (driver name followed by the bus_id, to be precise). If you set it
|
||||
up before calling v4l2_device_register then it will be untouched. If dev is
|
||||
NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register.
|
||||
Registration will initialize the v4l2_device struct. If the dev->driver_data
|
||||
field is NULL, it will be linked to v4l2_dev.
|
||||
|
||||
Drivers that want integration with the media device framework need to set
|
||||
dev->driver_data manually to point to the driver-specific device structure
|
||||
that embed the struct v4l2_device instance. This is achieved by a
|
||||
dev_set_drvdata() call before registering the V4L2 device instance. They must
|
||||
also set the struct v4l2_device mdev field to point to a properly initialized
|
||||
and registered media_device instance.
|
||||
|
||||
If v4l2_dev->name is empty then it will be set to a value derived from dev
|
||||
(driver name followed by the bus_id, to be precise). If you set it up before
|
||||
calling v4l2_device_register then it will be untouched. If dev is NULL, then
|
||||
you *must* setup v4l2_dev->name before calling v4l2_device_register.
|
||||
|
||||
You can use v4l2_device_set_name() to set the name based on a driver name and
|
||||
a driver-global atomic_t instance. This will generate names like ivtv0, ivtv1,
|
||||
|
@ -108,6 +121,7 @@ You unregister with:
|
|||
|
||||
v4l2_device_unregister(struct v4l2_device *v4l2_dev);
|
||||
|
||||
If the dev->driver_data field points to v4l2_dev, it will be reset to NULL.
|
||||
Unregistering will also automatically unregister all subdevs from the device.
|
||||
|
||||
If you have a hotpluggable device (e.g. a USB device), then when a disconnect
|
||||
|
@ -167,6 +181,21 @@ static int __devinit drv_probe(struct pci_dev *pdev,
|
|||
state->instance = atomic_inc_return(&drv_instance) - 1;
|
||||
}
|
||||
|
||||
If you have multiple device nodes then it can be difficult to know when it is
|
||||
safe to unregister v4l2_device. For this purpose v4l2_device has refcounting
|
||||
support. The refcount is increased whenever video_register_device is called and
|
||||
it is decreased whenever that device node is released. When the refcount reaches
|
||||
zero, then the v4l2_device release() callback is called. You can do your final
|
||||
cleanup there.
|
||||
|
||||
If other device nodes (e.g. ALSA) are created, then you can increase and
|
||||
decrease the refcount manually as well by calling:
|
||||
|
||||
void v4l2_device_get(struct v4l2_device *v4l2_dev);
|
||||
|
||||
or:
|
||||
|
||||
int v4l2_device_put(struct v4l2_device *v4l2_dev);
|
||||
|
||||
struct v4l2_subdev
|
||||
------------------
|
||||
|
@ -254,6 +283,26 @@ A sub-device driver initializes the v4l2_subdev struct using:
|
|||
Afterwards you need to initialize subdev->name with a unique name and set the
|
||||
module owner. This is done for you if you use the i2c helper functions.
|
||||
|
||||
If integration with the media framework is needed, you must initialize the
|
||||
media_entity struct embedded in the v4l2_subdev struct (entity field) by
|
||||
calling media_entity_init():
|
||||
|
||||
struct media_pad *pads = &my_sd->pads;
|
||||
int err;
|
||||
|
||||
err = media_entity_init(&sd->entity, npads, pads, 0);
|
||||
|
||||
The pads array must have been previously initialized. There is no need to
|
||||
manually set the struct media_entity type and name fields, but the revision
|
||||
field must be initialized if needed.
|
||||
|
||||
A reference to the entity will be automatically acquired/released when the
|
||||
subdev device node (if any) is opened/closed.
|
||||
|
||||
Don't forget to cleanup the media entity before the sub-device is destroyed:
|
||||
|
||||
media_entity_cleanup(&sd->entity);
|
||||
|
||||
A device (bridge) driver needs to register the v4l2_subdev with the
|
||||
v4l2_device:
|
||||
|
||||
|
@ -263,6 +312,9 @@ This can fail if the subdev module disappeared before it could be registered.
|
|||
After this function was called successfully the subdev->dev field points to
|
||||
the v4l2_device.
|
||||
|
||||
If the v4l2_device parent device has a non-NULL mdev field, the sub-device
|
||||
entity will be automatically registered with the media device.
|
||||
|
||||
You can unregister a sub-device using:
|
||||
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
|
@ -319,6 +371,61 @@ controlled through GPIO pins. This distinction is only relevant when setting
|
|||
up the device, but once the subdev is registered it is completely transparent.
|
||||
|
||||
|
||||
V4L2 sub-device userspace API
|
||||
-----------------------------
|
||||
|
||||
Beside exposing a kernel API through the v4l2_subdev_ops structure, V4L2
|
||||
sub-devices can also be controlled directly by userspace applications.
|
||||
|
||||
Device nodes named v4l-subdevX can be created in /dev to access sub-devices
|
||||
directly. If a sub-device supports direct userspace configuration it must set
|
||||
the V4L2_SUBDEV_FL_HAS_DEVNODE flag before being registered.
|
||||
|
||||
After registering sub-devices, the v4l2_device driver can create device nodes
|
||||
for all registered sub-devices marked with V4L2_SUBDEV_FL_HAS_DEVNODE by calling
|
||||
v4l2_device_register_subdev_nodes(). Those device nodes will be automatically
|
||||
removed when sub-devices are unregistered.
|
||||
|
||||
The device node handles a subset of the V4L2 API.
|
||||
|
||||
VIDIOC_QUERYCTRL
|
||||
VIDIOC_QUERYMENU
|
||||
VIDIOC_G_CTRL
|
||||
VIDIOC_S_CTRL
|
||||
VIDIOC_G_EXT_CTRLS
|
||||
VIDIOC_S_EXT_CTRLS
|
||||
VIDIOC_TRY_EXT_CTRLS
|
||||
|
||||
The controls ioctls are identical to the ones defined in V4L2. They
|
||||
behave identically, with the only exception that they deal only with
|
||||
controls implemented in the sub-device. Depending on the driver, those
|
||||
controls can be also be accessed through one (or several) V4L2 device
|
||||
nodes.
|
||||
|
||||
VIDIOC_DQEVENT
|
||||
VIDIOC_SUBSCRIBE_EVENT
|
||||
VIDIOC_UNSUBSCRIBE_EVENT
|
||||
|
||||
The events ioctls are identical to the ones defined in V4L2. They
|
||||
behave identically, with the only exception that they deal only with
|
||||
events generated by the sub-device. Depending on the driver, those
|
||||
events can also be reported by one (or several) V4L2 device nodes.
|
||||
|
||||
Sub-device drivers that want to use events need to set the
|
||||
V4L2_SUBDEV_USES_EVENTS v4l2_subdev::flags and initialize
|
||||
v4l2_subdev::nevents to events queue depth before registering the
|
||||
sub-device. After registration events can be queued as usual on the
|
||||
v4l2_subdev::devnode device node.
|
||||
|
||||
To properly support events, the poll() file operation is also
|
||||
implemented.
|
||||
|
||||
Private ioctls
|
||||
|
||||
All ioctls not in the above list are passed directly to the sub-device
|
||||
driver through the core::ioctl operation.
|
||||
|
||||
|
||||
I2C sub-device drivers
|
||||
----------------------
|
||||
|
||||
|
@ -457,6 +564,10 @@ You should also set these fields:
|
|||
Otherwise you give it a pointer to a struct mutex_lock and before any
|
||||
of the v4l2_file_operations is called this lock will be taken by the
|
||||
core and released afterwards.
|
||||
- prio: keeps track of the priorities. Used to implement VIDIOC_G/S_PRIORITY.
|
||||
If left to NULL, then it will use the struct v4l2_prio_state in v4l2_device.
|
||||
If you want to have a separate priority state per (group of) device node(s),
|
||||
then you can point it to your own struct v4l2_prio_state.
|
||||
- parent: you only set this if v4l2_device was registered with NULL as
|
||||
the parent device struct. This only happens in cases where one hardware
|
||||
device has multiple PCI devices that all share the same v4l2_device core.
|
||||
|
@ -466,13 +577,34 @@ You should also set these fields:
|
|||
(cx8802). Since the v4l2_device cannot be associated with a particular
|
||||
PCI device it is setup without a parent device. But when the struct
|
||||
video_device is setup you do know which parent PCI device to use.
|
||||
- flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework
|
||||
handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct
|
||||
v4l2_fh. Eventually this flag will disappear once all drivers use the core
|
||||
priority handling. But for now it has to be set explicitly.
|
||||
|
||||
If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
|
||||
.ioctl to video_ioctl2 in your v4l2_file_operations struct.
|
||||
If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to video_ioctl2
|
||||
in your v4l2_file_operations struct.
|
||||
|
||||
Do not use .ioctl! This is deprecated and will go away in the future.
|
||||
|
||||
The v4l2_file_operations struct is a subset of file_operations. The main
|
||||
difference is that the inode argument is omitted since it is never used.
|
||||
|
||||
If integration with the media framework is needed, you must initialize the
|
||||
media_entity struct embedded in the video_device struct (entity field) by
|
||||
calling media_entity_init():
|
||||
|
||||
struct media_pad *pad = &my_vdev->pad;
|
||||
int err;
|
||||
|
||||
err = media_entity_init(&vdev->entity, 1, pad, 0);
|
||||
|
||||
The pads array must have been previously initialized. There is no need to
|
||||
manually set the struct media_entity type and name fields.
|
||||
|
||||
A reference to the entity will be automatically acquired/released when the
|
||||
video device is opened/closed.
|
||||
|
||||
v4l2_file_operations and locking
|
||||
--------------------------------
|
||||
|
||||
|
@ -502,6 +634,9 @@ for you.
|
|||
return err;
|
||||
}
|
||||
|
||||
If the v4l2_device parent device has a non-NULL mdev field, the video device
|
||||
entity will be automatically registered with the media device.
|
||||
|
||||
Which device is registered depends on the type argument. The following
|
||||
types exist:
|
||||
|
||||
|
@ -577,6 +712,13 @@ release, of course) will return an error as well.
|
|||
When the last user of the video device node exits, then the vdev->release()
|
||||
callback is called and you can do the final cleanup there.
|
||||
|
||||
Don't forget to cleanup the media entity associated with the video device if
|
||||
it has been initialized:
|
||||
|
||||
media_entity_cleanup(&vdev->entity);
|
||||
|
||||
This can be done from the release callback.
|
||||
|
||||
|
||||
video_device helper functions
|
||||
-----------------------------
|
||||
|
@ -636,39 +778,25 @@ struct v4l2_fh
|
|||
--------------
|
||||
|
||||
struct v4l2_fh provides a way to easily keep file handle specific data
|
||||
that is used by the V4L2 framework. Using v4l2_fh is optional for
|
||||
drivers.
|
||||
that is used by the V4L2 framework. New drivers must use struct v4l2_fh
|
||||
since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY)
|
||||
if the video_device flag V4L2_FL_USE_FH_PRIO is also set.
|
||||
|
||||
The users of v4l2_fh (in the V4L2 framework, not the driver) know
|
||||
whether a driver uses v4l2_fh as its file->private_data pointer by
|
||||
testing the V4L2_FL_USES_V4L2_FH bit in video_device->flags.
|
||||
|
||||
Useful functions:
|
||||
|
||||
- v4l2_fh_init()
|
||||
|
||||
Initialise the file handle. This *MUST* be performed in the driver's
|
||||
v4l2_file_operations->open() handler.
|
||||
|
||||
- v4l2_fh_add()
|
||||
|
||||
Add a v4l2_fh to video_device file handle list. May be called after
|
||||
initialising the file handle.
|
||||
|
||||
- v4l2_fh_del()
|
||||
|
||||
Unassociate the file handle from video_device(). The file handle
|
||||
exit function may now be called.
|
||||
|
||||
- v4l2_fh_exit()
|
||||
|
||||
Uninitialise the file handle. After uninitialisation the v4l2_fh
|
||||
memory can be freed.
|
||||
testing the V4L2_FL_USES_V4L2_FH bit in video_device->flags. This bit is
|
||||
set whenever v4l2_fh_init() is called.
|
||||
|
||||
struct v4l2_fh is allocated as a part of the driver's own file handle
|
||||
structure and is set to file->private_data in the driver's open
|
||||
function by the driver. Drivers can extract their own file handle
|
||||
structure by using the container_of macro. Example:
|
||||
structure and file->private_data is set to it in the driver's open
|
||||
function by the driver.
|
||||
|
||||
In many cases the struct v4l2_fh will be embedded in a larger structure.
|
||||
In that case you should call v4l2_fh_init+v4l2_fh_add in open() and
|
||||
v4l2_fh_del+v4l2_fh_exit in release().
|
||||
|
||||
Drivers can extract their own file handle structure by using the container_of
|
||||
macro. Example:
|
||||
|
||||
struct my_fh {
|
||||
int blah;
|
||||
|
@ -685,15 +813,21 @@ int my_open(struct file *file)
|
|||
|
||||
...
|
||||
|
||||
ret = v4l2_fh_init(&my_fh->fh, vfd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
v4l2_fh_add(&my_fh->fh);
|
||||
|
||||
file->private_data = &my_fh->fh;
|
||||
my_fh = kzalloc(sizeof(*my_fh), GFP_KERNEL);
|
||||
|
||||
...
|
||||
|
||||
ret = v4l2_fh_init(&my_fh->fh, vfd);
|
||||
if (ret) {
|
||||
kfree(my_fh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
file->private_data = &my_fh->fh;
|
||||
v4l2_fh_add(&my_fh->fh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_release(struct file *file)
|
||||
|
@ -702,8 +836,65 @@ int my_release(struct file *file)
|
|||
struct my_fh *my_fh = container_of(fh, struct my_fh, fh);
|
||||
|
||||
...
|
||||
v4l2_fh_del(&my_fh->fh);
|
||||
v4l2_fh_exit(&my_fh->fh);
|
||||
kfree(my_fh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Below is a short description of the v4l2_fh functions used:
|
||||
|
||||
int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
|
||||
|
||||
Initialise the file handle. This *MUST* be performed in the driver's
|
||||
v4l2_file_operations->open() handler.
|
||||
|
||||
void v4l2_fh_add(struct v4l2_fh *fh)
|
||||
|
||||
Add a v4l2_fh to video_device file handle list. Must be called once the
|
||||
file handle is completely initialized.
|
||||
|
||||
void v4l2_fh_del(struct v4l2_fh *fh)
|
||||
|
||||
Unassociate the file handle from video_device(). The file handle
|
||||
exit function may now be called.
|
||||
|
||||
void v4l2_fh_exit(struct v4l2_fh *fh)
|
||||
|
||||
Uninitialise the file handle. After uninitialisation the v4l2_fh
|
||||
memory can be freed.
|
||||
|
||||
|
||||
If struct v4l2_fh is not embedded, then you can use these helper functions:
|
||||
|
||||
int v4l2_fh_open(struct file *filp)
|
||||
|
||||
This allocates a struct v4l2_fh, initializes it and adds it to the struct
|
||||
video_device associated with the file struct.
|
||||
|
||||
int v4l2_fh_release(struct file *filp)
|
||||
|
||||
This deletes it from the struct video_device associated with the file
|
||||
struct, uninitialised the v4l2_fh and frees it.
|
||||
|
||||
These two functions can be plugged into the v4l2_file_operation's open() and
|
||||
release() ops.
|
||||
|
||||
|
||||
Several drivers need to do something when the first file handle is opened and
|
||||
when the last file handle closes. Two helper functions were added to check
|
||||
whether the v4l2_fh struct is the only open filehandle of the associated
|
||||
device node:
|
||||
|
||||
int v4l2_fh_is_singular(struct v4l2_fh *fh)
|
||||
|
||||
Returns 1 if the file handle is the only open file handle, else 0.
|
||||
|
||||
int v4l2_fh_is_singular_file(struct file *filp)
|
||||
|
||||
Same, but it calls v4l2_fh_is_singular with filp->private_data.
|
||||
|
||||
|
||||
V4L2 events
|
||||
-----------
|
||||
|
||||
|
|
|
@ -4582,6 +4582,12 @@ L: linux-omap@vger.kernel.org
|
|||
S: Maintained
|
||||
F: arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
||||
|
||||
OMAP IMAGE SIGNAL PROCESSOR (ISP)
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/media/video/omap3isp/*
|
||||
|
||||
OMAP USB SUPPORT
|
||||
M: Felipe Balbi <balbi@ti.com>
|
||||
M: David Brownell <dbrownell@users.sourceforge.net>
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "mux.h"
|
||||
#include "control.h"
|
||||
#include "devices.h"
|
||||
|
||||
#define L3_MODULES_MAX_LEN 12
|
||||
#define L3_MODULES 3
|
||||
|
@ -102,7 +103,7 @@ postcore_initcall(omap4_l3_init);
|
|||
|
||||
#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
|
||||
|
||||
static struct resource cam_resources[] = {
|
||||
static struct resource omap2cam_resources[] = {
|
||||
{
|
||||
.start = OMAP24XX_CAMERA_BASE,
|
||||
.end = OMAP24XX_CAMERA_BASE + 0xfff,
|
||||
|
@ -114,19 +115,13 @@ static struct resource cam_resources[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct platform_device omap_cam_device = {
|
||||
static struct platform_device omap2cam_device = {
|
||||
.name = "omap24xxcam",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(cam_resources),
|
||||
.resource = cam_resources,
|
||||
.num_resources = ARRAY_SIZE(omap2cam_resources),
|
||||
.resource = omap2cam_resources,
|
||||
};
|
||||
|
||||
static inline void omap_init_camera(void)
|
||||
{
|
||||
platform_device_register(&omap_cam_device);
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
|
||||
#endif
|
||||
|
||||
static struct resource omap3isp_resources[] = {
|
||||
{
|
||||
|
@ -134,11 +129,6 @@ static struct resource omap3isp_resources[] = {
|
|||
.end = OMAP3430_ISP_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP3430_ISP_CBUFF_BASE,
|
||||
.end = OMAP3430_ISP_CBUFF_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP3430_ISP_CCP2_BASE,
|
||||
.end = OMAP3430_ISP_CCP2_END,
|
||||
|
@ -175,13 +165,33 @@ static struct resource omap3isp_resources[] = {
|
|||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP3430_ISP_CSI2A_BASE,
|
||||
.end = OMAP3430_ISP_CSI2A_END,
|
||||
.start = OMAP3430_ISP_CSI2A_REGS1_BASE,
|
||||
.end = OMAP3430_ISP_CSI2A_REGS1_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP3430_ISP_CSI2PHY_BASE,
|
||||
.end = OMAP3430_ISP_CSI2PHY_END,
|
||||
.start = OMAP3430_ISP_CSIPHY2_BASE,
|
||||
.end = OMAP3430_ISP_CSIPHY2_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP3630_ISP_CSI2A_REGS2_BASE,
|
||||
.end = OMAP3630_ISP_CSI2A_REGS2_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP3630_ISP_CSI2C_REGS1_BASE,
|
||||
.end = OMAP3630_ISP_CSI2C_REGS1_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP3630_ISP_CSIPHY1_BASE,
|
||||
.end = OMAP3630_ISP_CSIPHY1_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = OMAP3630_ISP_CSI2C_REGS2_BASE,
|
||||
.end = OMAP3630_ISP_CSI2C_REGS2_END,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
|
@ -197,15 +207,19 @@ static struct platform_device omap3isp_device = {
|
|||
.resource = omap3isp_resources,
|
||||
};
|
||||
|
||||
int omap3_init_camera(struct isp_platform_data *pdata)
|
||||
{
|
||||
omap3isp_device.dev.platform_data = pdata;
|
||||
return platform_device_register(&omap3isp_device);
|
||||
}
|
||||
|
||||
static inline void omap_init_camera(void)
|
||||
{
|
||||
platform_device_register(&omap3isp_device);
|
||||
}
|
||||
#else
|
||||
static inline void omap_init_camera(void)
|
||||
{
|
||||
}
|
||||
#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
|
||||
if (cpu_is_omap24xx())
|
||||
platform_device_register(&omap2cam_device);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct omap_device_pm_latency omap_keyboard_latency[] = {
|
||||
{
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* arch/arm/mach-omap2/devices.h
|
||||
*
|
||||
* OMAP2 platform device setup/initialization
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_MACH_OMAP_DEVICES_H
|
||||
#define __ARCH_ARM_MACH_OMAP_DEVICES_H
|
||||
|
||||
struct isp_platform_data;
|
||||
|
||||
int omap3_init_camera(struct isp_platform_data *pdata);
|
||||
|
||||
#endif
|
|
@ -56,8 +56,12 @@
|
|||
#define OMAP3430_ISP_RESZ_BASE (OMAP3430_ISP_BASE + 0x1000)
|
||||
#define OMAP3430_ISP_SBL_BASE (OMAP3430_ISP_BASE + 0x1200)
|
||||
#define OMAP3430_ISP_MMU_BASE (OMAP3430_ISP_BASE + 0x1400)
|
||||
#define OMAP3430_ISP_CSI2A_BASE (OMAP3430_ISP_BASE + 0x1800)
|
||||
#define OMAP3430_ISP_CSI2PHY_BASE (OMAP3430_ISP_BASE + 0x1970)
|
||||
#define OMAP3430_ISP_CSI2A_REGS1_BASE (OMAP3430_ISP_BASE + 0x1800)
|
||||
#define OMAP3430_ISP_CSIPHY2_BASE (OMAP3430_ISP_BASE + 0x1970)
|
||||
#define OMAP3630_ISP_CSI2A_REGS2_BASE (OMAP3430_ISP_BASE + 0x19C0)
|
||||
#define OMAP3630_ISP_CSI2C_REGS1_BASE (OMAP3430_ISP_BASE + 0x1C00)
|
||||
#define OMAP3630_ISP_CSIPHY1_BASE (OMAP3430_ISP_BASE + 0x1D70)
|
||||
#define OMAP3630_ISP_CSI2C_REGS2_BASE (OMAP3430_ISP_BASE + 0x1DC0)
|
||||
|
||||
#define OMAP3430_ISP_END (OMAP3430_ISP_BASE + 0x06F)
|
||||
#define OMAP3430_ISP_CBUFF_END (OMAP3430_ISP_CBUFF_BASE + 0x077)
|
||||
|
@ -69,8 +73,12 @@
|
|||
#define OMAP3430_ISP_RESZ_END (OMAP3430_ISP_RESZ_BASE + 0x0AB)
|
||||
#define OMAP3430_ISP_SBL_END (OMAP3430_ISP_SBL_BASE + 0x0FB)
|
||||
#define OMAP3430_ISP_MMU_END (OMAP3430_ISP_MMU_BASE + 0x06F)
|
||||
#define OMAP3430_ISP_CSI2A_END (OMAP3430_ISP_CSI2A_BASE + 0x16F)
|
||||
#define OMAP3430_ISP_CSI2PHY_END (OMAP3430_ISP_CSI2PHY_BASE + 0x007)
|
||||
#define OMAP3430_ISP_CSI2A_REGS1_END (OMAP3430_ISP_CSI2A_REGS1_BASE + 0x16F)
|
||||
#define OMAP3430_ISP_CSIPHY2_END (OMAP3430_ISP_CSIPHY2_BASE + 0x00B)
|
||||
#define OMAP3630_ISP_CSI2A_REGS2_END (OMAP3630_ISP_CSI2A_REGS2_BASE + 0x3F)
|
||||
#define OMAP3630_ISP_CSI2C_REGS1_END (OMAP3630_ISP_CSI2C_REGS1_BASE + 0x16F)
|
||||
#define OMAP3630_ISP_CSIPHY1_END (OMAP3630_ISP_CSIPHY1_BASE + 0x00B)
|
||||
#define OMAP3630_ISP_CSI2C_REGS2_END (OMAP3630_ISP_CSI2C_REGS2_BASE + 0x3F)
|
||||
|
||||
#define OMAP34XX_HSUSB_OTG_BASE (L4_34XX_BASE + 0xAB000)
|
||||
#define OMAP34XX_USBTLL_BASE (L4_34XX_BASE + 0x62000)
|
||||
|
|
|
@ -13,6 +13,19 @@ if MEDIA_SUPPORT
|
|||
|
||||
comment "Multimedia core support"
|
||||
|
||||
#
|
||||
# Media controller
|
||||
#
|
||||
|
||||
config MEDIA_CONTROLLER
|
||||
bool "Media Controller API (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
---help---
|
||||
Enable the media controller API used to query media devices internal
|
||||
topology and configure it dynamically.
|
||||
|
||||
This API is mostly used by camera interfaces in embedded platforms.
|
||||
|
||||
#
|
||||
# V4L core and enabled API's
|
||||
#
|
||||
|
@ -40,6 +53,15 @@ config VIDEO_V4L2_COMMON
|
|||
depends on (I2C || I2C=n) && VIDEO_DEV
|
||||
default (I2C || I2C=n) && VIDEO_DEV
|
||||
|
||||
config VIDEO_V4L2_SUBDEV_API
|
||||
bool "V4L2 sub-device userspace API (EXPERIMENTAL)"
|
||||
depends on VIDEO_DEV && MEDIA_CONTROLLER && EXPERIMENTAL
|
||||
---help---
|
||||
Enables the V4L2 sub-device pad-level userspace API used to configure
|
||||
video format, size and frame rate between hardware blocks.
|
||||
|
||||
This API is mostly used by camera interfaces in embedded platforms.
|
||||
|
||||
#
|
||||
# DVB Core
|
||||
#
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
# Makefile for the kernel multimedia device drivers.
|
||||
#
|
||||
|
||||
media-objs := media-device.o media-devnode.o media-entity.o
|
||||
|
||||
ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
|
||||
obj-$(CONFIG_MEDIA_SUPPORT) += media.o
|
||||
endif
|
||||
|
||||
obj-y += common/ rc/ video/
|
||||
|
||||
obj-$(CONFIG_VIDEO_DEV) += radio/
|
||||
|
|
|
@ -36,6 +36,8 @@ struct tda9887_priv {
|
|||
unsigned int mode;
|
||||
unsigned int audmode;
|
||||
v4l2_std_id std;
|
||||
|
||||
bool standby;
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -568,7 +570,7 @@ static void tda9887_configure(struct dvb_frontend *fe)
|
|||
tda9887_do_config(fe);
|
||||
tda9887_set_insmod(fe);
|
||||
|
||||
if (priv->mode == T_STANDBY)
|
||||
if (priv->standby)
|
||||
priv->data[1] |= cForcedMuteAudioON;
|
||||
|
||||
tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
|
||||
|
@ -616,7 +618,7 @@ static void tda9887_standby(struct dvb_frontend *fe)
|
|||
{
|
||||
struct tda9887_priv *priv = fe->analog_demod_priv;
|
||||
|
||||
priv->mode = T_STANDBY;
|
||||
priv->standby = true;
|
||||
|
||||
tda9887_configure(fe);
|
||||
}
|
||||
|
@ -626,6 +628,7 @@ static void tda9887_set_params(struct dvb_frontend *fe,
|
|||
{
|
||||
struct tda9887_priv *priv = fe->analog_demod_priv;
|
||||
|
||||
priv->standby = false;
|
||||
priv->mode = params->mode;
|
||||
priv->audmode = params->audmode;
|
||||
priv->std = params->std;
|
||||
|
@ -686,7 +689,7 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
|
|||
return NULL;
|
||||
case 1:
|
||||
fe->analog_demod_priv = priv;
|
||||
priv->mode = T_STANDBY;
|
||||
priv->standby = true;
|
||||
tuner_info("tda988[5/6/7] found\n");
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -23,6 +23,7 @@ struct tea5761_priv {
|
|||
struct tuner_i2c_props i2c_props;
|
||||
|
||||
u32 frequency;
|
||||
bool standby;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -135,18 +136,19 @@ static void tea5761_status_dump(unsigned char *buffer)
|
|||
}
|
||||
|
||||
/* Freq should be specifyed at 62.5 Hz */
|
||||
static int set_radio_freq(struct dvb_frontend *fe,
|
||||
struct analog_parameters *params)
|
||||
static int __set_radio_freq(struct dvb_frontend *fe,
|
||||
unsigned int freq,
|
||||
bool mono)
|
||||
{
|
||||
struct tea5761_priv *priv = fe->tuner_priv;
|
||||
unsigned int frq = params->frequency;
|
||||
unsigned int frq = freq;
|
||||
unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 };
|
||||
unsigned div;
|
||||
int rc;
|
||||
|
||||
tuner_dbg("radio freq counter %d\n", frq);
|
||||
|
||||
if (params->mode == T_STANDBY) {
|
||||
if (priv->standby) {
|
||||
tuner_dbg("TEA5761 set to standby mode\n");
|
||||
buffer[5] |= TEA5761_TNCTRL_MU;
|
||||
} else {
|
||||
|
@ -154,7 +156,7 @@ static int set_radio_freq(struct dvb_frontend *fe,
|
|||
}
|
||||
|
||||
|
||||
if (params->audmode == V4L2_TUNER_MODE_MONO) {
|
||||
if (mono) {
|
||||
tuner_dbg("TEA5761 set to mono\n");
|
||||
buffer[5] |= TEA5761_TNCTRL_MST;
|
||||
} else {
|
||||
|
@ -176,6 +178,26 @@ static int set_radio_freq(struct dvb_frontend *fe,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int set_radio_freq(struct dvb_frontend *fe,
|
||||
struct analog_parameters *params)
|
||||
{
|
||||
struct tea5761_priv *priv = fe->analog_demod_priv;
|
||||
|
||||
priv->standby = false;
|
||||
|
||||
return __set_radio_freq(fe, params->frequency,
|
||||
params->audmode == V4L2_TUNER_MODE_MONO);
|
||||
}
|
||||
|
||||
static int set_radio_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tea5761_priv *priv = fe->analog_demod_priv;
|
||||
|
||||
priv->standby = true;
|
||||
|
||||
return __set_radio_freq(fe, priv->frequency, false);
|
||||
}
|
||||
|
||||
static int tea5761_read_status(struct dvb_frontend *fe, char *buffer)
|
||||
{
|
||||
struct tea5761_priv *priv = fe->tuner_priv;
|
||||
|
@ -284,6 +306,7 @@ static struct dvb_tuner_ops tea5761_tuner_ops = {
|
|||
.name = "tea5761", // Philips TEA5761HN FM Radio
|
||||
},
|
||||
.set_analog_params = set_radio_freq,
|
||||
.sleep = set_radio_sleep,
|
||||
.release = tea5761_release,
|
||||
.get_frequency = tea5761_get_frequency,
|
||||
.get_status = tea5761_get_status,
|
||||
|
|
|
@ -971,6 +971,22 @@ static struct tuner_params tuner_tena_9533_di_params[] = {
|
|||
},
|
||||
};
|
||||
|
||||
/* ------------ TUNER_TENA_TNF_5337 - Tena tnf5337MFD STD M/N ------------ */
|
||||
|
||||
static struct tuner_range tuner_tena_tnf_5337_ntsc_ranges[] = {
|
||||
{ 16 * 166.25 /*MHz*/, 0x86, 0x01, },
|
||||
{ 16 * 466.25 /*MHz*/, 0x86, 0x02, },
|
||||
{ 16 * 999.99 , 0x86, 0x08, },
|
||||
};
|
||||
|
||||
static struct tuner_params tuner_tena_tnf_5337_params[] = {
|
||||
{
|
||||
.type = TUNER_PARAM_TYPE_NTSC,
|
||||
.ranges = tuner_tena_tnf_5337_ntsc_ranges,
|
||||
.count = ARRAY_SIZE(tuner_tena_tnf_5337_ntsc_ranges),
|
||||
},
|
||||
};
|
||||
|
||||
/* ------------ TUNER_PHILIPS_FMD1216ME(X)_MK3 - Philips PAL ------------ */
|
||||
|
||||
static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
|
||||
|
@ -1842,6 +1858,11 @@ struct tunertype tuners[] = {
|
|||
.params = tuner_philips_fq1236_mk5_params,
|
||||
.count = ARRAY_SIZE(tuner_philips_fq1236_mk5_params),
|
||||
},
|
||||
[TUNER_TENA_TNF_5337] = { /* Tena 5337 MFD */
|
||||
.name = "Tena TNF5337 MFD",
|
||||
.params = tuner_tena_tnf_5337_params,
|
||||
.count = ARRAY_SIZE(tuner_tena_tnf_5337_params),
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(tuners);
|
||||
|
||||
|
|
|
@ -685,7 +685,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
|
|||
{
|
||||
struct xc2028_data *priv = fe->tuner_priv;
|
||||
struct firmware_properties new_fw;
|
||||
int rc = 0, is_retry = 0;
|
||||
int rc = 0, retry_count = 0;
|
||||
u16 version, hwmodel;
|
||||
v4l2_std_id std0;
|
||||
|
||||
|
@ -855,9 +855,9 @@ read_not_reliable:
|
|||
|
||||
fail:
|
||||
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
|
||||
if (!is_retry) {
|
||||
if (retry_count < 8) {
|
||||
msleep(50);
|
||||
is_retry = 1;
|
||||
retry_count++;
|
||||
tuner_dbg("Retrying firmware load\n");
|
||||
goto retry;
|
||||
}
|
||||
|
@ -907,7 +907,7 @@ ret:
|
|||
#define DIV 15625
|
||||
|
||||
static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
|
||||
enum tuner_mode new_mode,
|
||||
enum v4l2_tuner_type new_type,
|
||||
unsigned int type,
|
||||
v4l2_std_id std,
|
||||
u16 int_freq)
|
||||
|
@ -933,7 +933,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
|
|||
* that xc2028 will be in a safe state.
|
||||
* Maybe this might also be needed for DTV.
|
||||
*/
|
||||
if (new_mode == T_ANALOG_TV) {
|
||||
if (new_type == V4L2_TUNER_ANALOG_TV) {
|
||||
rc = send_seq(priv, {0x00, 0x00});
|
||||
|
||||
/* Analog modes require offset = 0 */
|
||||
|
@ -1054,7 +1054,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
|
|||
if (priv->ctrl.input1)
|
||||
type |= INPUT1;
|
||||
return generic_set_freq(fe, (625l * p->frequency) / 10,
|
||||
T_RADIO, type, 0, 0);
|
||||
V4L2_TUNER_RADIO, type, 0, 0);
|
||||
}
|
||||
|
||||
/* if std is not defined, choose one */
|
||||
|
@ -1069,7 +1069,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
|
|||
p->std |= parse_audio_std_option();
|
||||
|
||||
return generic_set_freq(fe, 62500l * p->frequency,
|
||||
T_ANALOG_TV, type, p->std, 0);
|
||||
V4L2_TUNER_ANALOG_TV, type, p->std, 0);
|
||||
}
|
||||
|
||||
static int xc2028_set_params(struct dvb_frontend *fe,
|
||||
|
@ -1174,7 +1174,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
|
|||
}
|
||||
|
||||
return generic_set_freq(fe, p->frequency,
|
||||
T_DIGITAL_TV, type, 0, demod);
|
||||
V4L2_TUNER_DIGITAL_TV, type, 0, demod);
|
||||
}
|
||||
|
||||
static int xc2028_sleep(struct dvb_frontend *fe)
|
||||
|
|
|
@ -65,7 +65,7 @@ struct xc5000_priv {
|
|||
};
|
||||
|
||||
/* Misc Defines */
|
||||
#define MAX_TV_STANDARD 23
|
||||
#define MAX_TV_STANDARD 24
|
||||
#define XC_MAX_I2C_WRITE_LENGTH 64
|
||||
|
||||
/* Signal Types */
|
||||
|
@ -92,6 +92,8 @@ struct xc5000_priv {
|
|||
#define XREG_IF_OUT 0x05
|
||||
#define XREG_SEEK_MODE 0x07
|
||||
#define XREG_POWER_DOWN 0x0A /* Obsolete */
|
||||
/* Set the output amplitude - SIF for analog, DTVP/DTVN for digital */
|
||||
#define XREG_OUTPUT_AMP 0x0B
|
||||
#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
|
||||
#define XREG_SMOOTHEDCVBS 0x0E
|
||||
#define XREG_XTALFREQ 0x0F
|
||||
|
@ -173,6 +175,7 @@ struct XC_TV_STANDARD {
|
|||
#define DTV7 20
|
||||
#define FM_Radio_INPUT2 21
|
||||
#define FM_Radio_INPUT1 22
|
||||
#define FM_Radio_INPUT1_MONO 23
|
||||
|
||||
static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
|
||||
{"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
|
||||
|
@ -197,7 +200,8 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
|
|||
{"DTV7/8", 0x00C0, 0x801B},
|
||||
{"DTV7", 0x00C0, 0x8007},
|
||||
{"FM Radio-INPUT2", 0x9802, 0x9002},
|
||||
{"FM Radio-INPUT1", 0x0208, 0x9002}
|
||||
{"FM Radio-INPUT1", 0x0208, 0x9002},
|
||||
{"FM Radio-INPUT1_MONO", 0x0278, 0x9002}
|
||||
};
|
||||
|
||||
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
|
||||
|
@ -683,6 +687,24 @@ static int xc5000_set_params(struct dvb_frontend *fe,
|
|||
return -EINVAL;
|
||||
}
|
||||
priv->rf_mode = XC_RF_MODE_AIR;
|
||||
} else if (fe->ops.info.type == FE_QAM) {
|
||||
dprintk(1, "%s() QAM\n", __func__);
|
||||
switch (params->u.qam.modulation) {
|
||||
case QAM_16:
|
||||
case QAM_32:
|
||||
case QAM_64:
|
||||
case QAM_128:
|
||||
case QAM_256:
|
||||
case QAM_AUTO:
|
||||
dprintk(1, "%s() QAM modulation\n", __func__);
|
||||
priv->bandwidth = BANDWIDTH_8_MHZ;
|
||||
priv->video_standard = DTV7_8;
|
||||
priv->freq_hz = params->frequency - 2750000;
|
||||
priv->rf_mode = XC_RF_MODE_CABLE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "xc5000 modulation type not supported!\n");
|
||||
return -EINVAL;
|
||||
|
@ -714,6 +736,8 @@ static int xc5000_set_params(struct dvb_frontend *fe,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a);
|
||||
|
||||
xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
|
||||
|
||||
if (debug)
|
||||
|
@ -818,6 +842,8 @@ tune_channel:
|
|||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
|
||||
|
||||
xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
|
||||
|
||||
if (debug)
|
||||
|
@ -845,6 +871,8 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe,
|
|||
radio_input = FM_Radio_INPUT1;
|
||||
else if (priv->radio_input == XC5000_RADIO_FM2)
|
||||
radio_input = FM_Radio_INPUT2;
|
||||
else if (priv->radio_input == XC5000_RADIO_FM1_MONO)
|
||||
radio_input = FM_Radio_INPUT1_MONO;
|
||||
else {
|
||||
dprintk(1, "%s() unknown radio input %d\n", __func__,
|
||||
priv->radio_input);
|
||||
|
@ -871,6 +899,12 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe,
|
|||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
if ((priv->radio_input == XC5000_RADIO_FM1) ||
|
||||
(priv->radio_input == XC5000_RADIO_FM2))
|
||||
xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
|
||||
else if (priv->radio_input == XC5000_RADIO_FM1_MONO)
|
||||
xc_write_reg(priv, XREG_OUTPUT_AMP, 0x06);
|
||||
|
||||
xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
|
||||
|
||||
return 0;
|
||||
|
@ -1021,6 +1055,23 @@ static int xc5000_release(struct dvb_frontend *fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int xc5000_set_config(struct dvb_frontend *fe, void *priv_cfg)
|
||||
{
|
||||
struct xc5000_priv *priv = fe->tuner_priv;
|
||||
struct xc5000_config *p = priv_cfg;
|
||||
|
||||
dprintk(1, "%s()\n", __func__);
|
||||
|
||||
if (p->if_khz)
|
||||
priv->if_khz = p->if_khz;
|
||||
|
||||
if (p->radio_input)
|
||||
priv->radio_input = p->radio_input;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct dvb_tuner_ops xc5000_tuner_ops = {
|
||||
.info = {
|
||||
.name = "Xceive XC5000",
|
||||
|
@ -1033,6 +1084,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = {
|
|||
.init = xc5000_init,
|
||||
.sleep = xc5000_sleep,
|
||||
|
||||
.set_config = xc5000_set_config,
|
||||
.set_params = xc5000_set_params,
|
||||
.set_analog_params = xc5000_set_analog_params,
|
||||
.get_frequency = xc5000_get_frequency,
|
||||
|
|
|
@ -40,6 +40,7 @@ struct xc5000_config {
|
|||
#define XC5000_RADIO_NOT_CONFIGURED 0
|
||||
#define XC5000_RADIO_FM1 1
|
||||
#define XC5000_RADIO_FM2 2
|
||||
#define XC5000_RADIO_FM1_MONO 3
|
||||
|
||||
/* For each bridge framework, when it attaches either analog or digital,
|
||||
* it has to store a reference back to its _core equivalent structure,
|
||||
|
|
|
@ -65,7 +65,7 @@ comment "Supported SDMC DM1105 Adapters"
|
|||
source "drivers/media/dvb/dm1105/Kconfig"
|
||||
|
||||
comment "Supported FireWire (IEEE 1394) Adapters"
|
||||
depends on DVB_CORE && IEEE1394
|
||||
depends on DVB_CORE && FIREWIRE
|
||||
source "drivers/media/dvb/firewire/Kconfig"
|
||||
|
||||
comment "Supported Earthsoft PT1 Adapters"
|
||||
|
|
|
@ -239,7 +239,6 @@ struct analog_demod_ops {
|
|||
void (*set_params)(struct dvb_frontend *fe,
|
||||
struct analog_parameters *params);
|
||||
int (*has_signal)(struct dvb_frontend *fe);
|
||||
int (*is_stereo)(struct dvb_frontend *fe);
|
||||
int (*get_afc)(struct dvb_frontend *fe);
|
||||
void (*tuner_status)(struct dvb_frontend *fe);
|
||||
void (*standby)(struct dvb_frontend *fe);
|
||||
|
|
|
@ -358,3 +358,11 @@ config DVB_USB_LME2510
|
|||
select DVB_IX2505V if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 .
|
||||
|
||||
config DVB_USB_TECHNISAT_USB2
|
||||
tristate "Technisat DVB-S/S2 USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_STB0899 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB6100 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Technisat USB2 DVB-S/S2 device
|
||||
|
|
|
@ -91,6 +91,9 @@ obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
|
|||
dvb-usb-lmedm04-objs = lmedm04.o
|
||||
obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o
|
||||
|
||||
dvb-usb-technisat-usb2-objs = technisat-usb2.o
|
||||
obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
|
||||
# due to tuner-xc3028
|
||||
EXTRA_CFLAGS += -Idrivers/media/common/tuners
|
||||
|
|
|
@ -38,8 +38,8 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr
|
|||
}
|
||||
|
||||
static struct rc_map_table rc_map_a800_table[] = {
|
||||
{ 0x0201, KEY_PROG1 }, /* SOURCE */
|
||||
{ 0x0200, KEY_POWER }, /* POWER */
|
||||
{ 0x0201, KEY_MODE }, /* SOURCE */
|
||||
{ 0x0200, KEY_POWER2 }, /* POWER */
|
||||
{ 0x0205, KEY_1 }, /* 1 */
|
||||
{ 0x0206, KEY_2 }, /* 2 */
|
||||
{ 0x0207, KEY_3 }, /* 3 */
|
||||
|
@ -52,8 +52,8 @@ static struct rc_map_table rc_map_a800_table[] = {
|
|||
{ 0x0212, KEY_LEFT }, /* L / DISPLAY */
|
||||
{ 0x0211, KEY_0 }, /* 0 */
|
||||
{ 0x0213, KEY_RIGHT }, /* R / CH RTN */
|
||||
{ 0x0217, KEY_PROG2 }, /* SNAP SHOT */
|
||||
{ 0x0210, KEY_PROG3 }, /* 16-CH PREV */
|
||||
{ 0x0217, KEY_CAMERA }, /* SNAP SHOT */
|
||||
{ 0x0210, KEY_LAST }, /* 16-CH PREV */
|
||||
{ 0x021e, KEY_VOLUMEDOWN }, /* VOL DOWN */
|
||||
{ 0x020c, KEY_ZOOM }, /* FULL SCREEN */
|
||||
{ 0x021f, KEY_VOLUMEUP }, /* VOL UP */
|
||||
|
|
|
@ -479,6 +479,7 @@ static int af9015_init_endpoint(struct dvb_usb_device *d)
|
|||
ret = af9015_set_reg_bit(d, 0xd50b, 0);
|
||||
else
|
||||
ret = af9015_clear_reg_bit(d, 0xd50b, 0);
|
||||
|
||||
error:
|
||||
if (ret)
|
||||
err("endpoint init failed:%d", ret);
|
||||
|
@ -611,6 +612,11 @@ static int af9015_init(struct dvb_usb_device *d)
|
|||
int ret;
|
||||
deb_info("%s:\n", __func__);
|
||||
|
||||
/* init RC canary */
|
||||
ret = af9015_write_reg(d, 0x98e9, 0xff);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = af9015_init_endpoint(d);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -659,9 +665,8 @@ error:
|
|||
static int af9015_download_firmware(struct usb_device *udev,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
int i, len, packets, remainder, ret;
|
||||
int i, len, remaining, ret;
|
||||
struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL};
|
||||
u16 addr = 0x5100; /* firmware start address */
|
||||
u16 checksum = 0;
|
||||
|
||||
deb_info("%s:\n", __func__);
|
||||
|
@ -673,24 +678,20 @@ static int af9015_download_firmware(struct usb_device *udev,
|
|||
af9015_config.firmware_size = fw->size;
|
||||
af9015_config.firmware_checksum = checksum;
|
||||
|
||||
#define FW_PACKET_MAX_DATA 55
|
||||
|
||||
packets = fw->size / FW_PACKET_MAX_DATA;
|
||||
remainder = fw->size % FW_PACKET_MAX_DATA;
|
||||
len = FW_PACKET_MAX_DATA;
|
||||
for (i = 0; i <= packets; i++) {
|
||||
if (i == packets) /* set size of the last packet */
|
||||
len = remainder;
|
||||
#define FW_ADDR 0x5100 /* firmware start address */
|
||||
#define LEN_MAX 55 /* max packet size */
|
||||
for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
|
||||
len = remaining;
|
||||
if (len > LEN_MAX)
|
||||
len = LEN_MAX;
|
||||
|
||||
req.data_len = len;
|
||||
req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
|
||||
req.addr = addr;
|
||||
addr += FW_PACKET_MAX_DATA;
|
||||
req.data = (u8 *) &fw->data[fw->size - remaining];
|
||||
req.addr = FW_ADDR + fw->size - remaining;
|
||||
|
||||
ret = af9015_rw_udev(udev, &req);
|
||||
if (ret) {
|
||||
err("firmware download failed at packet %d with " \
|
||||
"code %d", i, ret);
|
||||
err("firmware download failed:%d", ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -738,6 +739,8 @@ static const struct af9015_rc_setup af9015_rc_setup_hashes[] = {
|
|||
};
|
||||
|
||||
static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
|
||||
{ (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_RC,
|
||||
RC_MAP_TERRATEC_SLIM_2 },
|
||||
{ (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
|
||||
RC_MAP_TERRATEC_SLIM },
|
||||
{ (USB_VID_VISIONPLUS << 16) + USB_PID_AZUREWAVE_AD_TU700,
|
||||
|
@ -1016,22 +1019,38 @@ static int af9015_rc_query(struct dvb_usb_device *d)
|
|||
{
|
||||
struct af9015_state *priv = d->priv;
|
||||
int ret;
|
||||
u8 buf[16];
|
||||
u8 buf[17];
|
||||
|
||||
/* read registers needed to detect remote controller code */
|
||||
ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (buf[14] || buf[15]) {
|
||||
/* If any of these are non-zero, assume invalid data */
|
||||
if (buf[1] || buf[2] || buf[3])
|
||||
return ret;
|
||||
|
||||
/* Check for repeat of previous code */
|
||||
if ((priv->rc_repeat != buf[6] || buf[0]) &&
|
||||
!memcmp(&buf[12], priv->rc_last, 4)) {
|
||||
deb_rc("%s: key repeated\n", __func__);
|
||||
rc_keydown(d->rc_dev, priv->rc_keycode, 0);
|
||||
priv->rc_repeat = buf[6];
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Only process key if canary killed */
|
||||
if (buf[16] != 0xff && buf[0] != 0x01) {
|
||||
deb_rc("%s: key pressed %02x %02x %02x %02x\n", __func__,
|
||||
buf[12], buf[13], buf[14], buf[15]);
|
||||
|
||||
/* clean IR code from mem */
|
||||
ret = af9015_write_regs(d, 0x98e5, "\x00\x00\x00\x00", 4);
|
||||
/* Reset the canary */
|
||||
ret = af9015_write_reg(d, 0x98e9, 0xff);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* Remember this key */
|
||||
memcpy(priv->rc_last, &buf[12], 4);
|
||||
if (buf[14] == (u8) ~buf[15]) {
|
||||
if (buf[12] == (u8) ~buf[13]) {
|
||||
/* NEC */
|
||||
|
@ -1041,15 +1060,17 @@ static int af9015_rc_query(struct dvb_usb_device *d)
|
|||
priv->rc_keycode = buf[12] << 16 |
|
||||
buf[13] << 8 | buf[14];
|
||||
}
|
||||
rc_keydown(d->rc_dev, priv->rc_keycode, 0);
|
||||
} else {
|
||||
priv->rc_keycode = 0; /* clear just for sure */
|
||||
/* 32 bit NEC */
|
||||
priv->rc_keycode = buf[12] << 24 | buf[13] << 16 |
|
||||
buf[14] << 8 | buf[15];
|
||||
}
|
||||
} else if (priv->rc_repeat != buf[6] || buf[0]) {
|
||||
deb_rc("%s: key repeated\n", __func__);
|
||||
rc_keydown(d->rc_dev, priv->rc_keycode, 0);
|
||||
} else {
|
||||
deb_rc("%s: no key press\n", __func__);
|
||||
/* Invalidate last keypress */
|
||||
/* Not really needed, but helps with debug */
|
||||
priv->rc_last[2] = priv->rc_last[3];
|
||||
}
|
||||
|
||||
priv->rc_repeat = buf[6];
|
||||
|
|
|
@ -102,6 +102,7 @@ struct af9015_state {
|
|||
struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */
|
||||
u8 rc_repeat;
|
||||
u32 rc_keycode;
|
||||
u8 rc_last[4];
|
||||
};
|
||||
|
||||
struct af9015_config {
|
||||
|
|
|
@ -32,6 +32,7 @@ extern int dvb_usb_dib0700_debug;
|
|||
// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
|
||||
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
|
||||
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
|
||||
#define REQUEST_SET_I2C_PARAM 0x10
|
||||
#define REQUEST_SET_RC 0x11
|
||||
#define REQUEST_NEW_I2C_READ 0x12
|
||||
#define REQUEST_NEW_I2C_WRITE 0x13
|
||||
|
@ -61,6 +62,7 @@ extern struct i2c_algorithm dib0700_i2c_algo;
|
|||
extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc, int *cold);
|
||||
extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type);
|
||||
extern int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz);
|
||||
|
||||
extern int dib0700_device_count;
|
||||
extern int dvb_usb_dib0700_ir_proto;
|
||||
|
|
|
@ -186,7 +186,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
msg[i].len,
|
||||
USB_CTRL_GET_TIMEOUT);
|
||||
if (result < 0) {
|
||||
err("i2c read error (status = %d)\n", result);
|
||||
deb_info("i2c read error (status = %d)\n", result);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
0, 0, buf, msg[i].len + 4,
|
||||
USB_CTRL_GET_TIMEOUT);
|
||||
if (result < 0) {
|
||||
err("i2c write error (status = %d)\n", result);
|
||||
deb_info("i2c write error (status = %d)\n", result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -328,6 +328,31 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
|
|||
return dib0700_ctrl_wr(d, b, 10);
|
||||
}
|
||||
|
||||
int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
|
||||
{
|
||||
u16 divider;
|
||||
u8 b[8];
|
||||
|
||||
if (scl_kHz == 0)
|
||||
return -EINVAL;
|
||||
|
||||
b[0] = REQUEST_SET_I2C_PARAM;
|
||||
divider = (u16) (30000 / scl_kHz);
|
||||
b[2] = (u8) (divider >> 8);
|
||||
b[3] = (u8) (divider & 0xff);
|
||||
divider = (u16) (72000 / scl_kHz);
|
||||
b[4] = (u8) (divider >> 8);
|
||||
b[5] = (u8) (divider & 0xff);
|
||||
divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */
|
||||
b[6] = (u8) (divider >> 8);
|
||||
b[7] = (u8) (divider & 0xff);
|
||||
|
||||
deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
|
||||
(b[2] << 8) | (b[3]), (b[4] << 8) | b[5], (b[6] << 8) | b[7], scl_kHz);
|
||||
return dib0700_ctrl_wr(d, b, 8);
|
||||
}
|
||||
|
||||
|
||||
int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
|
||||
{
|
||||
switch (clk_MHz) {
|
||||
|
@ -459,10 +484,20 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
|
||||
deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
|
||||
|
||||
if (onoff)
|
||||
st->channel_state |= 1 << adap->id;
|
||||
else
|
||||
st->channel_state &= ~(1 << adap->id);
|
||||
st->channel_state &= ~0x3;
|
||||
if ((adap->stream.props.endpoint != 2)
|
||||
&& (adap->stream.props.endpoint != 3)) {
|
||||
deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->stream.props.endpoint);
|
||||
if (onoff)
|
||||
st->channel_state |= 1 << (adap->id);
|
||||
else
|
||||
st->channel_state |= 1 << ~(adap->id);
|
||||
} else {
|
||||
if (onoff)
|
||||
st->channel_state |= 1 << (adap->stream.props.endpoint-2);
|
||||
else
|
||||
st->channel_state |= 1 << (3-adap->stream.props.endpoint);
|
||||
}
|
||||
|
||||
b[2] |= st->channel_state;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -176,7 +176,7 @@ static struct rc_map_table rc_map_digitv_table[] = {
|
|||
{ 0xaf59, KEY_AUX },
|
||||
{ 0x5f5a, KEY_DVD },
|
||||
{ 0x6f5a, KEY_POWER },
|
||||
{ 0x9f5a, KEY_MHP }, /* labelled 'Picture' */
|
||||
{ 0x9f5a, KEY_CAMERA }, /* labelled 'Picture' */
|
||||
{ 0xaf5a, KEY_AUDIO },
|
||||
{ 0x5f65, KEY_INFO },
|
||||
{ 0x6f65, KEY_F13 }, /* 16:9 */
|
||||
|
|
|
@ -106,8 +106,13 @@
|
|||
#define USB_PID_DIBCOM_STK807XP 0x1f90
|
||||
#define USB_PID_DIBCOM_STK807XPVR 0x1f98
|
||||
#define USB_PID_DIBCOM_STK8096GP 0x1fa0
|
||||
#define USB_PID_DIBCOM_NIM8096MD 0x1fa8
|
||||
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
|
||||
#define USB_PID_DIBCOM_STK7770P 0x1e80
|
||||
#define USB_PID_DIBCOM_NIM7090 0x1bb2
|
||||
#define USB_PID_DIBCOM_TFE7090PVR 0x1bb4
|
||||
#define USB_PID_DIBCOM_NIM9090M 0x2383
|
||||
#define USB_PID_DIBCOM_NIM9090MD 0x2384
|
||||
#define USB_PID_DPOSH_M9206_COLD 0x9206
|
||||
#define USB_PID_DPOSH_M9206_WARM 0xa090
|
||||
#define USB_PID_E3C_EC168 0x1689
|
||||
|
@ -312,4 +317,6 @@
|
|||
#define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac
|
||||
#define USB_PID_TECHNISAT_USB2_HDCI_V1 0x0001
|
||||
#define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002
|
||||
#define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004
|
||||
#define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500
|
||||
#endif
|
||||
|
|
|
@ -273,7 +273,7 @@ static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
|
|||
dev->map_name = d->props.rc.core.rc_codes;
|
||||
dev->change_protocol = d->props.rc.core.change_protocol;
|
||||
dev->allowed_protos = d->props.rc.core.allowed_protos;
|
||||
dev->driver_type = RC_DRIVER_SCANCODE;
|
||||
dev->driver_type = d->props.rc.core.driver_type;
|
||||
usb_to_input_id(d->udev, &dev->input_id);
|
||||
dev->input_name = "IR-receiver inside an USB DVB receiver";
|
||||
dev->input_phys = d->rc_phys;
|
||||
|
|
|
@ -181,6 +181,7 @@ struct dvb_rc_legacy {
|
|||
* @rc_codes: name of rc codes table
|
||||
* @protocol: type of protocol(s) currently used by the driver
|
||||
* @allowed_protos: protocol(s) supported by the driver
|
||||
* @driver_type: Used to point if a device supports raw mode
|
||||
* @change_protocol: callback to change protocol
|
||||
* @rc_query: called to query an event event.
|
||||
* @rc_interval: time in ms between two queries.
|
||||
|
@ -190,6 +191,7 @@ struct dvb_rc {
|
|||
char *rc_codes;
|
||||
u64 protocol;
|
||||
u64 allowed_protos;
|
||||
enum rc_driver_type driver_type;
|
||||
int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
|
||||
char *module_name;
|
||||
int (*rc_query) (struct dvb_usb_device *d);
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
/* DVB USB framework compliant Linux driver for the
|
||||
* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
|
||||
* TeVii S600, S630, S650,
|
||||
* Prof 1100, 7500 Cards
|
||||
* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by)
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
|
||||
* TeVii S600, S630, S650, S660, S480,
|
||||
* Prof 1100, 7500,
|
||||
* Geniatech SU3000 Cards
|
||||
* Copyright (C) 2008-2011 Igor M. Liplianin (liplianin@me.by)
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
#include "dw2102.h"
|
||||
#include "si21xx.h"
|
||||
#include "stv0299.h"
|
||||
|
@ -55,6 +56,14 @@
|
|||
#define USB_PID_TEVII_S660 0xd660
|
||||
#endif
|
||||
|
||||
#ifndef USB_PID_TEVII_S480_1
|
||||
#define USB_PID_TEVII_S480_1 0xd481
|
||||
#endif
|
||||
|
||||
#ifndef USB_PID_TEVII_S480_2
|
||||
#define USB_PID_TEVII_S480_2 0xd482
|
||||
#endif
|
||||
|
||||
#ifndef USB_PID_PROF_1100
|
||||
#define USB_PID_PROF_1100 0xb012
|
||||
#endif
|
||||
|
@ -67,7 +76,9 @@
|
|||
#define REG_21_SYMBOLRATE_BYTE2 0x21
|
||||
/* on my own*/
|
||||
#define DW2102_VOLTAGE_CTRL (0x1800)
|
||||
#define SU3000_STREAM_CTRL (0x1900)
|
||||
#define DW2102_RC_QUERY (0x1a00)
|
||||
#define DW2102_LED_CTRL (0x1b00)
|
||||
|
||||
#define err_str "did not find the firmware file. (%s) " \
|
||||
"Please see linux/Documentation/dvb/ for more details " \
|
||||
|
@ -78,6 +89,14 @@ struct rc_map_dvb_usb_table_table {
|
|||
int rc_keys_size;
|
||||
};
|
||||
|
||||
struct su3000_state {
|
||||
u8 initialized;
|
||||
};
|
||||
|
||||
struct s6x0_state {
|
||||
int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v);
|
||||
};
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_dw2102_debug;
|
||||
module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
|
||||
|
@ -87,7 +106,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
|
|||
/* keymaps */
|
||||
static int ir_keymap;
|
||||
module_param_named(keymap, ir_keymap, int, 0644);
|
||||
MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ...");
|
||||
MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ..."
|
||||
" 256=none");
|
||||
|
||||
/* demod probe */
|
||||
static int demod_probe = 1;
|
||||
|
@ -136,8 +156,7 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
/* read stv0299 register */
|
||||
value = msg[0].buf[0];/* register */
|
||||
for (i = 0; i < msg[1].len; i++) {
|
||||
value = value + i;
|
||||
ret = dw210x_op_rw(d->udev, 0xb5, value, 0,
|
||||
ret = dw210x_op_rw(d->udev, 0xb5, value + i, 0,
|
||||
buf6, 2, DW210X_READ_MSG);
|
||||
msg[1].buf[i] = buf6[0];
|
||||
}
|
||||
|
@ -483,10 +502,10 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
for (j = 0; j < num; j++) {
|
||||
switch (msg[j].addr) {
|
||||
case (DW2102_RC_QUERY): {
|
||||
u8 ibuf[4];
|
||||
u8 ibuf[5];
|
||||
ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
|
||||
ibuf, 4, DW210X_READ_MSG);
|
||||
memcpy(msg[j].buf, ibuf + 1, 2);
|
||||
ibuf, 5, DW210X_READ_MSG);
|
||||
memcpy(msg[j].buf, ibuf + 3, 2);
|
||||
break;
|
||||
}
|
||||
case (DW2102_VOLTAGE_CTRL): {
|
||||
|
@ -502,6 +521,15 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
obuf, 2, DW210X_WRITE_MSG);
|
||||
break;
|
||||
}
|
||||
case (DW2102_LED_CTRL): {
|
||||
u8 obuf[2];
|
||||
|
||||
obuf[0] = 5;
|
||||
obuf[1] = msg[j].buf[0];
|
||||
ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
|
||||
obuf, 2, DW210X_WRITE_MSG);
|
||||
break;
|
||||
}
|
||||
/*case 0x55: cx24116
|
||||
case 0x6a: stv0903
|
||||
case 0x68: ds3000, stv0903
|
||||
|
@ -535,14 +563,15 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
i += 16;
|
||||
len -= 16;
|
||||
} while (len > 0);
|
||||
} else if ((udev->descriptor.idProduct == 0x7500)
|
||||
&& (j < (num - 1))) {
|
||||
} else if (j < (num - 1)) {
|
||||
/* write register addr before read */
|
||||
u8 obuf[msg[j].len + 2];
|
||||
obuf[0] = msg[j + 1].len;
|
||||
obuf[1] = (msg[j].addr << 1);
|
||||
memcpy(obuf + 2, msg[j].buf, msg[j].len);
|
||||
ret = dw210x_op_rw(d->udev, 0x92, 0, 0,
|
||||
ret = dw210x_op_rw(d->udev,
|
||||
udev->descriptor.idProduct ==
|
||||
0x7500 ? 0x92 : 0x90, 0, 0,
|
||||
obuf, msg[j].len + 2,
|
||||
DW210X_WRITE_MSG);
|
||||
break;
|
||||
|
@ -552,8 +581,7 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
obuf[0] = msg[j].len + 1;
|
||||
obuf[1] = (msg[j].addr << 1);
|
||||
memcpy(obuf + 2, msg[j].buf, msg[j].len);
|
||||
ret = dw210x_op_rw(d->udev,
|
||||
(num > 1 ? 0x90 : 0x80), 0, 0,
|
||||
ret = dw210x_op_rw(d->udev, 0x80, 0, 0,
|
||||
obuf, msg[j].len + 2,
|
||||
DW210X_WRITE_MSG);
|
||||
break;
|
||||
|
@ -561,14 +589,76 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
msleep(3);
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
u8 obuf[0x40], ibuf[0x40];
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (num) {
|
||||
case 1:
|
||||
switch (msg[0].addr) {
|
||||
case SU3000_STREAM_CTRL:
|
||||
obuf[0] = msg[0].buf[0] + 0x36;
|
||||
obuf[1] = 3;
|
||||
obuf[2] = 0;
|
||||
if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0)
|
||||
err("i2c transfer failed.");
|
||||
break;
|
||||
case DW2102_RC_QUERY:
|
||||
obuf[0] = 0x10;
|
||||
if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0)
|
||||
err("i2c transfer failed.");
|
||||
msg[0].buf[1] = ibuf[0];
|
||||
msg[0].buf[0] = ibuf[1];
|
||||
break;
|
||||
default:
|
||||
/* always i2c write*/
|
||||
obuf[0] = 0x08;
|
||||
obuf[1] = msg[0].addr;
|
||||
obuf[2] = msg[0].len;
|
||||
|
||||
memcpy(&obuf[3], msg[0].buf, msg[0].len);
|
||||
|
||||
if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3,
|
||||
ibuf, 1, 0) < 0)
|
||||
err("i2c transfer failed.");
|
||||
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
/* always i2c read */
|
||||
obuf[0] = 0x09;
|
||||
obuf[1] = msg[0].len;
|
||||
obuf[2] = msg[1].len;
|
||||
obuf[3] = msg[0].addr;
|
||||
memcpy(&obuf[4], msg[0].buf, msg[0].len);
|
||||
|
||||
if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4,
|
||||
ibuf, msg[1].len + 1, 0) < 0)
|
||||
err("i2c transfer failed.");
|
||||
|
||||
memcpy(msg[1].buf, &ibuf[1], msg[1].len);
|
||||
break;
|
||||
default:
|
||||
warn("more than 2 i2c messages at a time is not handled yet.");
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
|
@ -604,6 +694,11 @@ static struct i2c_algorithm s6x0_i2c_algo = {
|
|||
.functionality = dw210x_i2c_func,
|
||||
};
|
||||
|
||||
static struct i2c_algorithm su3000_i2c_algo = {
|
||||
.master_xfer = su3000_i2c_transfer,
|
||||
.functionality = dw210x_i2c_func,
|
||||
};
|
||||
|
||||
static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i;
|
||||
|
@ -668,6 +763,82 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
|||
return 0;
|
||||
};
|
||||
|
||||
static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
static u8 command_start[] = {0x00};
|
||||
static u8 command_stop[] = {0x01};
|
||||
struct i2c_msg msg = {
|
||||
.addr = SU3000_STREAM_CTRL,
|
||||
.flags = 0,
|
||||
.buf = onoff ? command_start : command_stop,
|
||||
.len = 1
|
||||
};
|
||||
|
||||
i2c_transfer(&adap->dev->i2c_adap, &msg, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
|
||||
{
|
||||
struct su3000_state *state = (struct su3000_state *)d->priv;
|
||||
u8 obuf[] = {0xde, 0};
|
||||
|
||||
info("%s: %d, initialized %d\n", __func__, i, state->initialized);
|
||||
|
||||
if (i && !state->initialized) {
|
||||
state->initialized = 1;
|
||||
/* reset board */
|
||||
dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i;
|
||||
u8 obuf[] = { 0x1f, 0xf0 };
|
||||
u8 ibuf[] = { 0 };
|
||||
struct i2c_msg msg[] = {
|
||||
{
|
||||
.addr = 0x51,
|
||||
.flags = 0,
|
||||
.buf = obuf,
|
||||
.len = 2,
|
||||
}, {
|
||||
.addr = 0x51,
|
||||
.flags = I2C_M_RD,
|
||||
.buf = ibuf,
|
||||
.len = 1,
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
obuf[1] = 0xf0 + i;
|
||||
if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
|
||||
break;
|
||||
else
|
||||
mac[i] = ibuf[0];
|
||||
|
||||
debug_dump(mac, 6, printk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int su3000_identify_state(struct usb_device *udev,
|
||||
struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc,
|
||||
int *cold)
|
||||
{
|
||||
info("%s\n", __func__);
|
||||
|
||||
*cold = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
static u8 command_13v[] = {0x00, 0x01};
|
||||
|
@ -692,6 +863,37 @@ static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int s660_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct dvb_usb_adapter *d =
|
||||
(struct dvb_usb_adapter *)(fe->dvb->priv);
|
||||
struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
|
||||
|
||||
dw210x_set_voltage(fe, voltage);
|
||||
if (st->old_set_voltage)
|
||||
st->old_set_voltage(fe, voltage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
|
||||
{
|
||||
static u8 led_off[] = { 0 };
|
||||
static u8 led_on[] = { 1 };
|
||||
struct i2c_msg msg = {
|
||||
.addr = DW2102_LED_CTRL,
|
||||
.flags = 0,
|
||||
.buf = led_off,
|
||||
.len = 1
|
||||
};
|
||||
struct dvb_usb_adapter *udev_adap =
|
||||
(struct dvb_usb_adapter *)(fe->dvb->priv);
|
||||
|
||||
if (offon)
|
||||
msg.buf = led_on;
|
||||
i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
|
||||
}
|
||||
|
||||
static struct stv0299_config sharp_z0194a_config = {
|
||||
.demod_address = 0x68,
|
||||
.inittab = sharp_z0194a_inittab,
|
||||
|
@ -771,6 +973,12 @@ static struct stv0900_config prof_7500_stv0900_config = {
|
|||
.tun1_adc = 0,/* 2 Vpp */
|
||||
.path1_mode = 3,
|
||||
.tun1_type = 3,
|
||||
.set_lock_led = dw210x_led_ctrl,
|
||||
};
|
||||
|
||||
static struct ds3000_config su3000_ds3000_config = {
|
||||
.demod_address = 0x68,
|
||||
.ci_mode = 1,
|
||||
};
|
||||
|
||||
static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
|
||||
|
@ -885,7 +1093,7 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static int s6x0_frontend_attach(struct dvb_usb_adapter *d)
|
||||
static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
d->fe = dvb_attach(mt312_attach, &zl313_config,
|
||||
&d->dev->i2c_adap);
|
||||
|
@ -898,41 +1106,108 @@ static int s6x0_frontend_attach(struct dvb_usb_adapter *d)
|
|||
}
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
u8 obuf[] = {7, 1};
|
||||
|
||||
d->fe = dvb_attach(stv0288_attach, &earda_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe != NULL) {
|
||||
if (dvb_attach(stb6000_attach, d->fe, 0x61,
|
||||
&d->dev->i2c_adap)) {
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached stv0288+stb6000!\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (d->fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
if (NULL == dvb_attach(stb6000_attach, d->fe, 0x61, &d->dev->i2c_adap))
|
||||
return -EIO;
|
||||
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
|
||||
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
|
||||
|
||||
info("Attached stv0288+stb6000!\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
|
||||
u8 obuf[] = {7, 1};
|
||||
|
||||
d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe != NULL) {
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached ds3000+ds2020!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
if (d->fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
st->old_set_voltage = d->fe->ops.set_voltage;
|
||||
d->fe->ops.set_voltage = s660_set_voltage;
|
||||
|
||||
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
|
||||
|
||||
info("Attached ds3000+ds2020!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
u8 obuf[] = {7, 1};
|
||||
|
||||
d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
|
||||
&d->dev->i2c_adap, 0);
|
||||
if (d->fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
|
||||
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
|
||||
|
||||
info("Attached STV0900+STB6100A!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int su3000_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
u8 obuf[3] = { 0xe, 0x80, 0 };
|
||||
u8 ibuf[] = { 0 };
|
||||
|
||||
if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
|
||||
err("command 0x0e transfer failed.");
|
||||
|
||||
obuf[0] = 0xe;
|
||||
obuf[1] = 0x83;
|
||||
obuf[2] = 0;
|
||||
|
||||
if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
|
||||
err("command 0x0e transfer failed.");
|
||||
|
||||
obuf[0] = 0xe;
|
||||
obuf[1] = 0x83;
|
||||
obuf[2] = 1;
|
||||
|
||||
if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
|
||||
err("command 0x0e transfer failed.");
|
||||
|
||||
obuf[0] = 0x51;
|
||||
|
||||
if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
|
||||
err("command 0x51 transfer failed.");
|
||||
|
||||
d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
info("Attached DS3000!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
|
||||
|
@ -949,8 +1224,8 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
}
|
||||
|
||||
static struct rc_map_table rc_map_dw210x_table[] = {
|
||||
{ 0xf80a, KEY_Q }, /*power*/
|
||||
{ 0xf80c, KEY_M }, /*mute*/
|
||||
{ 0xf80a, KEY_POWER2 }, /*power*/
|
||||
{ 0xf80c, KEY_MUTE }, /*mute*/
|
||||
{ 0xf811, KEY_1 },
|
||||
{ 0xf812, KEY_2 },
|
||||
{ 0xf813, KEY_3 },
|
||||
|
@ -961,25 +1236,25 @@ static struct rc_map_table rc_map_dw210x_table[] = {
|
|||
{ 0xf818, KEY_8 },
|
||||
{ 0xf819, KEY_9 },
|
||||
{ 0xf810, KEY_0 },
|
||||
{ 0xf81c, KEY_PAGEUP }, /*ch+*/
|
||||
{ 0xf80f, KEY_PAGEDOWN }, /*ch-*/
|
||||
{ 0xf81a, KEY_O }, /*vol+*/
|
||||
{ 0xf80e, KEY_Z }, /*vol-*/
|
||||
{ 0xf804, KEY_R }, /*rec*/
|
||||
{ 0xf809, KEY_D }, /*fav*/
|
||||
{ 0xf808, KEY_BACKSPACE }, /*rewind*/
|
||||
{ 0xf807, KEY_A }, /*fast*/
|
||||
{ 0xf80b, KEY_P }, /*pause*/
|
||||
{ 0xf802, KEY_ESC }, /*cancel*/
|
||||
{ 0xf803, KEY_G }, /*tab*/
|
||||
{ 0xf81c, KEY_CHANNELUP }, /*ch+*/
|
||||
{ 0xf80f, KEY_CHANNELDOWN }, /*ch-*/
|
||||
{ 0xf81a, KEY_VOLUMEUP }, /*vol+*/
|
||||
{ 0xf80e, KEY_VOLUMEDOWN }, /*vol-*/
|
||||
{ 0xf804, KEY_RECORD }, /*rec*/
|
||||
{ 0xf809, KEY_FAVORITES }, /*fav*/
|
||||
{ 0xf808, KEY_REWIND }, /*rewind*/
|
||||
{ 0xf807, KEY_FASTFORWARD }, /*fast*/
|
||||
{ 0xf80b, KEY_PAUSE }, /*pause*/
|
||||
{ 0xf802, KEY_ESC }, /*cancel*/
|
||||
{ 0xf803, KEY_TAB }, /*tab*/
|
||||
{ 0xf800, KEY_UP }, /*up*/
|
||||
{ 0xf81f, KEY_ENTER }, /*ok*/
|
||||
{ 0xf801, KEY_DOWN }, /*down*/
|
||||
{ 0xf805, KEY_C }, /*cap*/
|
||||
{ 0xf806, KEY_S }, /*stop*/
|
||||
{ 0xf840, KEY_F }, /*full*/
|
||||
{ 0xf81e, KEY_W }, /*tvmode*/
|
||||
{ 0xf81b, KEY_B }, /*recall*/
|
||||
{ 0xf81f, KEY_OK }, /*ok*/
|
||||
{ 0xf801, KEY_DOWN }, /*down*/
|
||||
{ 0xf805, KEY_CAMERA }, /*cap*/
|
||||
{ 0xf806, KEY_STOP }, /*stop*/
|
||||
{ 0xf840, KEY_ZOOM }, /*full*/
|
||||
{ 0xf81e, KEY_TV }, /*tvmode*/
|
||||
{ 0xf81b, KEY_LAST }, /*recall*/
|
||||
};
|
||||
|
||||
static struct rc_map_table rc_map_tevii_table[] = {
|
||||
|
@ -1067,10 +1342,49 @@ static struct rc_map_table rc_map_tbs_table[] = {
|
|||
{ 0xf89b, KEY_MODE }
|
||||
};
|
||||
|
||||
static struct rc_map_table rc_map_su3000_table[] = {
|
||||
{ 0x25, KEY_POWER }, /* right-bottom Red */
|
||||
{ 0x0a, KEY_MUTE }, /* -/-- */
|
||||
{ 0x01, KEY_1 },
|
||||
{ 0x02, KEY_2 },
|
||||
{ 0x03, KEY_3 },
|
||||
{ 0x04, KEY_4 },
|
||||
{ 0x05, KEY_5 },
|
||||
{ 0x06, KEY_6 },
|
||||
{ 0x07, KEY_7 },
|
||||
{ 0x08, KEY_8 },
|
||||
{ 0x09, KEY_9 },
|
||||
{ 0x00, KEY_0 },
|
||||
{ 0x20, KEY_UP }, /* CH+ */
|
||||
{ 0x21, KEY_DOWN }, /* CH+ */
|
||||
{ 0x12, KEY_VOLUMEUP }, /* Brightness Up */
|
||||
{ 0x13, KEY_VOLUMEDOWN },/* Brightness Down */
|
||||
{ 0x1f, KEY_RECORD },
|
||||
{ 0x17, KEY_PLAY },
|
||||
{ 0x16, KEY_PAUSE },
|
||||
{ 0x0b, KEY_STOP },
|
||||
{ 0x27, KEY_FASTFORWARD },/* >> */
|
||||
{ 0x26, KEY_REWIND }, /* << */
|
||||
{ 0x0d, KEY_OK }, /* Mute */
|
||||
{ 0x11, KEY_LEFT }, /* VOL- */
|
||||
{ 0x10, KEY_RIGHT }, /* VOL+ */
|
||||
{ 0x29, KEY_BACK }, /* button under 9 */
|
||||
{ 0x2c, KEY_MENU }, /* TTX */
|
||||
{ 0x2b, KEY_EPG }, /* EPG */
|
||||
{ 0x1e, KEY_RED }, /* OSD */
|
||||
{ 0x0e, KEY_GREEN }, /* Window */
|
||||
{ 0x2d, KEY_YELLOW }, /* button under << */
|
||||
{ 0x0f, KEY_BLUE }, /* bottom yellow button */
|
||||
{ 0x14, KEY_AUDIO }, /* Snapshot */
|
||||
{ 0x38, KEY_TV }, /* TV/Radio */
|
||||
{ 0x0c, KEY_ESC } /* upper Red buttton */
|
||||
};
|
||||
|
||||
static struct rc_map_dvb_usb_table_table keys_tables[] = {
|
||||
{ rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) },
|
||||
{ rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) },
|
||||
{ rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) },
|
||||
{ rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) },
|
||||
};
|
||||
|
||||
static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
|
@ -1089,7 +1403,8 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) {
|
||||
keymap = keys_tables[ir_keymap - 1].rc_keys ;
|
||||
keymap_size = keys_tables[ir_keymap - 1].rc_keys_size;
|
||||
}
|
||||
} else if (ir_keymap > ARRAY_SIZE(keys_tables))
|
||||
return 0; /* none */
|
||||
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
|
||||
|
@ -1125,6 +1440,11 @@ static struct usb_device_id dw2102_table[] = {
|
|||
{USB_DEVICE(0x3011, USB_PID_PROF_1100)},
|
||||
{USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
|
||||
{USB_DEVICE(0x3034, 0x7500)},
|
||||
{USB_DEVICE(0x1f4d, 0x3000)},
|
||||
{USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
|
||||
{USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
|
||||
{USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
|
||||
{USB_DEVICE(0x1f4d, 0x3100)},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -1184,11 +1504,6 @@ static int dw2102_load_firmware(struct usb_device *dev,
|
|||
}
|
||||
/* init registers */
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case USB_PID_PROF_1100:
|
||||
s6x0_properties.rc.legacy.rc_map_table = rc_map_tbs_table;
|
||||
s6x0_properties.rc.legacy.rc_map_size =
|
||||
ARRAY_SIZE(rc_map_tbs_table);
|
||||
break;
|
||||
case USB_PID_TEVII_S650:
|
||||
dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table;
|
||||
dw2104_properties.rc.legacy.rc_map_size =
|
||||
|
@ -1271,8 +1586,6 @@ static struct dvb_usb_device_properties dw2102_properties = {
|
|||
.adapter = {
|
||||
{
|
||||
.frontend_attach = dw2102_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
|
@ -1324,8 +1637,6 @@ static struct dvb_usb_device_properties dw2104_properties = {
|
|||
.adapter = {
|
||||
{
|
||||
.frontend_attach = dw2104_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
/*.tuner_attach = dw2104_tuner_attach,*/
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
|
@ -1373,7 +1684,6 @@ static struct dvb_usb_device_properties dw3101_properties = {
|
|||
.adapter = {
|
||||
{
|
||||
.frontend_attach = dw3101_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
.tuner_attach = dw3101_tuner_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
|
@ -1399,6 +1709,7 @@ static struct dvb_usb_device_properties dw3101_properties = {
|
|||
static struct dvb_usb_device_properties s6x0_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.size_of_priv = sizeof(struct s6x0_state),
|
||||
.firmware = "dvb-usb-s630.fw",
|
||||
.no_reconnect = 1,
|
||||
|
||||
|
@ -1416,9 +1727,7 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
|||
.read_mac_address = s6x0_read_mac_address,
|
||||
.adapter = {
|
||||
{
|
||||
.frontend_attach = s6x0_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
.tuner_attach = NULL,
|
||||
.frontend_attach = zl100313_frontend_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
|
@ -1431,23 +1740,41 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
|||
},
|
||||
}
|
||||
},
|
||||
.num_device_descs = 3,
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"TeVii S630 USB",
|
||||
{&dw2102_table[6], NULL},
|
||||
{NULL},
|
||||
},
|
||||
{"Prof 1100 USB ",
|
||||
{&dw2102_table[7], NULL},
|
||||
{NULL},
|
||||
},
|
||||
{"TeVii S660 USB",
|
||||
{&dw2102_table[8], NULL},
|
||||
{NULL},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
struct dvb_usb_device_properties *p1100;
|
||||
static struct dvb_usb_device_description d1100 = {
|
||||
"Prof 1100 USB ",
|
||||
{&dw2102_table[7], NULL},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
struct dvb_usb_device_properties *s660;
|
||||
static struct dvb_usb_device_description d660 = {
|
||||
"TeVii S660 USB",
|
||||
{&dw2102_table[8], NULL},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_description d480_1 = {
|
||||
"TeVii S480.1 USB",
|
||||
{&dw2102_table[12], NULL},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_description d480_2 = {
|
||||
"TeVii S480.2 USB",
|
||||
{&dw2102_table[13], NULL},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
struct dvb_usb_device_properties *p7500;
|
||||
static struct dvb_usb_device_description d7500 = {
|
||||
"Prof 7500 USB DVB-S2",
|
||||
|
@ -1455,17 +1782,97 @@ static struct dvb_usb_device_description d7500 = {
|
|||
{NULL},
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties su3000_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.size_of_priv = sizeof(struct su3000_state),
|
||||
.power_ctrl = su3000_power_ctrl,
|
||||
.num_adapters = 1,
|
||||
.identify_state = su3000_identify_state,
|
||||
.i2c_algo = &su3000_i2c_algo,
|
||||
|
||||
.rc.legacy = {
|
||||
.rc_map_table = rc_map_su3000_table,
|
||||
.rc_map_size = ARRAY_SIZE(rc_map_su3000_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.read_mac_address = su3000_read_mac_address,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.adapter = {
|
||||
{
|
||||
.streaming_ctrl = su3000_streaming_ctrl,
|
||||
.frontend_attach = su3000_frontend_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
.num_device_descs = 3,
|
||||
.devices = {
|
||||
{ "SU3000HD DVB-S USB2.0",
|
||||
{ &dw2102_table[10], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Terratec Cinergy S2 USB HD",
|
||||
{ &dw2102_table[11], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "X3M TV SPC1400HD PCI",
|
||||
{ &dw2102_table[14], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static int dw2102_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
|
||||
p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!p7500)
|
||||
p1100 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!p1100)
|
||||
return -ENOMEM;
|
||||
/* copy default structure */
|
||||
memcpy(p7500, &s6x0_properties,
|
||||
memcpy(p1100, &s6x0_properties,
|
||||
sizeof(struct dvb_usb_device_properties));
|
||||
/* fill only different fields */
|
||||
p1100->firmware = "dvb-usb-p1100.fw";
|
||||
p1100->devices[0] = d1100;
|
||||
p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
|
||||
p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
|
||||
p1100->adapter->frontend_attach = stv0288_frontend_attach;
|
||||
|
||||
s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!s660) {
|
||||
kfree(p1100);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(s660, &s6x0_properties,
|
||||
sizeof(struct dvb_usb_device_properties));
|
||||
s660->firmware = "dvb-usb-s660.fw";
|
||||
s660->num_device_descs = 3;
|
||||
s660->devices[0] = d660;
|
||||
s660->devices[1] = d480_1;
|
||||
s660->devices[2] = d480_2;
|
||||
s660->adapter->frontend_attach = ds3000_frontend_attach;
|
||||
|
||||
p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!p7500) {
|
||||
kfree(p1100);
|
||||
kfree(s660);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(p7500, &s6x0_properties,
|
||||
sizeof(struct dvb_usb_device_properties));
|
||||
p7500->firmware = "dvb-usb-p7500.fw";
|
||||
p7500->devices[0] = d7500;
|
||||
p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
|
||||
|
@ -1480,8 +1887,14 @@ static int dw2102_probe(struct usb_interface *intf,
|
|||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &s6x0_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, p1100,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, s660,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, p7500,
|
||||
THIS_MODULE, NULL, adapter_nr))
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &su3000_properties,
|
||||
THIS_MODULE, NULL, adapter_nr))
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
|
@ -1514,7 +1927,8 @@ module_exit(dw2102_module_exit);
|
|||
MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
|
||||
MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
|
||||
" DVB-C 3101 USB2.0,"
|
||||
" TeVii S600, S630, S650, S660 USB2.0,"
|
||||
" Prof 1100, 7500 USB2.0 devices");
|
||||
" TeVii S600, S630, S650, S660, S480,"
|
||||
" Prof 1100, 7500 USB2.0,"
|
||||
" Geniatech SU3000 devices");
|
||||
MODULE_VERSION("0.1");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
*
|
||||
* DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395
|
||||
* LME2510C + LG TDQY-P001F
|
||||
* LME2510C + BS2F7HZ0194
|
||||
* LME2510 + LG TDQY-P001F
|
||||
* LME2510 + BS2F7HZ0194
|
||||
*
|
||||
* MVB7395 (LME2510C+SHARP:BS2F7HZ7395)
|
||||
* SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V)
|
||||
|
@ -12,20 +14,22 @@
|
|||
*
|
||||
* MVB0001F (LME2510C+LGTDQT-P001F)
|
||||
*
|
||||
* MV0194 (LME2510+SHARP:BS2F7HZ0194)
|
||||
* SHARP:BS2F7HZ0194 = (STV0299+IX2410)
|
||||
*
|
||||
* MVB0194 (LME2510C+SHARP0194)
|
||||
*
|
||||
* For firmware see Documentation/dvb/lmedm04.txt
|
||||
*
|
||||
* I2C addresses:
|
||||
* 0xd0 - STV0288 - Demodulator
|
||||
* 0xc0 - Sharp IX2505V - Tuner
|
||||
* --or--
|
||||
* --
|
||||
* 0x1c - TDA10086 - Demodulator
|
||||
* 0xc0 - TDA8263 - Tuner
|
||||
*
|
||||
* ***Please Note***
|
||||
* There are other variants of the DM04
|
||||
* ***NOT SUPPORTED***
|
||||
* MV0194 (LME2510+SHARP0194)
|
||||
* MVB0194 (LME2510C+SHARP0194)
|
||||
* --
|
||||
* 0xd0 - STV0299 - Demodulator
|
||||
* 0xc0 - IX2410 - Tuner
|
||||
*
|
||||
*
|
||||
* VID = 3344 PID LME2510=1122 LME2510C=1120
|
||||
|
@ -55,6 +59,9 @@
|
|||
*
|
||||
* QQbox suffers from noise on LNB voltage.
|
||||
*
|
||||
* LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system
|
||||
* with other tuners. After a cold reset streaming will not start.
|
||||
*
|
||||
* PID functions have been removed from this driver version due to
|
||||
* problems with different firmware and application versions.
|
||||
*/
|
||||
|
@ -69,6 +76,9 @@
|
|||
#include "tda10086.h"
|
||||
#include "stv0288.h"
|
||||
#include "ix2505v.h"
|
||||
#include "stv0299.h"
|
||||
#include "dvb-pll.h"
|
||||
#include "z0194a.h"
|
||||
|
||||
|
||||
|
||||
|
@ -96,8 +106,11 @@ MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG");
|
|||
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
#define TUNER_DEFAULT 0x0
|
||||
#define TUNER_LG 0x1
|
||||
#define TUNER_S7395 0x2
|
||||
#define TUNER_S0194 0x3
|
||||
|
||||
struct lme2510_state {
|
||||
u8 id;
|
||||
|
@ -191,7 +204,7 @@ static int lme2510_stream_restart(struct dvb_usb_device *d)
|
|||
rbuff, sizeof(rbuff));
|
||||
return ret;
|
||||
}
|
||||
static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u16 keypress)
|
||||
static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
|
||||
|
@ -237,7 +250,8 @@ static void lme2510_int_response(struct urb *lme_urb)
|
|||
case 0xaa:
|
||||
debug_data_snipet(1, "INT Remote data snipet in", ibuf);
|
||||
lme2510_remote_keypress(adap,
|
||||
(u16)(ibuf[4]<<8)+ibuf[5]);
|
||||
(u32)(ibuf[2] << 24) + (ibuf[3] << 16) +
|
||||
(ibuf[4] << 8) + ibuf[5]);
|
||||
break;
|
||||
case 0xbb:
|
||||
switch (st->tuner_config) {
|
||||
|
@ -249,6 +263,7 @@ static void lme2510_int_response(struct urb *lme_urb)
|
|||
st->time_key = ibuf[7];
|
||||
break;
|
||||
case TUNER_S7395:
|
||||
case TUNER_S0194:
|
||||
/* Tweak for earlier firmware*/
|
||||
if (ibuf[1] == 0x03) {
|
||||
if (ibuf[2] > 1)
|
||||
|
@ -364,6 +379,18 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|||
msleep(5);
|
||||
}
|
||||
break;
|
||||
case TUNER_S0194:
|
||||
if (wbuf[2] == 0xd0) {
|
||||
if (wbuf[3] == 0x1b) {
|
||||
st->signal_lock = rbuf[1];
|
||||
if ((st->stream_on & 1) &&
|
||||
(st->signal_lock & 0x8)) {
|
||||
lme2510_stream_restart(d);
|
||||
st->i2c_talk_onoff = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -423,6 +450,34 @@ static int lme2510_msg(struct dvb_usb_device *d,
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case TUNER_S0194:
|
||||
switch (wbuf[3]) {
|
||||
case 0x18:
|
||||
rbuf[0] = 0x55;
|
||||
rbuf[1] = (st->signal_level & 0x80)
|
||||
? 0 : (st->signal_level * 2);
|
||||
break;
|
||||
case 0x24:
|
||||
rbuf[0] = 0x55;
|
||||
rbuf[1] = st->signal_sn;
|
||||
break;
|
||||
case 0x1b:
|
||||
rbuf[0] = 0x55;
|
||||
rbuf[1] = st->signal_lock;
|
||||
break;
|
||||
case 0x19:
|
||||
case 0x25:
|
||||
case 0x1e:
|
||||
case 0x1d:
|
||||
rbuf[0] = 0x55;
|
||||
rbuf[1] = 0x00;
|
||||
break;
|
||||
default:
|
||||
lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
|
||||
st->i2c_talk_onoff = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -517,17 +572,14 @@ static int lme2510_identify_state(struct usb_device *udev,
|
|||
struct dvb_usb_device_description **desc,
|
||||
int *cold)
|
||||
{
|
||||
if (lme2510_return_status(udev) == 0x44)
|
||||
*cold = 1;
|
||||
else
|
||||
*cold = 0;
|
||||
*cold = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
struct lme2510_state *st = adap->dev->priv;
|
||||
static u8 clear_reg_3[] = LME_CLEAR_PID;
|
||||
static u8 clear_reg_3[] = LME_CLEAR_PID;
|
||||
static u8 rbuf[1];
|
||||
int ret = 0, rlen = sizeof(rbuf);
|
||||
|
||||
|
@ -658,9 +710,6 @@ static int lme2510_download_firmware(struct usb_device *dev,
|
|||
return (ret < 0) ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
/* Default firmware for LME2510C */
|
||||
char lme_firmware[50] = "dvb-usb-lme2510c-s7395.fw";
|
||||
|
||||
static void lme_coldreset(struct usb_device *dev)
|
||||
{
|
||||
int ret = 0, len_in;
|
||||
|
@ -678,49 +727,83 @@ static void lme_coldreset(struct usb_device *dev)
|
|||
static int lme_firmware_switch(struct usb_device *udev, int cold)
|
||||
{
|
||||
const struct firmware *fw = NULL;
|
||||
char lme2510c_s7395[] = "dvb-usb-lme2510c-s7395.fw";
|
||||
char lme2510c_lg[] = "dvb-usb-lme2510c-lg.fw";
|
||||
char *firm_msg[] = {"Loading", "Switching to"};
|
||||
int ret;
|
||||
const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw";
|
||||
const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw";
|
||||
const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw";
|
||||
const char fw_lg[] = "dvb-usb-lme2510-lg.fw";
|
||||
const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw";
|
||||
const char *fw_lme;
|
||||
int ret, cold_fw;
|
||||
|
||||
cold = (cold > 0) ? (cold & 1) : 0;
|
||||
|
||||
if (udev->descriptor.idProduct == 0x1122)
|
||||
return 0;
|
||||
cold_fw = !cold;
|
||||
|
||||
switch (dvb_usb_lme2510_firmware) {
|
||||
case 0:
|
||||
default:
|
||||
memcpy(&lme_firmware, lme2510c_s7395, sizeof(lme2510c_s7395));
|
||||
ret = request_firmware(&fw, lme_firmware, &udev->dev);
|
||||
if (ret == 0) {
|
||||
info("FRM %s S7395 Firmware", firm_msg[cold]);
|
||||
break;
|
||||
}
|
||||
if (cold == 0)
|
||||
dvb_usb_lme2510_firmware = 1;
|
||||
else
|
||||
if (udev->descriptor.idProduct == 0x1122) {
|
||||
switch (dvb_usb_lme2510_firmware) {
|
||||
default:
|
||||
dvb_usb_lme2510_firmware = TUNER_S0194;
|
||||
case TUNER_S0194:
|
||||
fw_lme = fw_s0194;
|
||||
ret = request_firmware(&fw, fw_lme, &udev->dev);
|
||||
if (ret == 0) {
|
||||
cold = 0;/*lme2510-s0194 cannot cold reset*/
|
||||
break;
|
||||
}
|
||||
dvb_usb_lme2510_firmware = TUNER_LG;
|
||||
case TUNER_LG:
|
||||
fw_lme = fw_lg;
|
||||
ret = request_firmware(&fw, fw_lme, &udev->dev);
|
||||
if (ret == 0)
|
||||
break;
|
||||
info("FRM No Firmware Found - please install");
|
||||
dvb_usb_lme2510_firmware = TUNER_DEFAULT;
|
||||
cold = 0;
|
||||
case 1:
|
||||
memcpy(&lme_firmware, lme2510c_lg, sizeof(lme2510c_lg));
|
||||
ret = request_firmware(&fw, lme_firmware, &udev->dev);
|
||||
if (ret == 0) {
|
||||
info("FRM %s LG Firmware", firm_msg[cold]);
|
||||
cold_fw = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (dvb_usb_lme2510_firmware) {
|
||||
default:
|
||||
dvb_usb_lme2510_firmware = TUNER_S7395;
|
||||
case TUNER_S7395:
|
||||
fw_lme = fw_c_s7395;
|
||||
ret = request_firmware(&fw, fw_lme, &udev->dev);
|
||||
if (ret == 0)
|
||||
break;
|
||||
dvb_usb_lme2510_firmware = TUNER_LG;
|
||||
case TUNER_LG:
|
||||
fw_lme = fw_c_lg;
|
||||
ret = request_firmware(&fw, fw_lme, &udev->dev);
|
||||
if (ret == 0)
|
||||
break;
|
||||
dvb_usb_lme2510_firmware = TUNER_S0194;
|
||||
case TUNER_S0194:
|
||||
fw_lme = fw_c_s0194;
|
||||
ret = request_firmware(&fw, fw_lme, &udev->dev);
|
||||
if (ret == 0)
|
||||
break;
|
||||
info("FRM No Firmware Found - please install");
|
||||
dvb_usb_lme2510_firmware = TUNER_DEFAULT;
|
||||
cold = 0;
|
||||
cold_fw = 0;
|
||||
break;
|
||||
}
|
||||
info("FRM No Firmware Found - please install");
|
||||
dvb_usb_lme2510_firmware = 0;
|
||||
cold = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
if (cold_fw) {
|
||||
info("FRM Loading %s file", fw_lme);
|
||||
ret = lme2510_download_firmware(udev, fw);
|
||||
}
|
||||
|
||||
if (cold) {
|
||||
info("FRM Changing to %s firmware", fw_lme);
|
||||
lme_coldreset(udev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -758,6 +841,18 @@ static struct ix2505v_config lme_tuner = {
|
|||
.tuner_chargepump = 0x3,
|
||||
};
|
||||
|
||||
static struct stv0299_config sharp_z0194_config = {
|
||||
.demod_address = 0xd0,
|
||||
.inittab = sharp_z0194a_inittab,
|
||||
.mclk = 88000000UL,
|
||||
.invert = 0,
|
||||
.skip_reinit = 0,
|
||||
.lock_output = STV0299_LOCKOUTPUT_1,
|
||||
.volt13_op0_op1 = STV0299_VOLT13_OP1,
|
||||
.min_delay_ms = 100,
|
||||
.set_symbol_rate = sharp_z0194a_set_symbol_rate,
|
||||
};
|
||||
|
||||
static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
|
||||
fe_sec_voltage_t voltage)
|
||||
{
|
||||
|
@ -793,7 +888,8 @@ static int lme_name(struct dvb_usb_adapter *adap)
|
|||
{
|
||||
struct lme2510_state *st = adap->dev->priv;
|
||||
const char *desc = adap->dev->desc->name;
|
||||
char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395"};
|
||||
char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
|
||||
" SHARP:BS2F7HZ0194"};
|
||||
char *name = adap->fe->ops.info.name;
|
||||
|
||||
strlcpy(name, desc, 128);
|
||||
|
@ -820,26 +916,40 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
st->i2c_tuner_gate_r = 4;
|
||||
st->i2c_tuner_addr = 0xc0;
|
||||
st->tuner_config = TUNER_LG;
|
||||
if (dvb_usb_lme2510_firmware != 1) {
|
||||
dvb_usb_lme2510_firmware = 1;
|
||||
if (dvb_usb_lme2510_firmware != TUNER_LG) {
|
||||
dvb_usb_lme2510_firmware = TUNER_LG;
|
||||
ret = lme_firmware_switch(adap->dev->udev, 1);
|
||||
} else /*stops LG/Sharp multi tuner problems*/
|
||||
dvb_usb_lme2510_firmware = 0;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
st->i2c_gate = 4;
|
||||
adap->fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe) {
|
||||
info("FE Found Stv0299");
|
||||
st->i2c_tuner_gate_w = 4;
|
||||
st->i2c_tuner_gate_r = 5;
|
||||
st->i2c_tuner_addr = 0xc0;
|
||||
st->tuner_config = TUNER_S0194;
|
||||
if (dvb_usb_lme2510_firmware != TUNER_S0194) {
|
||||
dvb_usb_lme2510_firmware = TUNER_S0194;
|
||||
ret = lme_firmware_switch(adap->dev->udev, 1);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
st->i2c_gate = 5;
|
||||
adap->fe = dvb_attach(stv0288_attach, &lme_config,
|
||||
&adap->dev->i2c_adap);
|
||||
|
||||
if (adap->fe) {
|
||||
info("FE Found Stv0288");
|
||||
st->i2c_tuner_gate_w = 4;
|
||||
st->i2c_tuner_gate_r = 5;
|
||||
st->i2c_tuner_addr = 0xc0;
|
||||
st->tuner_config = TUNER_S7395;
|
||||
if (dvb_usb_lme2510_firmware != 0) {
|
||||
dvb_usb_lme2510_firmware = 0;
|
||||
if (dvb_usb_lme2510_firmware != TUNER_S7395) {
|
||||
dvb_usb_lme2510_firmware = TUNER_S7395;
|
||||
ret = lme_firmware_switch(adap->dev->udev, 1);
|
||||
}
|
||||
} else {
|
||||
|
@ -847,6 +957,7 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
end: if (ret) {
|
||||
kfree(adap->fe);
|
||||
adap->fe = NULL;
|
||||
|
@ -855,14 +966,13 @@ end: if (ret) {
|
|||
|
||||
adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
|
||||
ret = lme_name(adap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct lme2510_state *st = adap->dev->priv;
|
||||
char *tun_msg[] = {"", "TDA8263", "IX2505V"};
|
||||
char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA"};
|
||||
int ret = 0;
|
||||
|
||||
switch (st->tuner_config) {
|
||||
|
@ -876,6 +986,11 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
|
|||
&adap->dev->i2c_adap))
|
||||
ret = st->tuner_config;
|
||||
break;
|
||||
case TUNER_S0194:
|
||||
if (dvb_attach(dvb_pll_attach , adap->fe, 0xc0,
|
||||
&adap->dev->i2c_adap, DVB_PLL_OPERA1))
|
||||
ret = st->tuner_config;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -936,7 +1051,10 @@ static int lme2510_probe(struct usb_interface *intf,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
lme_firmware_switch(udev, 0);
|
||||
if (lme2510_return_status(udev) == 0x44) {
|
||||
lme_firmware_switch(udev, 0);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (0 == dvb_usb_device_init(intf, &lme2510_properties,
|
||||
THIS_MODULE, NULL, adapter_nr)) {
|
||||
|
@ -964,10 +1082,6 @@ MODULE_DEVICE_TABLE(usb, lme2510_table);
|
|||
|
||||
static struct dvb_usb_device_properties lme2510_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.download_firmware = lme2510_download_firmware,
|
||||
.firmware = "dvb-usb-lme2510-lg.fw",
|
||||
|
||||
.size_of_priv = sizeof(struct lme2510_state),
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
@ -1004,9 +1118,6 @@ static struct dvb_usb_device_properties lme2510_properties = {
|
|||
|
||||
static struct dvb_usb_device_properties lme2510c_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.download_firmware = lme2510_download_firmware,
|
||||
.firmware = (const char *)&lme_firmware,
|
||||
.size_of_priv = sizeof(struct lme2510_state),
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
@ -1109,5 +1220,5 @@ module_exit(lme2510_module_exit);
|
|||
|
||||
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
|
||||
MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
|
||||
MODULE_VERSION("1.75");
|
||||
MODULE_VERSION("1.80");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -342,23 +342,22 @@ static struct rc_map_table rc_map_opera1_table[] = {
|
|||
{0x49b6, KEY_8},
|
||||
{0x05fa, KEY_9},
|
||||
{0x45ba, KEY_0},
|
||||
{0x09f6, KEY_UP}, /*chanup */
|
||||
{0x1be5, KEY_DOWN}, /*chandown */
|
||||
{0x5da3, KEY_LEFT}, /*voldown */
|
||||
{0x5fa1, KEY_RIGHT}, /*volup */
|
||||
{0x07f8, KEY_SPACE}, /*tab */
|
||||
{0x1fe1, KEY_ENTER}, /*play ok */
|
||||
{0x1be4, KEY_Z}, /*zoom */
|
||||
{0x59a6, KEY_M}, /*mute */
|
||||
{0x5ba5, KEY_F}, /*tv/f */
|
||||
{0x19e7, KEY_R}, /*rec */
|
||||
{0x01fe, KEY_S}, /*Stop */
|
||||
{0x03fd, KEY_P}, /*pause */
|
||||
{0x03fc, KEY_W}, /*<- -> */
|
||||
{0x07f9, KEY_C}, /*capture */
|
||||
{0x47b9, KEY_Q}, /*exit */
|
||||
{0x43bc, KEY_O}, /*power */
|
||||
|
||||
{0x09f6, KEY_CHANNELUP}, /*chanup */
|
||||
{0x1be5, KEY_CHANNELDOWN}, /*chandown */
|
||||
{0x5da3, KEY_VOLUMEDOWN}, /*voldown */
|
||||
{0x5fa1, KEY_VOLUMEUP}, /*volup */
|
||||
{0x07f8, KEY_SPACE}, /*tab */
|
||||
{0x1fe1, KEY_OK}, /*play ok */
|
||||
{0x1be4, KEY_ZOOM}, /*zoom */
|
||||
{0x59a6, KEY_MUTE}, /*mute */
|
||||
{0x5ba5, KEY_RADIO}, /*tv/f */
|
||||
{0x19e7, KEY_RECORD}, /*rec */
|
||||
{0x01fe, KEY_STOP}, /*Stop */
|
||||
{0x03fd, KEY_PAUSE}, /*pause */
|
||||
{0x03fc, KEY_SCREEN}, /*<- -> */
|
||||
{0x07f9, KEY_CAMERA}, /*capture */
|
||||
{0x47b9, KEY_ESC}, /*exit */
|
||||
{0x43bc, KEY_POWER2}, /*power */
|
||||
};
|
||||
|
||||
static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
|
||||
|
|
|
@ -0,0 +1,807 @@
|
|||
/*
|
||||
* Linux driver for Technisat DVB-S/S2 USB 2.0 device
|
||||
*
|
||||
* Copyright (C) 2010 Patrick Boettcher,
|
||||
* Kernel Labs Inc. PO Box 745, St James, NY 11780
|
||||
*
|
||||
* Development was sponsored by Technisat Digital UK Limited, whose
|
||||
* registered office is Witan Gate House 500 - 600 Witan Gate West,
|
||||
* Milton Keynes, MK9 1SH
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS PROGRAM IS PROVIDED "AS IS" AND BOTH THE COPYRIGHT HOLDER AND
|
||||
* TECHNISAT DIGITAL UK LTD DISCLAIM ALL WARRANTIES WITH REGARD TO
|
||||
* THIS PROGRAM INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. NEITHER THE COPYRIGHT HOLDER
|
||||
* NOR TECHNISAT DIGITAL UK LIMITED SHALL BE LIABLE FOR ANY SPECIAL,
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS PROGRAM. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "technisat-usb2"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#include "stv6110x.h"
|
||||
#include "stv090x.h"
|
||||
|
||||
/* module parameters */
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug,
|
||||
"set debugging level (bit-mask: 1=info,2=eeprom,4=i2c,8=rc)." \
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
/* disables all LED control command and
|
||||
* also does not start the signal polling thread */
|
||||
static int disable_led_control;
|
||||
module_param(disable_led_control, int, 0444);
|
||||
MODULE_PARM_DESC(disable_led_control,
|
||||
"disable LED control of the device "
|
||||
"(default: 0 - LED control is active).");
|
||||
|
||||
/* device private data */
|
||||
struct technisat_usb2_state {
|
||||
struct dvb_usb_device *dev;
|
||||
struct delayed_work green_led_work;
|
||||
u8 power_state;
|
||||
|
||||
u16 last_scan_code;
|
||||
};
|
||||
|
||||
/* debug print helpers */
|
||||
#define deb_info(args...) dprintk(debug, 0x01, args)
|
||||
#define deb_eeprom(args...) dprintk(debug, 0x02, args)
|
||||
#define deb_i2c(args...) dprintk(debug, 0x04, args)
|
||||
#define deb_rc(args...) dprintk(debug, 0x08, args)
|
||||
|
||||
/* vendor requests */
|
||||
#define SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST 0xB3
|
||||
#define SET_FRONT_END_RESET_VENDOR_REQUEST 0xB4
|
||||
#define GET_VERSION_INFO_VENDOR_REQUEST 0xB5
|
||||
#define SET_GREEN_LED_VENDOR_REQUEST 0xB6
|
||||
#define SET_RED_LED_VENDOR_REQUEST 0xB7
|
||||
#define GET_IR_DATA_VENDOR_REQUEST 0xB8
|
||||
#define SET_LED_TIMER_DIVIDER_VENDOR_REQUEST 0xB9
|
||||
#define SET_USB_REENUMERATION 0xBA
|
||||
|
||||
/* i2c-access methods */
|
||||
#define I2C_SPEED_100KHZ_BIT 0x40
|
||||
|
||||
#define I2C_STATUS_NAK 7
|
||||
#define I2C_STATUS_OK 8
|
||||
|
||||
static int technisat_usb2_i2c_access(struct usb_device *udev,
|
||||
u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
|
||||
{
|
||||
u8 b[64];
|
||||
int ret, actual_length;
|
||||
|
||||
deb_i2c("i2c-access: %02x, tx: ", device_addr);
|
||||
debug_dump(tx, txlen, deb_i2c);
|
||||
deb_i2c(" ");
|
||||
|
||||
if (txlen > 62) {
|
||||
err("i2c TX buffer can't exceed 62 bytes (dev 0x%02x)",
|
||||
device_addr);
|
||||
txlen = 62;
|
||||
}
|
||||
if (rxlen > 62) {
|
||||
err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)",
|
||||
device_addr);
|
||||
txlen = 62;
|
||||
}
|
||||
|
||||
b[0] = I2C_SPEED_100KHZ_BIT;
|
||||
b[1] = device_addr << 1;
|
||||
|
||||
if (rx != NULL) {
|
||||
b[0] |= rxlen;
|
||||
b[1] |= 1;
|
||||
}
|
||||
|
||||
memcpy(&b[2], tx, txlen);
|
||||
ret = usb_bulk_msg(udev,
|
||||
usb_sndbulkpipe(udev, 0x01),
|
||||
b, 2 + txlen,
|
||||
NULL, 1000);
|
||||
|
||||
if (ret < 0) {
|
||||
err("i2c-error: out failed %02x = %d", device_addr, ret);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = usb_bulk_msg(udev,
|
||||
usb_rcvbulkpipe(udev, 0x01),
|
||||
b, 64, &actual_length, 1000);
|
||||
if (ret < 0) {
|
||||
err("i2c-error: in failed %02x = %d", device_addr, ret);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (b[0] != I2C_STATUS_OK) {
|
||||
err("i2c-error: %02x = %d", device_addr, b[0]);
|
||||
/* handle tuner-i2c-nak */
|
||||
if (!(b[0] == I2C_STATUS_NAK &&
|
||||
device_addr == 0x60
|
||||
/* && device_is_technisat_usb2 */))
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
deb_i2c("status: %d, ", b[0]);
|
||||
|
||||
if (rx != NULL) {
|
||||
memcpy(rx, &b[2], rxlen);
|
||||
|
||||
deb_i2c("rx (%d): ", rxlen);
|
||||
debug_dump(rx, rxlen, deb_i2c);
|
||||
}
|
||||
|
||||
deb_i2c("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
int num)
|
||||
{
|
||||
int ret = 0, i;
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
|
||||
/* Ensure nobody else hits the i2c bus while we're sending our
|
||||
sequence of messages, (such as the remote control thread) */
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (i+1 < num && msg[i+1].flags & I2C_M_RD) {
|
||||
ret = technisat_usb2_i2c_access(d->udev, msg[i+1].addr,
|
||||
msg[i].buf, msg[i].len,
|
||||
msg[i+1].buf, msg[i+1].len);
|
||||
if (ret != 0)
|
||||
break;
|
||||
i++;
|
||||
} else {
|
||||
ret = technisat_usb2_i2c_access(d->udev, msg[i].addr,
|
||||
msg[i].buf, msg[i].len,
|
||||
NULL, 0);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
ret = i;
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 technisat_usb2_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm technisat_usb2_i2c_algo = {
|
||||
.master_xfer = technisat_usb2_i2c_xfer,
|
||||
.functionality = technisat_usb2_i2c_func,
|
||||
};
|
||||
|
||||
#if 0
|
||||
static void technisat_usb2_frontend_reset(struct usb_device *udev)
|
||||
{
|
||||
usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
SET_FRONT_END_RESET_VENDOR_REQUEST,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
10, 0,
|
||||
NULL, 0, 500);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* LED control */
|
||||
enum technisat_usb2_led_state {
|
||||
LED_OFF,
|
||||
LED_BLINK,
|
||||
LED_ON,
|
||||
LED_UNDEFINED
|
||||
};
|
||||
|
||||
static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum technisat_usb2_led_state state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
u8 led[8] = {
|
||||
red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
|
||||
0
|
||||
};
|
||||
|
||||
if (disable_led_control && state != LED_OFF)
|
||||
return 0;
|
||||
|
||||
switch (state) {
|
||||
case LED_ON:
|
||||
led[1] = 0x82;
|
||||
break;
|
||||
case LED_BLINK:
|
||||
led[1] = 0x82;
|
||||
if (red) {
|
||||
led[2] = 0x02;
|
||||
led[3] = 10;
|
||||
led[4] = 10;
|
||||
} else {
|
||||
led[2] = 0xff;
|
||||
led[3] = 50;
|
||||
led[4] = 50;
|
||||
}
|
||||
led[5] = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
case LED_OFF:
|
||||
led[1] = 0x80;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
|
||||
red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
0, 0,
|
||||
led, sizeof(led), 500);
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green)
|
||||
{
|
||||
int ret;
|
||||
u8 b = 0;
|
||||
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
|
||||
SET_LED_TIMER_DIVIDER_VENDOR_REQUEST,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
(red << 8) | green, 0,
|
||||
&b, 1, 500);
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void technisat_usb2_green_led_control(struct work_struct *work)
|
||||
{
|
||||
struct technisat_usb2_state *state =
|
||||
container_of(work, struct technisat_usb2_state, green_led_work.work);
|
||||
struct dvb_frontend *fe = state->dev->adapter[0].fe;
|
||||
|
||||
if (state->power_state == 0)
|
||||
goto schedule;
|
||||
|
||||
if (fe != NULL) {
|
||||
enum fe_status status;
|
||||
|
||||
if (fe->ops.read_status(fe, &status) != 0)
|
||||
goto schedule;
|
||||
|
||||
if (status & FE_HAS_LOCK) {
|
||||
u32 ber;
|
||||
|
||||
if (fe->ops.read_ber(fe, &ber) != 0)
|
||||
goto schedule;
|
||||
|
||||
if (ber > 1000)
|
||||
technisat_usb2_set_led(state->dev, 0, LED_BLINK);
|
||||
else
|
||||
technisat_usb2_set_led(state->dev, 0, LED_ON);
|
||||
} else
|
||||
technisat_usb2_set_led(state->dev, 0, LED_OFF);
|
||||
}
|
||||
|
||||
schedule:
|
||||
schedule_delayed_work(&state->green_led_work,
|
||||
msecs_to_jiffies(500));
|
||||
}
|
||||
|
||||
/* method to find out whether the firmware has to be downloaded or not */
|
||||
static int technisat_usb2_identify_state(struct usb_device *udev,
|
||||
struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc, int *cold)
|
||||
{
|
||||
int ret;
|
||||
u8 version[3];
|
||||
|
||||
/* first select the interface */
|
||||
if (usb_set_interface(udev, 0, 1) != 0)
|
||||
err("could not set alternate setting to 0");
|
||||
else
|
||||
info("set alternate setting");
|
||||
|
||||
*cold = 0; /* by default do not download a firmware - just in case something is wrong */
|
||||
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
GET_VERSION_INFO_VENDOR_REQUEST,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN,
|
||||
0, 0,
|
||||
version, sizeof(version), 500);
|
||||
|
||||
if (ret < 0)
|
||||
*cold = 1;
|
||||
else {
|
||||
info("firmware version: %d.%d", version[1], version[2]);
|
||||
*cold = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* power control */
|
||||
static int technisat_usb2_power_ctrl(struct dvb_usb_device *d, int level)
|
||||
{
|
||||
struct technisat_usb2_state *state = d->priv;
|
||||
|
||||
state->power_state = level;
|
||||
|
||||
if (disable_led_control)
|
||||
return 0;
|
||||
|
||||
/* green led is turned off in any case - will be turned on when tuning */
|
||||
technisat_usb2_set_led(d, 0, LED_OFF);
|
||||
/* red led is turned on all the time */
|
||||
technisat_usb2_set_led(d, 1, LED_ON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mac address reading - from the eeprom */
|
||||
#if 0
|
||||
static void technisat_usb2_eeprom_dump(struct dvb_usb_device *d)
|
||||
{
|
||||
u8 reg;
|
||||
u8 b[16];
|
||||
int i, j;
|
||||
|
||||
/* full EEPROM dump */
|
||||
for (j = 0; j < 256 * 4; j += 16) {
|
||||
reg = j;
|
||||
if (technisat_usb2_i2c_access(d->udev, 0x50 + j / 256, ®, 1, b, 16) != 0)
|
||||
break;
|
||||
|
||||
deb_eeprom("EEPROM: %01x%02x: ", j / 256, reg);
|
||||
for (i = 0; i < 16; i++)
|
||||
deb_eeprom("%02x ", b[i]);
|
||||
deb_eeprom("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static u8 technisat_usb2_calc_lrc(const u8 *b, u16 length)
|
||||
{
|
||||
u8 lrc = 0;
|
||||
while (--length)
|
||||
lrc ^= *b++;
|
||||
return lrc;
|
||||
}
|
||||
|
||||
static int technisat_usb2_eeprom_lrc_read(struct dvb_usb_device *d,
|
||||
u16 offset, u8 *b, u16 length, u8 tries)
|
||||
{
|
||||
u8 bo = offset & 0xff;
|
||||
struct i2c_msg msg[] = {
|
||||
{
|
||||
.addr = 0x50 | ((offset >> 8) & 0x3),
|
||||
.buf = &bo,
|
||||
.len = 1
|
||||
}, {
|
||||
.addr = 0x50 | ((offset >> 8) & 0x3),
|
||||
.flags = I2C_M_RD,
|
||||
.buf = b,
|
||||
.len = length
|
||||
}
|
||||
};
|
||||
|
||||
while (tries--) {
|
||||
int status;
|
||||
|
||||
if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
|
||||
break;
|
||||
|
||||
status =
|
||||
technisat_usb2_calc_lrc(b, length - 1) == b[length - 1];
|
||||
|
||||
if (status)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
#define EEPROM_MAC_START 0x3f8
|
||||
#define EEPROM_MAC_TOTAL 8
|
||||
static int technisat_usb2_read_mac_address(struct dvb_usb_device *d,
|
||||
u8 mac[])
|
||||
{
|
||||
u8 buf[EEPROM_MAC_TOTAL];
|
||||
|
||||
if (technisat_usb2_eeprom_lrc_read(d, EEPROM_MAC_START,
|
||||
buf, EEPROM_MAC_TOTAL, 4) != 0)
|
||||
return -ENODEV;
|
||||
|
||||
memcpy(mac, buf, 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* frontend attach */
|
||||
static int technisat_usb2_set_voltage(struct dvb_frontend *fe,
|
||||
fe_sec_voltage_t voltage)
|
||||
{
|
||||
int i;
|
||||
u8 gpio[3] = { 0 }; /* 0 = 2, 1 = 3, 2 = 4 */
|
||||
|
||||
gpio[2] = 1; /* high - voltage ? */
|
||||
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
gpio[0] = 1;
|
||||
break;
|
||||
case SEC_VOLTAGE_18:
|
||||
gpio[0] = 1;
|
||||
gpio[1] = 1;
|
||||
break;
|
||||
default:
|
||||
case SEC_VOLTAGE_OFF:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
if (stv090x_set_gpio(fe, i+2, 0, gpio[i], 0) != 0)
|
||||
return -EREMOTEIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct stv090x_config technisat_usb2_stv090x_config = {
|
||||
.device = STV0903,
|
||||
.demod_mode = STV090x_SINGLE,
|
||||
.clk_mode = STV090x_CLK_EXT,
|
||||
|
||||
.xtal = 8000000,
|
||||
.address = 0x68,
|
||||
|
||||
.ts1_mode = STV090x_TSMODE_DVBCI,
|
||||
.ts1_clk = 13400000,
|
||||
.ts1_tei = 1,
|
||||
|
||||
.repeater_level = STV090x_RPTLEVEL_64,
|
||||
|
||||
.tuner_bbgain = 6,
|
||||
};
|
||||
|
||||
static struct stv6110x_config technisat_usb2_stv6110x_config = {
|
||||
.addr = 0x60,
|
||||
.refclk = 16000000,
|
||||
.clk_div = 2,
|
||||
};
|
||||
|
||||
static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
|
||||
{
|
||||
struct usb_device *udev = a->dev->udev;
|
||||
int ret;
|
||||
|
||||
a->fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
|
||||
&a->dev->i2c_adap, STV090x_DEMODULATOR_0);
|
||||
|
||||
if (a->fe) {
|
||||
struct stv6110x_devctl *ctl;
|
||||
|
||||
ctl = dvb_attach(stv6110x_attach,
|
||||
a->fe,
|
||||
&technisat_usb2_stv6110x_config,
|
||||
&a->dev->i2c_adap);
|
||||
|
||||
if (ctl) {
|
||||
technisat_usb2_stv090x_config.tuner_init = ctl->tuner_init;
|
||||
technisat_usb2_stv090x_config.tuner_sleep = ctl->tuner_sleep;
|
||||
technisat_usb2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode;
|
||||
technisat_usb2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
|
||||
technisat_usb2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
|
||||
technisat_usb2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
|
||||
technisat_usb2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
|
||||
technisat_usb2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain;
|
||||
technisat_usb2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain;
|
||||
technisat_usb2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk;
|
||||
technisat_usb2_stv090x_config.tuner_get_status = ctl->tuner_get_status;
|
||||
|
||||
/* call the init function once to initialize
|
||||
tuner's clock output divider and demod's
|
||||
master clock */
|
||||
if (a->fe->ops.init)
|
||||
a->fe->ops.init(a->fe);
|
||||
|
||||
if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
0, 0,
|
||||
NULL, 0, 500);
|
||||
mutex_unlock(&a->dev->i2c_mutex);
|
||||
|
||||
if (ret != 0)
|
||||
err("could not set IF_CLK to external");
|
||||
|
||||
a->fe->ops.set_voltage = technisat_usb2_set_voltage;
|
||||
|
||||
/* if everything was successful assign a nice name to the frontend */
|
||||
strlcpy(a->fe->ops.info.name, a->dev->desc->name,
|
||||
sizeof(a->fe->ops.info.name));
|
||||
} else {
|
||||
dvb_frontend_detach(a->fe);
|
||||
a->fe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
technisat_usb2_set_led_timer(a->dev, 1, 1);
|
||||
|
||||
return a->fe == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
/* Remote control */
|
||||
|
||||
/* the device is giving providing raw IR-signals to the host mapping
|
||||
* it only to one remote control is just the default implementation
|
||||
*/
|
||||
#define NOMINAL_IR_BIT_TRANSITION_TIME_US 889
|
||||
#define NOMINAL_IR_BIT_TIME_US (2 * NOMINAL_IR_BIT_TRANSITION_TIME_US)
|
||||
|
||||
#define FIRMWARE_CLOCK_TICK 83333
|
||||
#define FIRMWARE_CLOCK_DIVISOR 256
|
||||
|
||||
#define IR_PERCENT_TOLERANCE 15
|
||||
|
||||
#define NOMINAL_IR_BIT_TRANSITION_TICKS ((NOMINAL_IR_BIT_TRANSITION_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
|
||||
#define NOMINAL_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICKS / FIRMWARE_CLOCK_DIVISOR)
|
||||
|
||||
#define NOMINAL_IR_BIT_TIME_TICKS ((NOMINAL_IR_BIT_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
|
||||
#define NOMINAL_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICKS / FIRMWARE_CLOCK_DIVISOR)
|
||||
|
||||
#define MINIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT - ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
|
||||
#define MAXIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT + ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
|
||||
|
||||
#define MINIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT - ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
|
||||
#define MAXIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT + ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
|
||||
|
||||
static int technisat_usb2_get_ir(struct dvb_usb_device *d)
|
||||
{
|
||||
u8 buf[62], *b;
|
||||
int ret;
|
||||
struct ir_raw_event ev;
|
||||
|
||||
buf[0] = GET_IR_DATA_VENDOR_REQUEST;
|
||||
buf[1] = 0x08;
|
||||
buf[2] = 0x8f;
|
||||
buf[3] = MINIMUM_IR_BIT_TRANSITION_TICK_COUNT;
|
||||
buf[4] = MAXIMUM_IR_BIT_TIME_TICK_COUNT;
|
||||
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
|
||||
GET_IR_DATA_VENDOR_REQUEST,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
0, 0,
|
||||
buf, 5, 500);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
|
||||
buf[1] = 0;
|
||||
buf[2] = 0;
|
||||
ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
|
||||
GET_IR_DATA_VENDOR_REQUEST,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN,
|
||||
0x8080, 0,
|
||||
buf, sizeof(buf), 500);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret == 1)
|
||||
return 0; /* no key pressed */
|
||||
|
||||
/* decoding */
|
||||
b = buf+1;
|
||||
|
||||
#if 0
|
||||
deb_rc("RC: %d ", ret);
|
||||
debug_dump(b, ret, deb_rc);
|
||||
#endif
|
||||
|
||||
ev.pulse = 0;
|
||||
while (1) {
|
||||
ev.pulse = !ev.pulse;
|
||||
ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000;
|
||||
ir_raw_event_store(d->rc_dev, &ev);
|
||||
|
||||
b++;
|
||||
if (*b == 0xff) {
|
||||
ev.pulse = 0;
|
||||
ev.duration = 888888*2;
|
||||
ir_raw_event_store(d->rc_dev, &ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ir_raw_event_handle(d->rc_dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int technisat_usb2_rc_query(struct dvb_usb_device *d)
|
||||
{
|
||||
int ret = technisat_usb2_get_ir(d);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
if (!disable_led_control)
|
||||
technisat_usb2_set_led(d, 1, LED_BLINK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DVB-USB and USB stuff follows */
|
||||
static struct usb_device_id technisat_usb2_id_table[] = {
|
||||
{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) },
|
||||
{ 0 } /* Terminating entry */
|
||||
};
|
||||
|
||||
/* device description */
|
||||
static struct dvb_usb_device_properties technisat_usb2_devices = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
|
||||
.usb_ctrl = CYPRESS_FX2,
|
||||
|
||||
.identify_state = technisat_usb2_identify_state,
|
||||
.firmware = "dvb-usb-SkyStar_USB_HD_FW_v17_63.HEX.fw",
|
||||
|
||||
.size_of_priv = sizeof(struct technisat_usb2_state),
|
||||
|
||||
.i2c_algo = &technisat_usb2_i2c_algo,
|
||||
|
||||
.power_ctrl = technisat_usb2_power_ctrl,
|
||||
.read_mac_address = technisat_usb2_read_mac_address,
|
||||
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.frontend_attach = technisat_usb2_frontend_attach,
|
||||
|
||||
.stream = {
|
||||
.type = USB_ISOC,
|
||||
.count = 8,
|
||||
.endpoint = 0x2,
|
||||
.u = {
|
||||
.isoc = {
|
||||
.framesperurb = 32,
|
||||
.framesize = 2048,
|
||||
.interval = 3,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.size_of_priv = 0,
|
||||
},
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ "Technisat SkyStar USB HD (DVB-S/S2)",
|
||||
{ &technisat_usb2_id_table[0], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
},
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = 100,
|
||||
.rc_codes = RC_MAP_TECHNISAT_USB2,
|
||||
.module_name = "technisat-usb2",
|
||||
.rc_query = technisat_usb2_rc_query,
|
||||
.allowed_protos = RC_TYPE_ALL,
|
||||
.driver_type = RC_DRIVER_IR_RAW,
|
||||
}
|
||||
};
|
||||
|
||||
static int technisat_usb2_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct dvb_usb_device *dev;
|
||||
|
||||
if (dvb_usb_device_init(intf, &technisat_usb2_devices, THIS_MODULE,
|
||||
&dev, adapter_nr) != 0)
|
||||
return -ENODEV;
|
||||
|
||||
if (dev) {
|
||||
struct technisat_usb2_state *state = dev->priv;
|
||||
state->dev = dev;
|
||||
|
||||
if (!disable_led_control) {
|
||||
INIT_DELAYED_WORK(&state->green_led_work,
|
||||
technisat_usb2_green_led_control);
|
||||
schedule_delayed_work(&state->green_led_work,
|
||||
msecs_to_jiffies(500));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void technisat_usb2_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct dvb_usb_device *dev = usb_get_intfdata(intf);
|
||||
|
||||
/* work and stuff was only created when the device is is hot-state */
|
||||
if (dev != NULL) {
|
||||
struct technisat_usb2_state *state = dev->priv;
|
||||
if (state != NULL) {
|
||||
cancel_delayed_work_sync(&state->green_led_work);
|
||||
flush_scheduled_work();
|
||||
}
|
||||
}
|
||||
|
||||
dvb_usb_device_exit(intf);
|
||||
}
|
||||
|
||||
static struct usb_driver technisat_usb2_driver = {
|
||||
.name = "dvb_usb_technisat_usb2",
|
||||
.probe = technisat_usb2_probe,
|
||||
.disconnect = technisat_usb2_disconnect,
|
||||
.id_table = technisat_usb2_id_table,
|
||||
};
|
||||
|
||||
/* module stuff */
|
||||
static int __init technisat_usb2_module_init(void)
|
||||
{
|
||||
int result = usb_register(&technisat_usb2_driver);
|
||||
if (result) {
|
||||
err("usb_register failed. Code %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit technisat_usb2_module_exit(void)
|
||||
{
|
||||
usb_deregister(&technisat_usb2_driver);
|
||||
}
|
||||
|
||||
module_init(technisat_usb2_module_init);
|
||||
module_exit(technisat_usb2_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Patrick Boettcher <pboettcher@kernellabs.com>");
|
||||
MODULE_DESCRIPTION("Driver for Technisat DVB-S/S2 USB 2.0 device");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -1,6 +1,6 @@
|
|||
config DVB_FIREDTV
|
||||
tristate "FireDTV and FloppyDTV"
|
||||
depends on DVB_CORE && (FIREWIRE || IEEE1394)
|
||||
depends on DVB_CORE && FIREWIRE
|
||||
help
|
||||
Support for DVB receivers from Digital Everywhere
|
||||
which are connected via IEEE 1394 (FireWire).
|
||||
|
@ -13,12 +13,6 @@ config DVB_FIREDTV
|
|||
|
||||
if DVB_FIREDTV
|
||||
|
||||
config DVB_FIREDTV_FIREWIRE
|
||||
def_bool FIREWIRE = y || (FIREWIRE = m && DVB_FIREDTV = m)
|
||||
|
||||
config DVB_FIREDTV_IEEE1394
|
||||
def_bool IEEE1394 = y || (IEEE1394 = m && DVB_FIREDTV = m)
|
||||
|
||||
config DVB_FIREDTV_INPUT
|
||||
def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
|
||||
|
||||
firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
|
||||
firedtv-$(CONFIG_DVB_FIREDTV_FIREWIRE) += firedtv-fw.o
|
||||
firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
|
||||
firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o
|
||||
firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o
|
||||
|
||||
ccflags-y += -Idrivers/media/dvb/dvb-core
|
||||
ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394
|
||||
|
|
|
@ -1,300 +0,0 @@
|
|||
/*
|
||||
* FireDTV driver -- ieee1394 I/O backend
|
||||
*
|
||||
* Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
|
||||
* Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com>
|
||||
* Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <dma.h>
|
||||
#include <csr1212.h>
|
||||
#include <highlevel.h>
|
||||
#include <hosts.h>
|
||||
#include <ieee1394.h>
|
||||
#include <iso.h>
|
||||
#include <nodemgr.h>
|
||||
|
||||
#include <dvb_demux.h>
|
||||
|
||||
#include "firedtv.h"
|
||||
|
||||
static LIST_HEAD(node_list);
|
||||
static DEFINE_SPINLOCK(node_list_lock);
|
||||
|
||||
#define CIP_HEADER_SIZE 8
|
||||
#define MPEG2_TS_HEADER_SIZE 4
|
||||
#define MPEG2_TS_SOURCE_PACKET_SIZE (4 + 188)
|
||||
|
||||
static void rawiso_activity_cb(struct hpsb_iso *iso)
|
||||
{
|
||||
struct firedtv *f, *fdtv = NULL;
|
||||
unsigned int i, num, packet;
|
||||
unsigned char *buf;
|
||||
unsigned long flags;
|
||||
int count;
|
||||
|
||||
spin_lock_irqsave(&node_list_lock, flags);
|
||||
list_for_each_entry(f, &node_list, list)
|
||||
if (f->backend_data == iso) {
|
||||
fdtv = f;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&node_list_lock, flags);
|
||||
|
||||
packet = iso->first_packet;
|
||||
num = hpsb_iso_n_ready(iso);
|
||||
|
||||
if (!fdtv) {
|
||||
pr_err("received at unknown iso channel\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) {
|
||||
buf = dma_region_i(&iso->data_buf, unsigned char,
|
||||
iso->infos[packet].offset + CIP_HEADER_SIZE);
|
||||
count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
|
||||
MPEG2_TS_SOURCE_PACKET_SIZE;
|
||||
|
||||
/* ignore empty packet */
|
||||
if (iso->infos[packet].len <= CIP_HEADER_SIZE)
|
||||
continue;
|
||||
|
||||
while (count--) {
|
||||
if (buf[MPEG2_TS_HEADER_SIZE] == 0x47)
|
||||
dvb_dmx_swfilter_packets(&fdtv->demux,
|
||||
&buf[MPEG2_TS_HEADER_SIZE], 1);
|
||||
else
|
||||
dev_err(fdtv->device,
|
||||
"skipping invalid packet\n");
|
||||
buf += MPEG2_TS_SOURCE_PACKET_SIZE;
|
||||
}
|
||||
}
|
||||
out:
|
||||
hpsb_iso_recv_release_packets(iso, num);
|
||||
}
|
||||
|
||||
static inline struct node_entry *node_of(struct firedtv *fdtv)
|
||||
{
|
||||
return container_of(fdtv->device, struct unit_directory, device)->ne;
|
||||
}
|
||||
|
||||
static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
|
||||
{
|
||||
quadlet_t *d = data;
|
||||
int ret;
|
||||
|
||||
ret = hpsb_node_lock(node_of(fdtv), addr,
|
||||
EXTCODE_COMPARE_SWAP, &d[1], d[0]);
|
||||
d[0] = d[1];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int node_read(struct firedtv *fdtv, u64 addr, void *data)
|
||||
{
|
||||
return hpsb_node_read(node_of(fdtv), addr, data, 4);
|
||||
}
|
||||
|
||||
static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
|
||||
{
|
||||
return hpsb_node_write(node_of(fdtv), addr, data, len);
|
||||
}
|
||||
|
||||
#define FDTV_ISO_BUFFER_PACKETS 256
|
||||
#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
|
||||
|
||||
static int start_iso(struct firedtv *fdtv)
|
||||
{
|
||||
struct hpsb_iso *iso_handle;
|
||||
int ret;
|
||||
|
||||
iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host,
|
||||
FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS,
|
||||
fdtv->isochannel, HPSB_ISO_DMA_DEFAULT,
|
||||
-1, /* stat.config.irq_interval */
|
||||
rawiso_activity_cb);
|
||||
if (iso_handle == NULL) {
|
||||
dev_err(fdtv->device, "cannot initialize iso receive\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
fdtv->backend_data = iso_handle;
|
||||
|
||||
ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0);
|
||||
if (ret != 0) {
|
||||
dev_err(fdtv->device, "cannot start iso receive\n");
|
||||
hpsb_iso_shutdown(iso_handle);
|
||||
fdtv->backend_data = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stop_iso(struct firedtv *fdtv)
|
||||
{
|
||||
struct hpsb_iso *iso_handle = fdtv->backend_data;
|
||||
|
||||
if (iso_handle != NULL) {
|
||||
hpsb_iso_stop(iso_handle);
|
||||
hpsb_iso_shutdown(iso_handle);
|
||||
}
|
||||
fdtv->backend_data = NULL;
|
||||
}
|
||||
|
||||
static const struct firedtv_backend fdtv_1394_backend = {
|
||||
.lock = node_lock,
|
||||
.read = node_read,
|
||||
.write = node_write,
|
||||
.start_iso = start_iso,
|
||||
.stop_iso = stop_iso,
|
||||
};
|
||||
|
||||
static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
|
||||
int cts, u8 *data, size_t length)
|
||||
{
|
||||
struct firedtv *f, *fdtv = NULL;
|
||||
unsigned long flags;
|
||||
int su;
|
||||
|
||||
if (length == 0 || (data[0] & 0xf0) != 0)
|
||||
return;
|
||||
|
||||
su = data[1] & 0x7;
|
||||
|
||||
spin_lock_irqsave(&node_list_lock, flags);
|
||||
list_for_each_entry(f, &node_list, list)
|
||||
if (node_of(f)->host == host &&
|
||||
node_of(f)->nodeid == nodeid &&
|
||||
(f->subunit == su || (f->subunit == 0 && su == 0x7))) {
|
||||
fdtv = f;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&node_list_lock, flags);
|
||||
|
||||
if (fdtv)
|
||||
avc_recv(fdtv, data, length);
|
||||
}
|
||||
|
||||
static int node_probe(struct device *dev)
|
||||
{
|
||||
struct unit_directory *ud =
|
||||
container_of(dev, struct unit_directory, device);
|
||||
struct firedtv *fdtv;
|
||||
int kv_len, err;
|
||||
void *kv_str;
|
||||
|
||||
if (ud->model_name_kv) {
|
||||
kv_len = (ud->model_name_kv->value.leaf.len - 2) * 4;
|
||||
kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
|
||||
} else {
|
||||
kv_len = 0;
|
||||
kv_str = NULL;
|
||||
}
|
||||
fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
|
||||
if (!fdtv)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Work around a bug in udev's path_id script: Use the fw-host's dev
|
||||
* instead of the unit directory's dev as parent of the input device.
|
||||
*/
|
||||
err = fdtv_register_rc(fdtv, dev->parent->parent);
|
||||
if (err)
|
||||
goto fail_free;
|
||||
|
||||
spin_lock_irq(&node_list_lock);
|
||||
list_add_tail(&fdtv->list, &node_list);
|
||||
spin_unlock_irq(&node_list_lock);
|
||||
|
||||
err = avc_identify_subunit(fdtv);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
err = fdtv_dvb_register(fdtv);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
avc_register_remote_control(fdtv);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
spin_lock_irq(&node_list_lock);
|
||||
list_del(&fdtv->list);
|
||||
spin_unlock_irq(&node_list_lock);
|
||||
fdtv_unregister_rc(fdtv);
|
||||
fail_free:
|
||||
kfree(fdtv);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int node_remove(struct device *dev)
|
||||
{
|
||||
struct firedtv *fdtv = dev_get_drvdata(dev);
|
||||
|
||||
fdtv_dvb_unregister(fdtv);
|
||||
|
||||
spin_lock_irq(&node_list_lock);
|
||||
list_del(&fdtv->list);
|
||||
spin_unlock_irq(&node_list_lock);
|
||||
|
||||
fdtv_unregister_rc(fdtv);
|
||||
kfree(fdtv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int node_update(struct unit_directory *ud)
|
||||
{
|
||||
struct firedtv *fdtv = dev_get_drvdata(&ud->device);
|
||||
|
||||
if (fdtv->isochannel >= 0)
|
||||
cmp_establish_pp_connection(fdtv, fdtv->subunit,
|
||||
fdtv->isochannel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hpsb_protocol_driver fdtv_driver = {
|
||||
.name = "firedtv",
|
||||
.id_table = fdtv_id_table,
|
||||
.update = node_update,
|
||||
.driver = {
|
||||
.probe = node_probe,
|
||||
.remove = node_remove,
|
||||
},
|
||||
};
|
||||
|
||||
static struct hpsb_highlevel fdtv_highlevel = {
|
||||
.name = "firedtv",
|
||||
.fcp_request = fcp_request,
|
||||
};
|
||||
|
||||
int __init fdtv_1394_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hpsb_register_highlevel(&fdtv_highlevel);
|
||||
ret = hpsb_register_protocol(&fdtv_driver);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "firedtv: failed to register protocol\n");
|
||||
hpsb_unregister_highlevel(&fdtv_highlevel);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit fdtv_1394_exit(void)
|
||||
{
|
||||
hpsb_unregister_protocol(&fdtv_driver);
|
||||
hpsb_unregister_highlevel(&fdtv_highlevel);
|
||||
}
|
|
@ -241,8 +241,8 @@ static int avc_write(struct firedtv *fdtv)
|
|||
if (unlikely(avc_debug))
|
||||
debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
|
||||
|
||||
err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
|
||||
fdtv->avc_data, fdtv->avc_data_length);
|
||||
err = fdtv_write(fdtv, FCP_COMMAND_REGISTER,
|
||||
fdtv->avc_data, fdtv->avc_data_length);
|
||||
if (err) {
|
||||
dev_err(fdtv->device, "FCP command write failed\n");
|
||||
|
||||
|
@ -1322,7 +1322,7 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
|
|||
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
ret = fdtv->backend->read(fdtv, addr, data);
|
||||
ret = fdtv_read(fdtv, addr, data);
|
||||
if (ret < 0)
|
||||
dev_err(fdtv->device, "CMP: read I/O error\n");
|
||||
|
||||
|
@ -1340,7 +1340,7 @@ static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
|
|||
/* data[] is stack-allocated and should not be DMA-mapped. */
|
||||
memcpy(fdtv->avc_data, data, 8);
|
||||
|
||||
ret = fdtv->backend->lock(fdtv, addr, fdtv->avc_data);
|
||||
ret = fdtv_lock(fdtv, addr, fdtv->avc_data);
|
||||
if (ret < 0)
|
||||
dev_err(fdtv->device, "CMP: lock I/O error\n");
|
||||
else
|
||||
|
@ -1405,10 +1405,7 @@ repeat:
|
|||
/* FIXME: this is for the worst case - optimize */
|
||||
set_opcr_overhead_id(opcr, 0);
|
||||
|
||||
/*
|
||||
* FIXME: allocate isochronous channel and bandwidth at IRM
|
||||
* fdtv->backend->alloc_resources(fdtv, channels_mask, bw);
|
||||
*/
|
||||
/* FIXME: allocate isochronous channel and bandwidth at IRM */
|
||||
}
|
||||
|
||||
set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) + 1);
|
||||
|
@ -1424,8 +1421,6 @@ repeat:
|
|||
/*
|
||||
* FIXME: if old_opcr.P2P_Connections > 0,
|
||||
* deallocate isochronous channel and bandwidth at IRM
|
||||
* if (...)
|
||||
* fdtv->backend->dealloc_resources(fdtv, channel, bw);
|
||||
*/
|
||||
|
||||
if (++attempts < 6) /* arbitrary limit */
|
||||
|
|
|
@ -14,14 +14,9 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <dmxdev.h>
|
||||
#include <dvb_demux.h>
|
||||
|
@ -166,11 +161,11 @@ int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
|
|||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
int fdtv_dvb_register(struct firedtv *fdtv)
|
||||
int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
|
||||
err = dvb_register_adapter(&fdtv->adapter, name,
|
||||
THIS_MODULE, fdtv->device, adapter_nr);
|
||||
if (err < 0)
|
||||
goto fail_log;
|
||||
|
@ -210,7 +205,7 @@ int fdtv_dvb_register(struct firedtv *fdtv)
|
|||
|
||||
dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
|
||||
|
||||
fdtv_frontend_init(fdtv);
|
||||
fdtv_frontend_init(fdtv, name);
|
||||
err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
|
||||
if (err)
|
||||
goto fail_net_release;
|
||||
|
@ -248,127 +243,3 @@ void fdtv_dvb_unregister(struct firedtv *fdtv)
|
|||
dvb_dmx_release(&fdtv->demux);
|
||||
dvb_unregister_adapter(&fdtv->adapter);
|
||||
}
|
||||
|
||||
const char *fdtv_model_names[] = {
|
||||
[FIREDTV_UNKNOWN] = "unknown type",
|
||||
[FIREDTV_DVB_S] = "FireDTV S/CI",
|
||||
[FIREDTV_DVB_C] = "FireDTV C/CI",
|
||||
[FIREDTV_DVB_T] = "FireDTV T/CI",
|
||||
[FIREDTV_DVB_S2] = "FireDTV S2 ",
|
||||
};
|
||||
|
||||
struct firedtv *fdtv_alloc(struct device *dev,
|
||||
const struct firedtv_backend *backend,
|
||||
const char *name, size_t name_len)
|
||||
{
|
||||
struct firedtv *fdtv;
|
||||
int i;
|
||||
|
||||
fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
|
||||
if (!fdtv)
|
||||
return NULL;
|
||||
|
||||
dev_set_drvdata(dev, fdtv);
|
||||
fdtv->device = dev;
|
||||
fdtv->isochannel = -1;
|
||||
fdtv->voltage = 0xff;
|
||||
fdtv->tone = 0xff;
|
||||
fdtv->backend = backend;
|
||||
|
||||
mutex_init(&fdtv->avc_mutex);
|
||||
init_waitqueue_head(&fdtv->avc_wait);
|
||||
mutex_init(&fdtv->demux_mutex);
|
||||
INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
|
||||
|
||||
for (i = ARRAY_SIZE(fdtv_model_names); --i; )
|
||||
if (strlen(fdtv_model_names[i]) <= name_len &&
|
||||
strncmp(name, fdtv_model_names[i], name_len) == 0)
|
||||
break;
|
||||
fdtv->type = i;
|
||||
|
||||
return fdtv;
|
||||
}
|
||||
|
||||
#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
|
||||
IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
|
||||
|
||||
#define DIGITAL_EVERYWHERE_OUI 0x001287
|
||||
#define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d
|
||||
#define AVC_SW_VERSION_ENTRY 0x010001
|
||||
|
||||
const struct ieee1394_device_id fdtv_id_table[] = {
|
||||
{
|
||||
/* FloppyDTV S/CI and FloppyDTV S2 */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000024,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FloppyDTV T/CI */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000025,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FloppyDTV C/CI */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000026,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FireDTV S/CI and FloppyDTV S2 */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000034,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FireDTV T/CI */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000035,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FireDTV C/CI */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000036,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
|
||||
|
||||
static int __init fdtv_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = fdtv_fw_init();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = fdtv_1394_init();
|
||||
if (ret < 0)
|
||||
fdtv_fw_exit();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit fdtv_exit(void)
|
||||
{
|
||||
fdtv_1394_exit();
|
||||
fdtv_fw_exit();
|
||||
}
|
||||
|
||||
module_init(fdtv_init);
|
||||
module_exit(fdtv_exit);
|
||||
|
||||
MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
|
||||
MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
|
||||
MODULE_DESCRIPTION("FireDTV DVB Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_SUPPORTED_DEVICE("FireDTV DVB");
|
||||
|
|
|
@ -36,14 +36,14 @@ static int fdtv_dvb_init(struct dvb_frontend *fe)
|
|||
return err;
|
||||
}
|
||||
|
||||
return fdtv->backend->start_iso(fdtv);
|
||||
return fdtv_start_iso(fdtv);
|
||||
}
|
||||
|
||||
static int fdtv_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct firedtv *fdtv = fe->sec_priv;
|
||||
|
||||
fdtv->backend->stop_iso(fdtv);
|
||||
fdtv_stop_iso(fdtv);
|
||||
cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
|
||||
fdtv->isochannel = -1;
|
||||
return 0;
|
||||
|
@ -165,7 +165,7 @@ static int fdtv_set_property(struct dvb_frontend *fe, struct dtv_property *tvp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void fdtv_frontend_init(struct firedtv *fdtv)
|
||||
void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
|
||||
{
|
||||
struct dvb_frontend_ops *ops = &fdtv->fe.ops;
|
||||
struct dvb_frontend_info *fi = &ops->info;
|
||||
|
@ -266,7 +266,7 @@ void fdtv_frontend_init(struct firedtv *fdtv)
|
|||
dev_err(fdtv->device, "no frontend for model type %d\n",
|
||||
fdtv->type);
|
||||
}
|
||||
strcpy(fi->name, fdtv_model_names[fdtv->type]);
|
||||
strcpy(fi->name, name);
|
||||
|
||||
fdtv->fe.dvb = &fdtv->adapter;
|
||||
fdtv->fe.sec_priv = fdtv;
|
||||
|
|
|
@ -9,11 +9,18 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include <dvb_demux.h>
|
||||
|
||||
|
@ -41,17 +48,17 @@ static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len,
|
|||
return rcode != RCODE_COMPLETE ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
|
||||
int fdtv_lock(struct firedtv *fdtv, u64 addr, void *data)
|
||||
{
|
||||
return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
|
||||
}
|
||||
|
||||
static int node_read(struct firedtv *fdtv, u64 addr, void *data)
|
||||
int fdtv_read(struct firedtv *fdtv, u64 addr, void *data)
|
||||
{
|
||||
return node_req(fdtv, addr, data, 4, TCODE_READ_QUADLET_REQUEST);
|
||||
}
|
||||
|
||||
static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
|
||||
int fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
|
||||
{
|
||||
return node_req(fdtv, addr, data, len, TCODE_WRITE_BLOCK_REQUEST);
|
||||
}
|
||||
|
@ -67,7 +74,7 @@ static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
|
|||
#define N_PAGES DIV_ROUND_UP(N_PACKETS, PACKETS_PER_PAGE)
|
||||
#define IRQ_INTERVAL 16
|
||||
|
||||
struct firedtv_receive_context {
|
||||
struct fdtv_ir_context {
|
||||
struct fw_iso_context *context;
|
||||
struct fw_iso_buffer buffer;
|
||||
int interrupt_packet;
|
||||
|
@ -75,7 +82,7 @@ struct firedtv_receive_context {
|
|||
char *pages[N_PAGES];
|
||||
};
|
||||
|
||||
static int queue_iso(struct firedtv_receive_context *ctx, int index)
|
||||
static int queue_iso(struct fdtv_ir_context *ctx, int index)
|
||||
{
|
||||
struct fw_iso_packet p;
|
||||
|
||||
|
@ -92,7 +99,7 @@ static void handle_iso(struct fw_iso_context *context, u32 cycle,
|
|||
size_t header_length, void *header, void *data)
|
||||
{
|
||||
struct firedtv *fdtv = data;
|
||||
struct firedtv_receive_context *ctx = fdtv->backend_data;
|
||||
struct fdtv_ir_context *ctx = fdtv->ir_context;
|
||||
__be32 *h, *h_end;
|
||||
int length, err, i = ctx->current_packet;
|
||||
char *p, *p_end;
|
||||
|
@ -121,9 +128,9 @@ static void handle_iso(struct fw_iso_context *context, u32 cycle,
|
|||
ctx->current_packet = i;
|
||||
}
|
||||
|
||||
static int start_iso(struct firedtv *fdtv)
|
||||
int fdtv_start_iso(struct firedtv *fdtv)
|
||||
{
|
||||
struct firedtv_receive_context *ctx;
|
||||
struct fdtv_ir_context *ctx;
|
||||
struct fw_device *device = device_of(fdtv);
|
||||
int i, err;
|
||||
|
||||
|
@ -161,7 +168,7 @@ static int start_iso(struct firedtv *fdtv)
|
|||
if (err)
|
||||
goto fail;
|
||||
|
||||
fdtv->backend_data = ctx;
|
||||
fdtv->ir_context = ctx;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
|
@ -174,9 +181,9 @@ fail_free:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void stop_iso(struct firedtv *fdtv)
|
||||
void fdtv_stop_iso(struct firedtv *fdtv)
|
||||
{
|
||||
struct firedtv_receive_context *ctx = fdtv->backend_data;
|
||||
struct fdtv_ir_context *ctx = fdtv->ir_context;
|
||||
|
||||
fw_iso_context_stop(ctx->context);
|
||||
fw_iso_buffer_destroy(&ctx->buffer, device_of(fdtv)->card);
|
||||
|
@ -184,14 +191,6 @@ static void stop_iso(struct firedtv *fdtv)
|
|||
kfree(ctx);
|
||||
}
|
||||
|
||||
static const struct firedtv_backend backend = {
|
||||
.lock = node_lock,
|
||||
.read = node_read,
|
||||
.write = node_write,
|
||||
.start_iso = start_iso,
|
||||
.stop_iso = stop_iso,
|
||||
};
|
||||
|
||||
static void handle_fcp(struct fw_card *card, struct fw_request *request,
|
||||
int tcode, int destination, int source, int generation,
|
||||
unsigned long long offset, void *payload, size_t length,
|
||||
|
@ -238,6 +237,14 @@ static const struct fw_address_region fcp_region = {
|
|||
.end = CSR_REGISTER_BASE + CSR_FCP_END,
|
||||
};
|
||||
|
||||
static const char * const model_names[] = {
|
||||
[FIREDTV_UNKNOWN] = "unknown type",
|
||||
[FIREDTV_DVB_S] = "FireDTV S/CI",
|
||||
[FIREDTV_DVB_C] = "FireDTV C/CI",
|
||||
[FIREDTV_DVB_T] = "FireDTV T/CI",
|
||||
[FIREDTV_DVB_S2] = "FireDTV S2 ",
|
||||
};
|
||||
|
||||
/* Adjust the template string if models with longer names appear. */
|
||||
#define MAX_MODEL_NAME_LEN sizeof("FireDTV ????")
|
||||
|
||||
|
@ -245,14 +252,30 @@ static int node_probe(struct device *dev)
|
|||
{
|
||||
struct firedtv *fdtv;
|
||||
char name[MAX_MODEL_NAME_LEN];
|
||||
int name_len, err;
|
||||
int name_len, i, err;
|
||||
|
||||
fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
|
||||
if (!fdtv)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, fdtv);
|
||||
fdtv->device = dev;
|
||||
fdtv->isochannel = -1;
|
||||
fdtv->voltage = 0xff;
|
||||
fdtv->tone = 0xff;
|
||||
|
||||
mutex_init(&fdtv->avc_mutex);
|
||||
init_waitqueue_head(&fdtv->avc_wait);
|
||||
mutex_init(&fdtv->demux_mutex);
|
||||
INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
|
||||
|
||||
name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL,
|
||||
name, sizeof(name));
|
||||
|
||||
fdtv = fdtv_alloc(dev, &backend, name, name_len >= 0 ? name_len : 0);
|
||||
if (!fdtv)
|
||||
return -ENOMEM;
|
||||
for (i = ARRAY_SIZE(model_names); --i; )
|
||||
if (strlen(model_names[i]) <= name_len &&
|
||||
strncmp(name, model_names[i], name_len) == 0)
|
||||
break;
|
||||
fdtv->type = i;
|
||||
|
||||
err = fdtv_register_rc(fdtv, dev);
|
||||
if (err)
|
||||
|
@ -266,7 +289,7 @@ static int node_probe(struct device *dev)
|
|||
if (err)
|
||||
goto fail;
|
||||
|
||||
err = fdtv_dvb_register(fdtv);
|
||||
err = fdtv_dvb_register(fdtv, model_names[fdtv->type]);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
|
@ -309,6 +332,60 @@ static void node_update(struct fw_unit *unit)
|
|||
fdtv->isochannel);
|
||||
}
|
||||
|
||||
#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
|
||||
IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
|
||||
|
||||
#define DIGITAL_EVERYWHERE_OUI 0x001287
|
||||
#define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d
|
||||
#define AVC_SW_VERSION_ENTRY 0x010001
|
||||
|
||||
static const struct ieee1394_device_id fdtv_id_table[] = {
|
||||
{
|
||||
/* FloppyDTV S/CI and FloppyDTV S2 */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000024,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FloppyDTV T/CI */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000025,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FloppyDTV C/CI */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000026,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FireDTV S/CI and FloppyDTV S2 */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000034,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FireDTV T/CI */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000035,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {
|
||||
/* FireDTV C/CI */
|
||||
.match_flags = MATCH_FLAGS,
|
||||
.vendor_id = DIGITAL_EVERYWHERE_OUI,
|
||||
.model_id = 0x000036,
|
||||
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
|
||||
.version = AVC_SW_VERSION_ENTRY,
|
||||
}, {}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
|
||||
|
||||
static struct fw_driver fdtv_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -321,7 +398,7 @@ static struct fw_driver fdtv_driver = {
|
|||
.id_table = fdtv_id_table,
|
||||
};
|
||||
|
||||
int __init fdtv_fw_init(void)
|
||||
static int __init fdtv_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -329,11 +406,24 @@ int __init fdtv_fw_init(void)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return driver_register(&fdtv_driver.driver);
|
||||
ret = driver_register(&fdtv_driver.driver);
|
||||
if (ret < 0)
|
||||
fw_core_remove_address_handler(&fcp_handler);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fdtv_fw_exit(void)
|
||||
static void __exit fdtv_exit(void)
|
||||
{
|
||||
driver_unregister(&fdtv_driver.driver);
|
||||
fw_core_remove_address_handler(&fcp_handler);
|
||||
}
|
||||
|
||||
module_init(fdtv_init);
|
||||
module_exit(fdtv_exit);
|
||||
|
||||
MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
|
||||
MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
|
||||
MODULE_DESCRIPTION("FireDTV DVB Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_SUPPORTED_DEVICE("FireDTV DVB");
|
||||
|
|
|
@ -70,15 +70,7 @@ enum model_type {
|
|||
|
||||
struct device;
|
||||
struct input_dev;
|
||||
struct firedtv;
|
||||
|
||||
struct firedtv_backend {
|
||||
int (*lock)(struct firedtv *fdtv, u64 addr, void *data);
|
||||
int (*read)(struct firedtv *fdtv, u64 addr, void *data);
|
||||
int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
|
||||
int (*start_iso)(struct firedtv *fdtv);
|
||||
void (*stop_iso)(struct firedtv *fdtv);
|
||||
};
|
||||
struct fdtv_ir_context;
|
||||
|
||||
struct firedtv {
|
||||
struct device *device;
|
||||
|
@ -104,12 +96,11 @@ struct firedtv {
|
|||
enum model_type type;
|
||||
char subunit;
|
||||
char isochannel;
|
||||
struct fdtv_ir_context *ir_context;
|
||||
|
||||
fe_sec_voltage_t voltage;
|
||||
fe_sec_tone_mode_t tone;
|
||||
|
||||
const struct firedtv_backend *backend;
|
||||
void *backend_data;
|
||||
|
||||
struct mutex demux_mutex;
|
||||
unsigned long channel_active;
|
||||
u16 channel_pid[16];
|
||||
|
@ -118,15 +109,6 @@ struct firedtv {
|
|||
u8 avc_data[512];
|
||||
};
|
||||
|
||||
/* firedtv-1394.c */
|
||||
#ifdef CONFIG_DVB_FIREDTV_IEEE1394
|
||||
int fdtv_1394_init(void);
|
||||
void fdtv_1394_exit(void);
|
||||
#else
|
||||
static inline int fdtv_1394_init(void) { return 0; }
|
||||
static inline void fdtv_1394_exit(void) {}
|
||||
#endif
|
||||
|
||||
/* firedtv-avc.c */
|
||||
int avc_recv(struct firedtv *fdtv, void *data, size_t length);
|
||||
int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
|
||||
|
@ -158,25 +140,18 @@ void fdtv_ca_release(struct firedtv *fdtv);
|
|||
/* firedtv-dvb.c */
|
||||
int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
|
||||
int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
|
||||
int fdtv_dvb_register(struct firedtv *fdtv);
|
||||
int fdtv_dvb_register(struct firedtv *fdtv, const char *name);
|
||||
void fdtv_dvb_unregister(struct firedtv *fdtv);
|
||||
struct firedtv *fdtv_alloc(struct device *dev,
|
||||
const struct firedtv_backend *backend,
|
||||
const char *name, size_t name_len);
|
||||
extern const char *fdtv_model_names[];
|
||||
extern const struct ieee1394_device_id fdtv_id_table[];
|
||||
|
||||
/* firedtv-fe.c */
|
||||
void fdtv_frontend_init(struct firedtv *fdtv);
|
||||
void fdtv_frontend_init(struct firedtv *fdtv, const char *name);
|
||||
|
||||
/* firedtv-fw.c */
|
||||
#ifdef CONFIG_DVB_FIREDTV_FIREWIRE
|
||||
int fdtv_fw_init(void);
|
||||
void fdtv_fw_exit(void);
|
||||
#else
|
||||
static inline int fdtv_fw_init(void) { return 0; }
|
||||
static inline void fdtv_fw_exit(void) {}
|
||||
#endif
|
||||
int fdtv_lock(struct firedtv *fdtv, u64 addr, void *data);
|
||||
int fdtv_read(struct firedtv *fdtv, u64 addr, void *data);
|
||||
int fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len);
|
||||
int fdtv_start_iso(struct firedtv *fdtv);
|
||||
void fdtv_stop_iso(struct firedtv *fdtv);
|
||||
|
||||
/* firedtv-rc.c */
|
||||
#ifdef CONFIG_DVB_FIREDTV_INPUT
|
||||
|
|
|
@ -349,6 +349,14 @@ config DVB_DIB7000P
|
|||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_DIB9000
|
||||
tristate "DiBcom 9000"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_TDA10048
|
||||
tristate "Philips TDA10048HN based"
|
||||
depends on DVB_CORE && I2C
|
||||
|
@ -370,6 +378,13 @@ config DVB_EC100
|
|||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_STV0367
|
||||
tristate "ST STV0367 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T/C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
comment "DVB-C (cable) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
|
|||
obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB8000) += dib8000.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB9000) += dib9000.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_MT312) += mt312.o
|
||||
obj-$(CONFIG_DVB_VES1820) += ves1820.o
|
||||
obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
|
||||
|
@ -83,3 +84,4 @@ obj-$(CONFIG_DVB_DS3000) += ds3000.o
|
|||
obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
|
||||
obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
|
||||
obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
|
||||
obj-$(CONFIG_DVB_STV0367) += stv0367.o
|
||||
|
|
|
@ -1323,13 +1323,11 @@ static struct dvb_frontend_ops af9013_ops;
|
|||
|
||||
static int af9013_download_firmware(struct af9013_state *state)
|
||||
{
|
||||
int i, len, packets, remainder, ret;
|
||||
int i, len, remaining, ret;
|
||||
const struct firmware *fw;
|
||||
u16 addr = 0x5100; /* firmware start address */
|
||||
u16 checksum = 0;
|
||||
u8 val;
|
||||
u8 fw_params[4];
|
||||
u8 *data;
|
||||
u8 *fw_file = AF9013_DEFAULT_FIRMWARE;
|
||||
|
||||
msleep(100);
|
||||
|
@ -1373,21 +1371,18 @@ static int af9013_download_firmware(struct af9013_state *state)
|
|||
if (ret)
|
||||
goto error_release;
|
||||
|
||||
#define FW_PACKET_MAX_DATA 16
|
||||
|
||||
packets = fw->size / FW_PACKET_MAX_DATA;
|
||||
remainder = fw->size % FW_PACKET_MAX_DATA;
|
||||
len = FW_PACKET_MAX_DATA;
|
||||
for (i = 0; i <= packets; i++) {
|
||||
if (i == packets) /* set size of the last packet */
|
||||
len = remainder;
|
||||
|
||||
data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
|
||||
ret = af9013_write_ofsm_regs(state, addr, data, len);
|
||||
addr += FW_PACKET_MAX_DATA;
|
||||
#define FW_ADDR 0x5100 /* firmware start address */
|
||||
#define LEN_MAX 16 /* max packet size */
|
||||
for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
|
||||
len = remaining;
|
||||
if (len > LEN_MAX)
|
||||
len = LEN_MAX;
|
||||
|
||||
ret = af9013_write_ofsm_regs(state,
|
||||
FW_ADDR + fw->size - remaining,
|
||||
(u8 *) &fw->data[fw->size - remaining], len);
|
||||
if (ret) {
|
||||
err("firmware download failed at %d with %d", i, ret);
|
||||
err("firmware download failed:%d", ret);
|
||||
goto error_release;
|
||||
}
|
||||
}
|
||||
|
@ -1466,20 +1461,6 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
|
|||
state->i2c = i2c;
|
||||
memcpy(&state->config, config, sizeof(struct af9013_config));
|
||||
|
||||
/* chip version */
|
||||
ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* ROM version */
|
||||
for (i = 0; i < 2; i++) {
|
||||
ret = af9013_read_reg(state, 0x116b + i, &buf[i]);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__,
|
||||
buf[2], buf[0], buf[1]);
|
||||
|
||||
/* download firmware */
|
||||
if (state->config.output_mode != AF9013_OUTPUT_MODE_USB) {
|
||||
ret = af9013_download_firmware(state);
|
||||
|
@ -1495,6 +1476,20 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
|
|||
}
|
||||
info("firmware version:%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
|
||||
|
||||
/* chip version */
|
||||
ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* ROM version */
|
||||
for (i = 0; i < 2; i++) {
|
||||
ret = af9013_read_reg(state, 0x116b + i, &buf[i]);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__,
|
||||
buf[2], buf[0], buf[1]);
|
||||
|
||||
/* settings for mp2if */
|
||||
if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) {
|
||||
/* AF9015 split PSB to 1.5k + 0.5k */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,6 +27,21 @@ struct dib0090_io_config {
|
|||
u16 pll_int_loop_filt;
|
||||
};
|
||||
|
||||
struct dib0090_wbd_slope {
|
||||
u16 max_freq; /* for every frequency less than or equal to that field: this information is correct */
|
||||
u16 slope_cold;
|
||||
u16 offset_cold;
|
||||
u16 slope_hot;
|
||||
u16 offset_hot;
|
||||
u8 wbd_gain;
|
||||
};
|
||||
|
||||
struct dib0090_low_if_offset_table {
|
||||
int std;
|
||||
u32 RF_freq;
|
||||
s32 offset_khz;
|
||||
};
|
||||
|
||||
struct dib0090_config {
|
||||
struct dib0090_io_config io;
|
||||
int (*reset) (struct dvb_frontend *, int);
|
||||
|
@ -47,10 +62,20 @@ struct dib0090_config {
|
|||
u16 wbd_cband_offset;
|
||||
u8 use_pwm_agc;
|
||||
u8 clkoutdrive;
|
||||
|
||||
u8 ls_cfg_pad_drv;
|
||||
u8 data_tx_drv;
|
||||
|
||||
u8 in_soc;
|
||||
const struct dib0090_low_if_offset_table *low_if;
|
||||
u8 fref_clock_ratio;
|
||||
u16 force_cband_input;
|
||||
struct dib0090_wbd_slope *wbd;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
|
||||
extern struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
|
||||
extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
|
||||
extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
|
||||
extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner);
|
||||
|
@ -65,6 +90,12 @@ static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, str
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue