aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-18 20:03:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-18 20:03:51 -0400
commit19c5abcb74b712a7824ae7c55862932534e7dfec (patch)
tree006822aa663cb9ee886773e819d4793fe3947626
parent675e0655c12209ba1f40af0dff7cd76b17a1315c (diff)
parentaff093d4bbca91f543e24cde2135f393b8130f4b (diff)
Merge tag 'media/v4.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - added support for Intersil/Techwell TW686x-based video capture cards - v4l PCI skeleton driver moved to samples directory - Documentation cleanups and improvements - RC: reduced the memory footprint for IR raw events - tpg: Export the tpg code from vivid as a module - adv7180: Add device tree binding documentation - lots of driver improvements and fixes * tag 'media/v4.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (173 commits) [media] exynos-gsc: avoid build warning without CONFIG_OF [media] samples: v4l: from Documentation to samples directory [media] dib0700: add USB ID for another STK8096-PVR ref design based card [media] tvp5150: propagate I2C write error in .s_register callback [media] tvp5150: return I2C write operation failure to callers [media] em28xx: add support for Hauppauge WinTV-dualHD DVB tuner [media] em28xx: add missing USB IDs [media] update cx23885 and em28xx cardlists [media] media: au0828 fix au0828_v4l2_device_register() to not unlock and free [media] c8sectpfe: Rework firmware loading mechanism [media] c8sectpfe: Demote print to dev_dbg [media] c8sectpfe: Fix broken circular buffer wp management [media] media-device: Simplify compat32 logic [media] media: i2c: ths7303: remove redundant assignment on bt [media] dvb-usb: hide unused functions [media] xilinx-vipp: remove unnecessary of_node_put [media] drivers/media/media-devnode: clear private_data before put_device() [media] drivers/media/media-device: move debug log before _devnode_unregister() [media] drivers/media/rc: postpone kfree(rc_dev) [media] media/dvb-core: forward media_create_pad_links() return value ...
-rw-r--r--Documentation/DocBook/device-drivers.tmpl1
-rw-r--r--Documentation/DocBook/media/dvb/net.xml2
-rw-r--r--Documentation/DocBook/media/v4l/compat.xml38
-rw-r--r--Documentation/DocBook/media/v4l/controls.xml31
-rw-r--r--Documentation/DocBook/media/v4l/dev-sdr.xml6
-rw-r--r--Documentation/DocBook/media/v4l/dev-subdev.xml6
-rw-r--r--Documentation/DocBook/media/v4l/io.xml6
-rw-r--r--Documentation/DocBook/media/v4l/selection-api.xml9
-rw-r--r--Documentation/DocBook/media/v4l/subdev-formats.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-create-bufs.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml18
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml11
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-expbuf.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-edid.xml10
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-selection.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-streamon.xml8
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml6
-rw-r--r--Documentation/Makefile3
-rw-r--r--Documentation/devicetree/bindings/media/i2c/adv7180.txt29
-rw-r--r--Documentation/devicetree/bindings/media/rcar_vin.txt12
-rw-r--r--Documentation/devicetree/bindings/media/xilinx/video.txt2
-rw-r--r--Documentation/video4linux/CARDLIST.cx238852
-rw-r--r--Documentation/video4linux/CARDLIST.em28xx12
-rw-r--r--Documentation/video4linux/v4l2-framework.txt2
-rw-r--r--Documentation/video4linux/vivid.txt6
-rw-r--r--MAINTAINERS8
-rw-r--r--drivers/media/common/Kconfig1
-rw-r--r--drivers/media/common/Makefile2
-rw-r--r--drivers/media/common/v4l2-tpg/Kconfig2
-rw-r--r--drivers/media/common/v4l2-tpg/Makefile3
-rw-r--r--drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c (renamed from drivers/media/platform/vivid/vivid-tpg-colors.c)7
-rw-r--r--drivers/media/common/v4l2-tpg/v4l2-tpg-core.c (renamed from drivers/media/platform/vivid/vivid-tpg.c)25
-rw-r--r--drivers/media/dvb-core/dvb-usb-ids.h14
-rw-r--r--drivers/media/dvb-core/dvbdev.c4
-rw-r--r--drivers/media/dvb-frontends/dib0090.c2
-rw-r--r--drivers/media/dvb-frontends/ds3000.c14
-rw-r--r--drivers/media/dvb-frontends/m88ds3103_priv.h2
-rw-r--r--drivers/media/dvb-frontends/zl10353.c6
-rw-r--r--drivers/media/i2c/ad9389b.c8
-rw-r--r--drivers/media/i2c/adp1653.c4
-rw-r--r--drivers/media/i2c/adv7180.c160
-rw-r--r--drivers/media/i2c/adv7511.c6
-rw-r--r--drivers/media/i2c/adv7604.c8
-rw-r--r--drivers/media/i2c/adv7842.c6
-rw-r--r--drivers/media/i2c/m5mols/m5mols_controls.c2
-rw-r--r--drivers/media/i2c/saa7115.c15
-rw-r--r--drivers/media/i2c/smiapp/smiapp-core.c12
-rw-r--r--drivers/media/i2c/smiapp/smiapp.h1
-rw-r--r--drivers/media/i2c/tc358743.c5
-rw-r--r--drivers/media/i2c/ths7303.c2
-rw-r--r--drivers/media/i2c/tvp5150.c9
-rw-r--r--drivers/media/media-device.c50
-rw-r--r--drivers/media/media-devnode.c6
-rw-r--r--drivers/media/media-entity.c18
-rw-r--r--drivers/media/pci/Kconfig1
-rw-r--r--drivers/media/pci/Makefile1
-rw-r--r--drivers/media/pci/cobalt/Kconfig1
-rw-r--r--drivers/media/pci/cx18/cx18-driver.h13
-rw-r--r--drivers/media/pci/cx23885/cx23885-av.c2
-rw-r--r--drivers/media/pci/ivtv/ivtv-driver.h13
-rw-r--r--drivers/media/pci/smipcie/smipcie-ir.c2
-rw-r--r--drivers/media/pci/smipcie/smipcie-main.c17
-rw-r--r--drivers/media/pci/smipcie/smipcie.h2
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c28
-rw-r--r--drivers/media/pci/tw686x/Kconfig18
-rw-r--r--drivers/media/pci/tw686x/Makefile3
-rw-r--r--drivers/media/pci/tw686x/tw686x-audio.c386
-rw-r--r--drivers/media/pci/tw686x/tw686x-core.c415
-rw-r--r--drivers/media/pci/tw686x/tw686x-regs.h122
-rw-r--r--drivers/media/pci/tw686x/tw686x-video.c937
-rw-r--r--drivers/media/pci/tw686x/tw686x.h158
-rw-r--r--drivers/media/pci/zoran/videocodec.c5
-rw-r--r--drivers/media/platform/Kconfig4
-rw-r--r--drivers/media/platform/am437x/am437x-vpfe.c4
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-core.c35
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-core.h1
-rw-r--r--drivers/media/platform/exynos4-is/fimc-core.c50
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.c8
-rw-r--r--drivers/media/platform/exynos4-is/mipi-csis.c6
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c2
-rw-r--r--drivers/media/platform/s5p-g2d/g2d.c27
-rw-r--r--drivers/media/platform/s5p-g2d/g2d.h5
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-core.c7
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc.c37
-rw-r--r--drivers/media/platform/s5p-tv/mixer.h2
-rw-r--r--drivers/media/platform/s5p-tv/mixer_grp_layer.c2
-rw-r--r--drivers/media/platform/s5p-tv/mixer_video.c2
-rw-r--r--drivers/media/platform/s5p-tv/mixer_vp_layer.c2
-rw-r--r--drivers/media/platform/soc_camera/Kconfig4
-rw-r--r--drivers/media/platform/soc_camera/rcar_vin.c2
-rw-r--r--drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c69
-rw-r--r--drivers/media/platform/vivid/Kconfig1
-rw-r--r--drivers/media/platform/vivid/Makefile2
-rw-r--r--drivers/media/platform/vivid/vivid-core.c22
-rw-r--r--drivers/media/platform/vivid/vivid-core.h2
-rw-r--r--drivers/media/platform/vivid/vivid-kthread-cap.c13
-rw-r--r--drivers/media/platform/vivid/vivid-rds-gen.c19
-rw-r--r--drivers/media/platform/vivid/vivid-vid-cap.c101
-rw-r--r--drivers/media/platform/vivid/vivid-vid-common.c97
-rw-r--r--drivers/media/platform/vivid/vivid-vid-common.h9
-rw-r--r--drivers/media/platform/vivid/vivid-vid-out.c103
-rw-r--r--drivers/media/platform/vsp1/vsp1.h14
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.c359
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.h3
-rw-r--r--drivers/media/platform/vsp1/vsp1_dl.c567
-rw-r--r--drivers/media/platform/vsp1/vsp1_dl.h49
-rw-r--r--drivers/media/platform/vsp1/vsp1_drm.c234
-rw-r--r--drivers/media/platform/vsp1/vsp1_drm.h27
-rw-r--r--drivers/media/platform/vsp1/vsp1_drv.c34
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.c288
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.h63
-rw-r--r--drivers/media/platform/vsp1/vsp1_hsit.c130
-rw-r--r--drivers/media/platform/vsp1/vsp1_lif.c179
-rw-r--r--drivers/media/platform/vsp1/vsp1_lut.c172
-rw-r--r--drivers/media/platform/vsp1/vsp1_lut.h6
-rw-r--r--drivers/media/platform/vsp1/vsp1_pipe.c71
-rw-r--r--drivers/media/platform/vsp1/vsp1_pipe.h19
-rw-r--r--drivers/media/platform/vsp1/vsp1_regs.h10
-rw-r--r--drivers/media/platform/vsp1/vsp1_rpf.c275
-rw-r--r--drivers/media/platform/vsp1/vsp1_rwpf.c171
-rw-r--r--drivers/media/platform/vsp1/vsp1_rwpf.h64
-rw-r--r--drivers/media/platform/vsp1/vsp1_sru.c214
-rw-r--r--drivers/media/platform/vsp1/vsp1_sru.h2
-rw-r--r--drivers/media/platform/vsp1/vsp1_uds.c223
-rw-r--r--drivers/media/platform/vsp1/vsp1_uds.h3
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.c493
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.h2
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c279
-rw-r--r--drivers/media/platform/xilinx/xilinx-vipp.c8
-rw-r--r--drivers/media/rc/ati_remote.c11
-rw-r--r--drivers/media/rc/mceusb.c6
-rw-r--r--drivers/media/rc/rc-main.c9
-rw-r--r--drivers/media/tuners/qm1d1c0042.c38
-rw-r--r--drivers/media/tuners/si2157.c19
-rw-r--r--drivers/media/tuners/si2157_priv.h1
-rw-r--r--drivers/media/usb/au0828/au0828-core.c38
-rw-r--r--drivers/media/usb/au0828/au0828-video.c4
-rw-r--r--drivers/media/usb/au0828/au0828.h1
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-417.c31
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-core.c3
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.h24
-rw-r--r--drivers/media/usb/dvb-usb/az6027.c7
-rw-r--r--drivers/media/usb/dvb-usb/dib0700_devices.c4
-rw-r--r--drivers/media/usb/dvb-usb/dibusb-common.c4
-rw-r--r--drivers/media/usb/dvb-usb/dw2102.c63
-rw-r--r--drivers/media/usb/dvb-usb/pctv452e.c4
-rw-r--r--drivers/media/usb/em28xx/Kconfig2
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c88
-rw-r--r--drivers/media/usb/em28xx/em28xx-dvb.c185
-rw-r--r--drivers/media/usb/em28xx/em28xx-reg.h13
-rw-r--r--drivers/media/usb/em28xx/em28xx.h3
-rw-r--r--drivers/media/usb/go7007/go7007-v4l2.c2
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-hdw.c9
-rw-r--r--drivers/media/v4l2-core/v4l2-compat-ioctl32.c3
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c1
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c73
-rw-r--r--drivers/media/v4l2-core/v4l2-mc.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c44
-rw-r--r--drivers/staging/media/Kconfig2
-rw-r--r--drivers/staging/media/Makefile1
-rw-r--r--drivers/staging/media/bcm2048/radio-bcm2048.c2
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.c2
-rw-r--r--drivers/staging/media/omap4iss/iss_video.c2
-rw-r--r--drivers/staging/media/tw686x-kh/Kconfig17
-rw-r--r--drivers/staging/media/tw686x-kh/Makefile3
-rw-r--r--drivers/staging/media/tw686x-kh/TODO6
-rw-r--r--drivers/staging/media/tw686x-kh/tw686x-kh-core.c140
-rw-r--r--drivers/staging/media/tw686x-kh/tw686x-kh-regs.h103
-rw-r--r--drivers/staging/media/tw686x-kh/tw686x-kh-video.c821
-rw-r--r--drivers/staging/media/tw686x-kh/tw686x-kh.h118
-rw-r--r--include/media/media-device.h13
-rw-r--r--include/media/media-entity.h81
-rw-r--r--include/media/rc-core.h18
-rw-r--r--include/media/v4l2-dev.h3
-rw-r--r--include/media/v4l2-device.h55
-rw-r--r--include/media/v4l2-rect.h173
-rw-r--r--include/media/v4l2-subdev.h8
-rw-r--r--include/media/v4l2-tpg-colors.h (renamed from drivers/media/platform/vivid/vivid-tpg-colors.h)6
-rw-r--r--include/media/v4l2-tpg.h (renamed from drivers/media/platform/vivid/vivid-tpg.h)9
-rw-r--r--include/media/vsp1.h23
-rw-r--r--include/uapi/linux/videodev2.h38
-rw-r--r--samples/Makefile2
-rw-r--r--samples/v4l/Makefile (renamed from Documentation/video4linux/Makefile)0
-rw-r--r--samples/v4l/v4l2-pci-skeleton.c (renamed from Documentation/video4linux/v4l2-pci-skeleton.c)5
192 files changed, 6757 insertions, 3001 deletions
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index 184f3c7b5145..893b2cabf7e4 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -233,6 +233,7 @@ X!Isound/sound_firmware.c
233!Iinclude/media/v4l2-mediabus.h 233!Iinclude/media/v4l2-mediabus.h
234!Iinclude/media/v4l2-mem2mem.h 234!Iinclude/media/v4l2-mem2mem.h
235!Iinclude/media/v4l2-of.h 235!Iinclude/media/v4l2-of.h
236!Iinclude/media/v4l2-rect.h
236!Iinclude/media/v4l2-subdev.h 237!Iinclude/media/v4l2-subdev.h
237!Iinclude/media/videobuf2-core.h 238!Iinclude/media/videobuf2-core.h
238!Iinclude/media/videobuf2-v4l2.h 239!Iinclude/media/videobuf2-v4l2.h
diff --git a/Documentation/DocBook/media/dvb/net.xml b/Documentation/DocBook/media/dvb/net.xml
index d2e44b7e07df..da095ed0b75c 100644
--- a/Documentation/DocBook/media/dvb/net.xml
+++ b/Documentation/DocBook/media/dvb/net.xml
@@ -15,7 +15,7 @@
15 that are present on the transport stream. This is done through 15 that are present on the transport stream. This is done through
16 <constant>/dev/dvb/adapter?/net?</constant> device node. 16 <constant>/dev/dvb/adapter?/net?</constant> device node.
17 The data will be available via virtual <constant>dvb?_?</constant> 17 The data will be available via virtual <constant>dvb?_?</constant>
18 network interfaces, and will be controled/routed via the standard 18 network interfaces, and will be controlled/routed via the standard
19 ip tools (like ip, route, netstat, ifconfig, etc).</para> 19 ip tools (like ip, route, netstat, ifconfig, etc).</para>
20<para> Data types and and ioctl definitions are defined via 20<para> Data types and and ioctl definitions are defined via
21 <constant>linux/dvb/net.h</constant> header.</para> 21 <constant>linux/dvb/net.h</constant> header.</para>
diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
index 5399e8904715..82fa328abd58 100644
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ b/Documentation/DocBook/media/v4l/compat.xml
@@ -2686,50 +2686,12 @@ and may change in the future.</para>
2686 2686
2687 <itemizedlist> 2687 <itemizedlist>
2688 <listitem> 2688 <listitem>
2689 <para>Video Output Overlay (OSD) Interface, <xref
2690 linkend="osd" />.</para>
2691 </listitem>
2692 <listitem>
2693 <para>&VIDIOC-DBG-G-REGISTER; and &VIDIOC-DBG-S-REGISTER; 2689 <para>&VIDIOC-DBG-G-REGISTER; and &VIDIOC-DBG-S-REGISTER;
2694ioctls.</para> 2690ioctls.</para>
2695 </listitem> 2691 </listitem>
2696 <listitem> 2692 <listitem>
2697 <para>&VIDIOC-DBG-G-CHIP-INFO; ioctl.</para> 2693 <para>&VIDIOC-DBG-G-CHIP-INFO; ioctl.</para>
2698 </listitem> 2694 </listitem>
2699 <listitem>
2700 <para>&VIDIOC-ENUM-DV-TIMINGS;, &VIDIOC-QUERY-DV-TIMINGS; and
2701 &VIDIOC-DV-TIMINGS-CAP; ioctls.</para>
2702 </listitem>
2703 <listitem>
2704 <para>Flash API. <xref linkend="flash-controls" /></para>
2705 </listitem>
2706 <listitem>
2707 <para>&VIDIOC-CREATE-BUFS; and &VIDIOC-PREPARE-BUF; ioctls.</para>
2708 </listitem>
2709 <listitem>
2710 <para>Selection API. <xref linkend="selection-api" /></para>
2711 </listitem>
2712 <listitem>
2713 <para>Sub-device selection API: &VIDIOC-SUBDEV-G-SELECTION;
2714 and &VIDIOC-SUBDEV-S-SELECTION; ioctls.</para>
2715 </listitem>
2716 <listitem>
2717 <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
2718 </listitem>
2719 <listitem>
2720 <para>Vendor and device specific media bus pixel formats.
2721 <xref linkend="v4l2-mbus-vendor-spec-fmts" />.</para>
2722 </listitem>
2723 <listitem>
2724 <para>Importing DMABUF file descriptors as a new IO method described
2725 in <xref linkend="dmabuf" />.</para>
2726 </listitem>
2727 <listitem>
2728 <para>Exporting DMABUF files using &VIDIOC-EXPBUF; ioctl.</para>
2729 </listitem>
2730 <listitem>
2731 <para>Software Defined Radio (SDR) Interface, <xref linkend="sdr" />.</para>
2732 </listitem>
2733 </itemizedlist> 2695 </itemizedlist>
2734 </section> 2696 </section>
2735 2697
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 361040e6b0f4..81efa883f67d 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -4272,13 +4272,6 @@ manually or automatically if set to zero. Unit, range and step are driver-specif
4272 <section id="flash-controls"> 4272 <section id="flash-controls">
4273 <title>Flash Control Reference</title> 4273 <title>Flash Control Reference</title>
4274 4274
4275 <note>
4276 <title>Experimental</title>
4277
4278 <para>This is an <link linkend="experimental">experimental</link>
4279interface and may change in the future.</para>
4280 </note>
4281
4282 <para> 4275 <para>
4283 The V4L2 flash controls are intended to provide generic access 4276 The V4L2 flash controls are intended to provide generic access
4284 to flash controller devices. Flash controller devices are 4277 to flash controller devices. Flash controller devices are
@@ -4743,14 +4736,6 @@ interface and may change in the future.</para>
4743 <section id="image-source-controls"> 4736 <section id="image-source-controls">
4744 <title>Image Source Control Reference</title> 4737 <title>Image Source Control Reference</title>
4745 4738
4746 <note>
4747 <title>Experimental</title>
4748
4749 <para>This is an <link
4750 linkend="experimental">experimental</link> interface and may
4751 change in the future.</para>
4752 </note>
4753
4754 <para> 4739 <para>
4755 The Image Source control class is intended for low-level 4740 The Image Source control class is intended for low-level
4756 control of image source devices such as image sensors. The 4741 control of image source devices such as image sensors. The
@@ -4862,14 +4847,6 @@ interface and may change in the future.</para>
4862 <section id="image-process-controls"> 4847 <section id="image-process-controls">
4863 <title>Image Process Control Reference</title> 4848 <title>Image Process Control Reference</title>
4864 4849
4865 <note>
4866 <title>Experimental</title>
4867
4868 <para>This is an <link
4869 linkend="experimental">experimental</link> interface and may
4870 change in the future.</para>
4871 </note>
4872
4873 <para> 4850 <para>
4874 The Image Process control class is intended for low-level control of 4851 The Image Process control class is intended for low-level control of
4875 image processing functions. Unlike 4852 image processing functions. Unlike
@@ -4955,14 +4932,6 @@ interface and may change in the future.</para>
4955 <section id="dv-controls"> 4932 <section id="dv-controls">
4956 <title>Digital Video Control Reference</title> 4933 <title>Digital Video Control Reference</title>
4957 4934
4958 <note>
4959 <title>Experimental</title>
4960
4961 <para>This is an <link
4962 linkend="experimental">experimental</link> interface and may
4963 change in the future.</para>
4964 </note>
4965
4966 <para> 4935 <para>
4967 The Digital Video control class is intended to control receivers 4936 The Digital Video control class is intended to control receivers
4968 and transmitters for <ulink url="http://en.wikipedia.org/wiki/Vga">VGA</ulink>, 4937 and transmitters for <ulink url="http://en.wikipedia.org/wiki/Vga">VGA</ulink>,
diff --git a/Documentation/DocBook/media/v4l/dev-sdr.xml b/Documentation/DocBook/media/v4l/dev-sdr.xml
index a659771f7b7c..6da1157fb5bd 100644
--- a/Documentation/DocBook/media/v4l/dev-sdr.xml
+++ b/Documentation/DocBook/media/v4l/dev-sdr.xml
@@ -1,11 +1,5 @@
1 <title>Software Defined Radio Interface (SDR)</title> 1 <title>Software Defined Radio Interface (SDR)</title>
2 2
3 <note>
4 <title>Experimental</title>
5 <para>This is an <link linkend="experimental"> experimental </link>
6 interface and may change in the future.</para>
7 </note>
8
9 <para> 3 <para>
10SDR is an abbreviation of Software Defined Radio, the radio device 4SDR is an abbreviation of Software Defined Radio, the radio device
11which uses application software for modulation or demodulation. This interface 5which uses application software for modulation or demodulation. This interface
diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml
index 4f0ba58c9bd9..f4bc27af83eb 100644
--- a/Documentation/DocBook/media/v4l/dev-subdev.xml
+++ b/Documentation/DocBook/media/v4l/dev-subdev.xml
@@ -1,11 +1,5 @@
1 <title>Sub-device Interface</title> 1 <title>Sub-device Interface</title>
2 2
3 <note>
4 <title>Experimental</title>
5 <para>This is an <link linkend="experimental">experimental</link>
6 interface and may change in the future.</para>
7 </note>
8
9 <para>The complex nature of V4L2 devices, where hardware is often made of 3 <para>The complex nature of V4L2 devices, where hardware is often made of
10 several integrated circuits that need to interact with each other in a 4 several integrated circuits that need to interact with each other in a
11 controlled way, leads to complex V4L2 drivers. The drivers usually reflect 5 controlled way, leads to complex V4L2 drivers. The drivers usually reflect
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index 144158b3a5ac..e09025db92bd 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -475,12 +475,6 @@ rest should be evident.</para>
475 <section id="dmabuf"> 475 <section id="dmabuf">
476 <title>Streaming I/O (DMA buffer importing)</title> 476 <title>Streaming I/O (DMA buffer importing)</title>
477 477
478 <note>
479 <title>Experimental</title>
480 <para>This is an <link linkend="experimental">experimental</link>
481 interface and may change in the future.</para>
482 </note>
483
484<para>The DMABUF framework provides a generic method for sharing buffers 478<para>The DMABUF framework provides a generic method for sharing buffers
485between multiple devices. Device drivers that support DMABUF can export a DMA 479between multiple devices. Device drivers that support DMABUF can export a DMA
486buffer to userspace as a file descriptor (known as the exporter role), import a 480buffer to userspace as a file descriptor (known as the exporter role), import a
diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml
index 28cbded766c9..b764cba150d1 100644
--- a/Documentation/DocBook/media/v4l/selection-api.xml
+++ b/Documentation/DocBook/media/v4l/selection-api.xml
@@ -1,13 +1,6 @@
1<section id="selection-api"> 1<section id="selection-api">
2 2
3 <title>Experimental API for cropping, composing and scaling</title> 3 <title>API for cropping, composing and scaling</title>
4
5 <note>
6 <title>Experimental</title>
7
8 <para>This is an <link linkend="experimental">experimental</link>
9interface and may change in the future.</para>
10 </note>
11 4
12 <section> 5 <section>
13 <title>Introduction</title> 6 <title>Introduction</title>
diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml
index 4e73345e3eab..199c84e3aede 100644
--- a/Documentation/DocBook/media/v4l/subdev-formats.xml
+++ b/Documentation/DocBook/media/v4l/subdev-formats.xml
@@ -4002,12 +4002,6 @@ see <xref linkend="colorspaces" />.</entry>
4002 <section id="v4l2-mbus-vendor-spec-fmts"> 4002 <section id="v4l2-mbus-vendor-spec-fmts">
4003 <title>Vendor and Device Specific Formats</title> 4003 <title>Vendor and Device Specific Formats</title>
4004 4004
4005 <note>
4006 <title>Experimental</title>
4007 <para>This is an <link linkend="experimental">experimental</link>
4008interface and may change in the future.</para>
4009 </note>
4010
4011 <para>This section lists complex data formats that are either vendor or 4005 <para>This section lists complex data formats that are either vendor or
4012 device specific. 4006 device specific.
4013 </para> 4007 </para>
diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
index d81fa0d4016b..6528e97b8990 100644
--- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
@@ -49,12 +49,6 @@
49 <refsect1> 49 <refsect1>
50 <title>Description</title> 50 <title>Description</title>
51 51
52 <note>
53 <title>Experimental</title>
54 <para>This is an <link linkend="experimental"> experimental </link>
55 interface and may change in the future.</para>
56 </note>
57
58 <para>This ioctl is used to create buffers for <link linkend="mmap">memory 52 <para>This ioctl is used to create buffers for <link linkend="mmap">memory
59mapped</link> or <link linkend="userp">user pointer</link> or <link 53mapped</link> or <link linkend="userp">user pointer</link> or <link
60linkend="dmabuf">DMA buffer</link> I/O. It can be used as an alternative or in 54linkend="dmabuf">DMA buffer</link> I/O. It can be used as an alternative or in
diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
index a2017bfcaed2..ca9ffce9b4c1 100644
--- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
@@ -49,14 +49,9 @@
49 <refsect1> 49 <refsect1>
50 <title>Description</title> 50 <title>Description</title>
51 51
52 <note> 52 <para>To query the capabilities of the DV receiver/transmitter applications initialize the
53 <title>Experimental</title> 53<structfield>pad</structfield> field to 0, zero the reserved array of &v4l2-dv-timings-cap;
54 <para>This is an <link linkend="experimental"> experimental </link> 54and call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node
55 interface and may change in the future.</para>
56 </note>
57
58 <para>To query the capabilities of the DV receiver/transmitter applications
59can call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node
60and the driver will fill in the structure. Note that drivers may return 55and the driver will fill in the structure. Note that drivers may return
61different values after switching the video input or output.</para> 56different values after switching the video input or output.</para>
62 57
@@ -65,8 +60,8 @@ queried by calling the <constant>VIDIOC_SUBDEV_DV_TIMINGS_CAP</constant> ioctl
65directly on a subdevice node. The capabilities are specific to inputs (for DV 60directly on a subdevice node. The capabilities are specific to inputs (for DV
66receivers) or outputs (for DV transmitters), applications must specify the 61receivers) or outputs (for DV transmitters), applications must specify the
67desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield> 62desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield>
68field. Attempts to query capabilities on a pad that doesn't support them will 63field and zero the <structfield>reserved</structfield> array. Attempts to query
69return an &EINVAL;.</para> 64capabilities on a pad that doesn't support them will return an &EINVAL;.</para>
70 65
71 <table pgwide="1" frame="none" id="v4l2-bt-timings-cap"> 66 <table pgwide="1" frame="none" id="v4l2-bt-timings-cap">
72 <title>struct <structname>v4l2_bt_timings_cap</structname></title> 67 <title>struct <structname>v4l2_bt_timings_cap</structname></title>
@@ -145,7 +140,8 @@ return an &EINVAL;.</para>
145 <row> 140 <row>
146 <entry>__u32</entry> 141 <entry>__u32</entry>
147 <entry><structfield>reserved</structfield>[2]</entry> 142 <entry><structfield>reserved</structfield>[2]</entry>
148 <entry>Reserved for future extensions. Drivers must set the array to zero.</entry> 143 <entry>Reserved for future extensions. Drivers and applications must
144 set the array to zero.</entry>
149 </row> 145 </row>
150 <row> 146 <row>
151 <entry>union</entry> 147 <entry>union</entry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
index 6e3cadd4e1f9..9b3d42018b69 100644
--- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
@@ -49,20 +49,15 @@
49 <refsect1> 49 <refsect1>
50 <title>Description</title> 50 <title>Description</title>
51 51
52 <note>
53 <title>Experimental</title>
54 <para>This is an <link linkend="experimental"> experimental </link>
55 interface and may change in the future.</para>
56 </note>
57
58 <para>While some DV receivers or transmitters support a wide range of timings, others 52 <para>While some DV receivers or transmitters support a wide range of timings, others
59support only a limited number of timings. With this ioctl applications can enumerate a list 53support only a limited number of timings. With this ioctl applications can enumerate a list
60of known supported timings. Call &VIDIOC-DV-TIMINGS-CAP; to check if it also supports other 54of known supported timings. Call &VIDIOC-DV-TIMINGS-CAP; to check if it also supports other
61standards or even custom timings that are not in this list.</para> 55standards or even custom timings that are not in this list.</para>
62 56
63 <para>To query the available timings, applications initialize the 57 <para>To query the available timings, applications initialize the
64<structfield>index</structfield> field and zero the reserved array of &v4l2-enum-dv-timings; 58<structfield>index</structfield> field, set the <structfield>pad</structfield> field to 0,
65and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a 59zero the reserved array of &v4l2-enum-dv-timings; and call the
60<constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a
66pointer to this structure. Drivers fill the rest of the structure or return an 61pointer to this structure. Drivers fill the rest of the structure or return an
67&EINVAL; when the index is out of bounds. To enumerate all supported DV timings, 62&EINVAL; when the index is out of bounds. To enumerate all supported DV timings,
68applications shall begin at index zero, incrementing by one until the 63applications shall begin at index zero, incrementing by one until the
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml
index 4e8ea65f7282..a0608abc1ab8 100644
--- a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml
@@ -49,12 +49,6 @@
49 <refsect1> 49 <refsect1>
50 <title>Description</title> 50 <title>Description</title>
51 51
52 <note>
53 <title>Experimental</title>
54 <para>This is an <link linkend="experimental"> experimental </link>
55 interface and may change in the future.</para>
56 </note>
57
58 <para>Enumerates the frequency bands that a tuner or modulator supports. 52 <para>Enumerates the frequency bands that a tuner or modulator supports.
59To do this applications initialize the <structfield>tuner</structfield>, 53To do this applications initialize the <structfield>tuner</structfield>,
60<structfield>type</structfield> and <structfield>index</structfield> fields, 54<structfield>type</structfield> and <structfield>index</structfield> fields,
diff --git a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
index 0ae0b6a915d0..a6558a676ef3 100644
--- a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
@@ -49,12 +49,6 @@
49 <refsect1> 49 <refsect1>
50 <title>Description</title> 50 <title>Description</title>
51 51
52 <note>
53 <title>Experimental</title>
54 <para>This is an <link linkend="experimental"> experimental </link>
55 interface and may change in the future.</para>
56 </note>
57
58<para>This ioctl is an extension to the <link linkend="mmap">memory 52<para>This ioctl is an extension to the <link linkend="mmap">memory
59mapping</link> I/O method, therefore it is available only for 53mapping</link> I/O method, therefore it is available only for
60<constant>V4L2_MEMORY_MMAP</constant> buffers. It can be used to export a 54<constant>V4L2_MEMORY_MMAP</constant> buffers. It can be used to export a
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-edid.xml b/Documentation/DocBook/media/v4l/vidioc-g-edid.xml
index 2702536bbc7c..b7602d30f596 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-edid.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-edid.xml
@@ -1,6 +1,6 @@
1<refentry id="vidioc-g-edid"> 1<refentry id="vidioc-g-edid">
2 <refmeta> 2 <refmeta>
3 <refentrytitle>ioctl VIDIOC_G_EDID, VIDIOC_S_EDID</refentrytitle> 3 <refentrytitle>ioctl VIDIOC_G_EDID, VIDIOC_S_EDID, VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID</refentrytitle>
4 &manvol; 4 &manvol;
5 </refmeta> 5 </refmeta>
6 6
@@ -71,7 +71,8 @@
71 71
72 <para>To get the EDID data the application has to fill in the <structfield>pad</structfield>, 72 <para>To get the EDID data the application has to fill in the <structfield>pad</structfield>,
73 <structfield>start_block</structfield>, <structfield>blocks</structfield> and <structfield>edid</structfield> 73 <structfield>start_block</structfield>, <structfield>blocks</structfield> and <structfield>edid</structfield>
74 fields and call <constant>VIDIOC_G_EDID</constant>. The current EDID from block 74 fields, zero the <structfield>reserved</structfield> array and call
75 <constant>VIDIOC_G_EDID</constant>. The current EDID from block
75 <structfield>start_block</structfield> and of size <structfield>blocks</structfield> 76 <structfield>start_block</structfield> and of size <structfield>blocks</structfield>
76 will be placed in the memory <structfield>edid</structfield> points to. The <structfield>edid</structfield> 77 will be placed in the memory <structfield>edid</structfield> points to. The <structfield>edid</structfield>
77 pointer must point to memory at least <structfield>blocks</structfield>&nbsp;*&nbsp;128 bytes 78 pointer must point to memory at least <structfield>blocks</structfield>&nbsp;*&nbsp;128 bytes
@@ -92,8 +93,9 @@
92 the driver will set <structfield>blocks</structfield> to 0 and it returns 0.</para> 93 the driver will set <structfield>blocks</structfield> to 0 and it returns 0.</para>
93 94
94 <para>To set the EDID blocks of a receiver the application has to fill in the <structfield>pad</structfield>, 95 <para>To set the EDID blocks of a receiver the application has to fill in the <structfield>pad</structfield>,
95 <structfield>blocks</structfield> and <structfield>edid</structfield> fields and set 96 <structfield>blocks</structfield> and <structfield>edid</structfield> fields, set
96 <structfield>start_block</structfield> to 0. It is not possible to set part of an EDID, 97 <structfield>start_block</structfield> to 0 and zero the <structfield>reserved</structfield> array.
98 It is not possible to set part of an EDID,
97 it is always all or nothing. Setting the EDID data is only valid for receivers as it makes 99 it is always all or nothing. Setting the EDID data is only valid for receivers as it makes
98 no sense for a transmitter.</para> 100 no sense for a transmitter.</para>
99 101
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
index 7865351688da..9523bc5650f9 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
@@ -50,12 +50,6 @@
50 <refsect1> 50 <refsect1>
51 <title>Description</title> 51 <title>Description</title>
52 52
53 <note>
54 <title>Experimental</title>
55 <para>This is an <link linkend="experimental"> experimental </link>
56 interface and may change in the future.</para>
57 </note>
58
59 <para>The ioctls are used to query and configure selection rectangles.</para> 53 <para>The ioctls are used to query and configure selection rectangles.</para>
60 54
61<para>To query the cropping (composing) rectangle set &v4l2-selection; 55<para>To query the cropping (composing) rectangle set &v4l2-selection;
diff --git a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
index fa7ad7e33228..7bde698760e4 100644
--- a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
@@ -48,12 +48,6 @@
48 <refsect1> 48 <refsect1>
49 <title>Description</title> 49 <title>Description</title>
50 50
51 <note>
52 <title>Experimental</title>
53 <para>This is an <link linkend="experimental"> experimental </link>
54 interface and may change in the future.</para>
55 </note>
56
57 <para>Applications can optionally call the 51 <para>Applications can optionally call the
58<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer 52<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
59to the driver before actually enqueuing it, using the 53to the driver before actually enqueuing it, using the
diff --git a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml
index 0c93677d16b4..d41bf47ee5a2 100644
--- a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml
@@ -50,12 +50,6 @@ input</refpurpose>
50 <refsect1> 50 <refsect1>
51 <title>Description</title> 51 <title>Description</title>
52 52
53 <note>
54 <title>Experimental</title>
55 <para>This is an <link linkend="experimental"> experimental </link>
56 interface and may change in the future.</para>
57 </note>
58
59 <para>The hardware may be able to detect the current DV timings 53 <para>The hardware may be able to detect the current DV timings
60automatically, similar to sensing the video standard. To do so, applications 54automatically, similar to sensing the video standard. To do so, applications
61call <constant>VIDIOC_QUERY_DV_TIMINGS</constant> with a pointer to a 55call <constant>VIDIOC_QUERY_DV_TIMINGS</constant> with a pointer to a
diff --git a/Documentation/DocBook/media/v4l/vidioc-streamon.xml b/Documentation/DocBook/media/v4l/vidioc-streamon.xml
index df2c63d07bac..89fd7ce964f9 100644
--- a/Documentation/DocBook/media/v4l/vidioc-streamon.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-streamon.xml
@@ -123,6 +123,14 @@ synchronize with other events.</para>
123 </para> 123 </para>
124 </listitem> 124 </listitem>
125 </varlistentry> 125 </varlistentry>
126 <varlistentry>
127 <term><errorcode>ENOLINK</errorcode></term>
128 <listitem>
129 <para>The driver implements Media Controller interface and
130 the pipeline link configuration is invalid.
131 </para>
132 </listitem>
133 </varlistentry>
126 </variablelist> 134 </variablelist>
127 </refsect1> 135 </refsect1>
128</refentry> 136</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml
index cff59f5cbf04..9d0251a27e5f 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml
@@ -49,12 +49,6 @@
49 <refsect1> 49 <refsect1>
50 <title>Description</title> 50 <title>Description</title>
51 51
52 <note>
53 <title>Experimental</title>
54 <para>This is an <link linkend="experimental">experimental</link>
55 interface and may change in the future.</para>
56 </note>
57
58 <para>This ioctl lets applications enumerate available frame intervals on a 52 <para>This ioctl lets applications enumerate available frame intervals on a
59 given sub-device pad. Frame intervals only makes sense for sub-devices that 53 given sub-device pad. Frame intervals only makes sense for sub-devices that
60 can control the frame period on their own. This includes, for instance, 54 can control the frame period on their own. This includes, for instance,
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml
index abd545ede67a..9b91b8332ba9 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml
@@ -49,12 +49,6 @@
49 <refsect1> 49 <refsect1>
50 <title>Description</title> 50 <title>Description</title>
51 51
52 <note>
53 <title>Experimental</title>
54 <para>This is an <link linkend="experimental">experimental</link>
55 interface and may change in the future.</para>
56 </note>
57
58 <para>This ioctl allows applications to enumerate all frame sizes 52 <para>This ioctl allows applications to enumerate all frame sizes
59 supported by a sub-device on the given pad for the given media bus format. 53 supported by a sub-device on the given pad for the given media bus format.
60 Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE; 54 Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE;
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml
index 0bcb278fd062..c67256ada87a 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml
@@ -49,12 +49,6 @@
49 <refsect1> 49 <refsect1>
50 <title>Description</title> 50 <title>Description</title>
51 51
52 <note>
53 <title>Experimental</title>
54 <para>This is an <link linkend="experimental">experimental</link>
55 interface and may change in the future.</para>
56 </note>
57
58 <para>To enumerate media bus formats available at a given sub-device pad 52 <para>To enumerate media bus formats available at a given sub-device pad
59 applications initialize the <structfield>pad</structfield>, <structfield>which</structfield> 53 applications initialize the <structfield>pad</structfield>, <structfield>which</structfield>
60 and <structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and 54 and <structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml
index a67cde6f8c54..781089cba453 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml
@@ -50,12 +50,6 @@
50 <refsect1> 50 <refsect1>
51 <title>Description</title> 51 <title>Description</title>
52 52
53 <note>
54 <title>Experimental</title>
55 <para>This is an <link linkend="experimental">experimental</link>
56 interface and may change in the future.</para>
57 </note>
58
59 <para>These ioctls are used to negotiate the frame format at specific 53 <para>These ioctls are used to negotiate the frame format at specific
60 subdev pads in the image pipeline.</para> 54 subdev pads in the image pipeline.</para>
61 55
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml
index 0bc3ea22d31f..848ec789ddaa 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml
@@ -50,12 +50,6 @@
50 <refsect1> 50 <refsect1>
51 <title>Description</title> 51 <title>Description</title>
52 52
53 <note>
54 <title>Experimental</title>
55 <para>This is an <link linkend="experimental">experimental</link>
56 interface and may change in the future.</para>
57 </note>
58
59 <para>These ioctls are used to get and set the frame interval at specific 53 <para>These ioctls are used to get and set the frame interval at specific
60 subdev pads in the image pipeline. The frame interval only makes sense for 54 subdev pads in the image pipeline. The frame interval only makes sense for
61 sub-devices that can control the frame period on their own. This includes, 55 sub-devices that can control the frame period on their own. This includes,
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
index c62a7360719b..8346b2e4a703 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
@@ -49,12 +49,6 @@
49 <refsect1> 49 <refsect1>
50 <title>Description</title> 50 <title>Description</title>
51 51
52 <note>
53 <title>Experimental</title>
54 <para>This is an <link linkend="experimental">experimental</link>
55 interface and may change in the future.</para>
56 </note>
57
58 <para>The selections are used to configure various image 52 <para>The selections are used to configure various image
59 processing functionality performed by the subdevs which affect the 53 processing functionality performed by the subdevs which affect the
60 image size. This currently includes cropping, scaling and 54 image size. This currently includes cropping, scaling and
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 1207d7907650..f3b04d22957c 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -1,4 +1,3 @@
1subdir-y := accounting auxdisplay blackfin connector \ 1subdir-y := accounting auxdisplay blackfin connector \
2 filesystems filesystems ia64 laptops mic misc-devices \ 2 filesystems filesystems ia64 laptops mic misc-devices \
3 networking pcmcia prctl ptp timers vDSO video4linux \ 3 networking pcmcia prctl ptp timers vDSO watchdog
4 watchdog
diff --git a/Documentation/devicetree/bindings/media/i2c/adv7180.txt b/Documentation/devicetree/bindings/media/i2c/adv7180.txt
new file mode 100644
index 000000000000..0d501154dfb2
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/adv7180.txt
@@ -0,0 +1,29 @@
1* Analog Devices ADV7180 analog video decoder family
2
3The adv7180 family devices are used to capture analog video to different
4digital interfaces like MIPI CSI-2 or parallel video.
5
6Required Properties :
7- compatible : value must be one of
8 "adi,adv7180"
9 "adi,adv7182"
10 "adi,adv7280"
11 "adi,adv7280-m"
12 "adi,adv7281"
13 "adi,adv7281-m"
14 "adi,adv7281-ma"
15 "adi,adv7282"
16 "adi,adv7282-m"
17
18Example:
19
20 i2c0@1c22000 {
21 ...
22 ...
23 adv7180@21 {
24 compatible = "adi,adv7180";
25 reg = <0x21>;
26 };
27 ...
28 };
29
diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt
index 619193ccf7ff..6a4e61cbe011 100644
--- a/Documentation/devicetree/bindings/media/rcar_vin.txt
+++ b/Documentation/devicetree/bindings/media/rcar_vin.txt
@@ -5,14 +5,22 @@ The rcar_vin device provides video input capabilities for the Renesas R-Car
5family of devices. The current blocks are always slaves and suppot one input 5family of devices. The current blocks are always slaves and suppot one input
6channel which can be either RGB, YUYV or BT656. 6channel which can be either RGB, YUYV or BT656.
7 7
8 - compatible: Must be one of the following 8 - compatible: Must be one or more of the following
9 - "renesas,vin-r8a7795" for the R8A7795 device 9 - "renesas,vin-r8a7795" for the R8A7795 device
10 - "renesas,vin-r8a7794" for the R8A7794 device 10 - "renesas,vin-r8a7794" for the R8A7794 device
11 - "renesas,vin-r8a7793" for the R8A7793 device 11 - "renesas,vin-r8a7793" for the R8A7793 device
12 - "renesas,vin-r8a7792" for the R8A7792 device
12 - "renesas,vin-r8a7791" for the R8A7791 device 13 - "renesas,vin-r8a7791" for the R8A7791 device
13 - "renesas,vin-r8a7790" for the R8A7790 device 14 - "renesas,vin-r8a7790" for the R8A7790 device
14 - "renesas,vin-r8a7779" for the R8A7779 device 15 - "renesas,vin-r8a7779" for the R8A7779 device
15 - "renesas,vin-r8a7778" for the R8A7778 device 16 - "renesas,vin-r8a7778" for the R8A7778 device
17 - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 compatible device.
18 - "renesas,rcar-gen3-vin" for a generic R-Car Gen3 compatible device.
19
20 When compatible with the generic version nodes must list the
21 SoC-specific version corresponding to the platform first
22 followed by the generic version.
23
16 - reg: the register base and size for the device registers 24 - reg: the register base and size for the device registers
17 - interrupts: the interrupt for the device 25 - interrupts: the interrupt for the device
18 - clocks: Reference to the parent clock 26 - clocks: Reference to the parent clock
@@ -37,7 +45,7 @@ Device node example
37 }; 45 };
38 46
39 vin0: vin@0xe6ef0000 { 47 vin0: vin@0xe6ef0000 {
40 compatible = "renesas,vin-r8a7790"; 48 compatible = "renesas,vin-r8a7790", "renesas,rcar-gen2-vin";
41 clocks = <&mstp8_clks R8A7790_CLK_VIN0>; 49 clocks = <&mstp8_clks R8A7790_CLK_VIN0>;
42 reg = <0 0xe6ef0000 0 0x1000>; 50 reg = <0 0xe6ef0000 0 0x1000>;
43 interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>; 51 interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/Documentation/devicetree/bindings/media/xilinx/video.txt b/Documentation/devicetree/bindings/media/xilinx/video.txt
index cbd46fa0988f..68ac210e688e 100644
--- a/Documentation/devicetree/bindings/media/xilinx/video.txt
+++ b/Documentation/devicetree/bindings/media/xilinx/video.txt
@@ -20,7 +20,7 @@ The following properties are common to all Xilinx video IP cores.
20- xlnx,video-format: This property represents a video format transmitted on an 20- xlnx,video-format: This property represents a video format transmitted on an
21 AXI bus between video IP cores, using its VF code as defined in "AXI4-Stream 21 AXI bus between video IP cores, using its VF code as defined in "AXI4-Stream
22 Video IP and System Design Guide" [UG934]. How the format relates to the IP 22 Video IP and System Design Guide" [UG934]. How the format relates to the IP
23 core is decribed in the IP core bindings documentation. 23 core is described in the IP core bindings documentation.
24 24
25- xlnx,video-width: This property qualifies the video format with the sample 25- xlnx,video-width: This property qualifies the video format with the sample
26 width expressed as a number of bits per pixel component. All components must 26 width expressed as a number of bits per pixel component. All components must
diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885
index 44a4cfbfdc40..85a8fdcfcdaa 100644
--- a/Documentation/video4linux/CARDLIST.cx23885
+++ b/Documentation/video4linux/CARDLIST.cx23885
@@ -52,3 +52,5 @@
52 51 -> DVBSky T982 [4254:0982] 52 51 -> DVBSky T982 [4254:0982]
53 52 -> Hauppauge WinTV-HVR5525 [0070:f038] 53 52 -> Hauppauge WinTV-HVR5525 [0070:f038]
54 53 -> Hauppauge WinTV Starburst [0070:c12a] 54 53 -> Hauppauge WinTV Starburst [0070:c12a]
55 54 -> ViewCast 260e [1576:0260]
56 55 -> ViewCast 460e [1576:0460]
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index 67209998a439..6784220c6a16 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -76,9 +76,9 @@
76 75 -> Dikom DK300 (em2882) 76 75 -> Dikom DK300 (em2882)
77 76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340] 77 76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340]
78 77 -> EM2874 Leadership ISDBT (em2874) 78 77 -> EM2874 Leadership ISDBT (em2874)
79 78 -> PCTV nanoStick T2 290e (em28174) 79 78 -> PCTV nanoStick T2 290e (em28174) [2013:024f]
80 79 -> Terratec Cinergy H5 (em2884) [eb1a:2885,0ccd:10a2,0ccd:10ad,0ccd:10b6] 80 79 -> Terratec Cinergy H5 (em2884) [eb1a:2885,0ccd:10a2,0ccd:10ad,0ccd:10b6]
81 80 -> PCTV DVB-S2 Stick (460e) (em28174) 81 80 -> PCTV DVB-S2 Stick (460e) (em28174) [2013:024c]
82 81 -> Hauppauge WinTV HVR 930C (em2884) [2040:1605] 82 81 -> Hauppauge WinTV HVR 930C (em2884) [2040:1605]
83 82 -> Terratec Cinergy HTC Stick (em2884) [0ccd:00b2] 83 82 -> Terratec Cinergy HTC Stick (em2884) [0ccd:00b2]
84 83 -> Honestech Vidbox NW03 (em2860) [eb1a:5006] 84 83 -> Honestech Vidbox NW03 (em2860) [eb1a:5006]
@@ -90,9 +90,11 @@
90 89 -> Delock 61959 (em2874) [1b80:e1cc] 90 89 -> Delock 61959 (em2874) [1b80:e1cc]
91 90 -> KWorld USB ATSC TV Stick UB435-Q V2 (em2874) [1b80:e346] 91 90 -> KWorld USB ATSC TV Stick UB435-Q V2 (em2874) [1b80:e346]
92 91 -> SpeedLink Vicious And Devine Laplace webcam (em2765) [1ae7:9003,1ae7:9004] 92 91 -> SpeedLink Vicious And Devine Laplace webcam (em2765) [1ae7:9003,1ae7:9004]
93 92 -> PCTV DVB-S2 Stick (461e) (em28178) 93 92 -> PCTV DVB-S2 Stick (461e) (em28178) [2013:0258]
94 93 -> KWorld USB ATSC TV Stick UB435-Q V3 (em2874) [1b80:e34c] 94 93 -> KWorld USB ATSC TV Stick UB435-Q V3 (em2874) [1b80:e34c]
95 94 -> PCTV tripleStick (292e) (em28178) 95 94 -> PCTV tripleStick (292e) (em28178) [2013:025f,2040:0264]
96 95 -> Leadtek VC100 (em2861) [0413:6f07] 96 95 -> Leadtek VC100 (em2861) [0413:6f07]
97 96 -> Terratec Cinergy T2 Stick HD (em28178) 97 96 -> Terratec Cinergy T2 Stick HD (em28178) [eb1a:8179]
98 97 -> Elgato EyeTV Hybrid 2008 INT (em2884) [0fd9:0018] 98 97 -> Elgato EyeTV Hybrid 2008 INT (em2884) [0fd9:0018]
99 98 -> PLEX PX-BCUD (em28178) [3275:0085]
100 99 -> Hauppauge WinTV-dualHD DVB (em28174) [2040:0265]
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index fa41608ab2b4..cbefc7902f5f 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -35,7 +35,7 @@ need and this same framework should make it much easier to refactor
35common code into utility functions shared by all drivers. 35common code into utility functions shared by all drivers.
36 36
37A good example to look at as a reference is the v4l2-pci-skeleton.c 37A good example to look at as a reference is the v4l2-pci-skeleton.c
38source that is available in this directory. It is a skeleton driver for 38source that is available in samples/v4l/. It is a skeleton driver for
39a PCI capture card, and demonstrates how to use the V4L2 driver 39a PCI capture card, and demonstrates how to use the V4L2 driver
40framework. It can be used as a template for real PCI video capture driver. 40framework. It can be used as a template for real PCI video capture driver.
41 41
diff --git a/Documentation/video4linux/vivid.txt b/Documentation/video4linux/vivid.txt
index e35d376b7f64..8da5d2a576bc 100644
--- a/Documentation/video4linux/vivid.txt
+++ b/Documentation/video4linux/vivid.txt
@@ -294,7 +294,7 @@ the result will be.
294 294
295These inputs support all combinations of the field setting. Special care has 295These inputs support all combinations of the field setting. Special care has
296been taken to faithfully reproduce how fields are handled for the different 296been taken to faithfully reproduce how fields are handled for the different
297TV standards. This is particularly noticable when generating a horizontally 297TV standards. This is particularly noticeable when generating a horizontally
298moving image so the temporal effect of using interlaced formats becomes clearly 298moving image so the temporal effect of using interlaced formats becomes clearly
299visible. For 50 Hz standards the top field is the oldest and the bottom field 299visible. For 50 Hz standards the top field is the oldest and the bottom field
300is the newest in time. For 60 Hz standards that is reversed: the bottom field 300is the newest in time. For 60 Hz standards that is reversed: the bottom field
@@ -313,7 +313,7 @@ will be SMPTE-170M.
313The pixel aspect ratio will depend on the TV standard. The video aspect ratio 313The pixel aspect ratio will depend on the TV standard. The video aspect ratio
314can be selected through the 'Standard Aspect Ratio' Vivid control. 314can be selected through the 'Standard Aspect Ratio' Vivid control.
315Choices are '4x3', '16x9' which will give letterboxed widescreen video and 315Choices are '4x3', '16x9' which will give letterboxed widescreen video and
316'16x9 Anomorphic' which will give full screen squashed anamorphic widescreen 316'16x9 Anamorphic' which will give full screen squashed anamorphic widescreen
317video that will need to be scaled accordingly. 317video that will need to be scaled accordingly.
318 318
319The TV 'tuner' supports a frequency range of 44-958 MHz. Channels are available 319The TV 'tuner' supports a frequency range of 44-958 MHz. Channels are available
@@ -862,7 +862,7 @@ RDS Radio Text:
862RDS Stereo: 862RDS Stereo:
863RDS Artificial Head: 863RDS Artificial Head:
864RDS Compressed: 864RDS Compressed:
865RDS Dymanic PTY: 865RDS Dynamic PTY:
866RDS Traffic Announcement: 866RDS Traffic Announcement:
867RDS Traffic Program: 867RDS Traffic Program:
868RDS Music: these are all controls that set the RDS data that is transmitted by 868RDS Music: these are all controls that set the RDS data that is transmitted by
diff --git a/MAINTAINERS b/MAINTAINERS
index c7dd1a3401e5..add406a46231 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11338,6 +11338,14 @@ W: https://linuxtv.org
11338S: Odd Fixes 11338S: Odd Fixes
11339F: drivers/media/pci/tw68/ 11339F: drivers/media/pci/tw68/
11340 11340
11341TW686X VIDEO4LINUX DRIVER
11342M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
11343L: linux-media@vger.kernel.org
11344T: git git://linuxtv.org/media_tree.git
11345W: http://linuxtv.org
11346S: Maintained
11347F: drivers/media/pci/tw686x/
11348
11341TPM DEVICE DRIVER 11349TPM DEVICE DRIVER
11342M: Peter Huewe <peterhuewe@gmx.de> 11350M: Peter Huewe <peterhuewe@gmx.de>
11343M: Marcel Selhorst <tpmdd@selhorst.net> 11351M: Marcel Selhorst <tpmdd@selhorst.net>
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index 21154dd87b0b..326df0ad75c0 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -19,3 +19,4 @@ config CYPRESS_FIRMWARE
19source "drivers/media/common/b2c2/Kconfig" 19source "drivers/media/common/b2c2/Kconfig"
20source "drivers/media/common/saa7146/Kconfig" 20source "drivers/media/common/saa7146/Kconfig"
21source "drivers/media/common/siano/Kconfig" 21source "drivers/media/common/siano/Kconfig"
22source "drivers/media/common/v4l2-tpg/Kconfig"
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile
index 89b795df2cdd..2d1b0a025084 100644
--- a/drivers/media/common/Makefile
+++ b/drivers/media/common/Makefile
@@ -1,4 +1,4 @@
1obj-y += b2c2/ saa7146/ siano/ 1obj-y += b2c2/ saa7146/ siano/ v4l2-tpg/
2obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o 2obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
3obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o 3obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
4obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o 4obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o
diff --git a/drivers/media/common/v4l2-tpg/Kconfig b/drivers/media/common/v4l2-tpg/Kconfig
new file mode 100644
index 000000000000..7456fc1c41ed
--- /dev/null
+++ b/drivers/media/common/v4l2-tpg/Kconfig
@@ -0,0 +1,2 @@
1config VIDEO_V4L2_TPG
2 tristate
diff --git a/drivers/media/common/v4l2-tpg/Makefile b/drivers/media/common/v4l2-tpg/Makefile
new file mode 100644
index 000000000000..f588df466ae3
--- /dev/null
+++ b/drivers/media/common/v4l2-tpg/Makefile
@@ -0,0 +1,3 @@
1v4l2-tpg-objs := v4l2-tpg-core.o v4l2-tpg-colors.o
2
3obj-$(CONFIG_VIDEO_V4L2_TPG) += v4l2-tpg.o
diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c
index 2299f0ce47c8..9bcbd318489b 100644
--- a/drivers/media/platform/vivid/vivid-tpg-colors.c
+++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * vivid-color.c - A table that converts colors to various colorspaces 2 * v4l2-tpg-colors.c - A table that converts colors to various colorspaces
3 * 3 *
4 * The test pattern generator uses the tpg_colors for its test patterns. 4 * The test pattern generator uses the tpg_colors for its test patterns.
5 * For testing colorspaces the first 8 colors of that table need to be 5 * For testing colorspaces the first 8 colors of that table need to be
@@ -12,7 +12,7 @@
12 * This source also contains the code used to generate the tpg_csc_colors 12 * This source also contains the code used to generate the tpg_csc_colors
13 * table. Run the following command to compile it: 13 * table. Run the following command to compile it:
14 * 14 *
15 * gcc vivid-tpg-colors.c -DCOMPILE_APP -o gen-colors -lm 15 * gcc v4l2-tpg-colors.c -DCOMPILE_APP -o gen-colors -lm
16 * 16 *
17 * and run the utility. 17 * and run the utility.
18 * 18 *
@@ -36,8 +36,7 @@
36 */ 36 */
37 37
38#include <linux/videodev2.h> 38#include <linux/videodev2.h>
39 39#include <media/v4l2-tpg-colors.h>
40#include "vivid-tpg-colors.h"
41 40
42/* sRGB colors with range [0-255] */ 41/* sRGB colors with range [0-255] */
43const struct color tpg_colors[TPG_COLOR_MAX] = { 42const struct color tpg_colors[TPG_COLOR_MAX] = {
diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
index da862bb2e5f8..cf1dadd0be9e 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * vivid-tpg.c - Test Pattern Generator 2 * v4l2-tpg-core.c - Test Pattern Generator
3 * 3 *
4 * Note: gen_twopix and tpg_gen_text are based on code from vivi.c. See the 4 * Note: gen_twopix and tpg_gen_text are based on code from vivi.c. See the
5 * vivi.c source for the copyright information of those functions. 5 * vivi.c source for the copyright information of those functions.
@@ -20,7 +20,8 @@
20 * SOFTWARE. 20 * SOFTWARE.
21 */ 21 */
22 22
23#include "vivid-tpg.h" 23#include <linux/module.h>
24#include <media/v4l2-tpg.h>
24 25
25/* Must remain in sync with enum tpg_pattern */ 26/* Must remain in sync with enum tpg_pattern */
26const char * const tpg_pattern_strings[] = { 27const char * const tpg_pattern_strings[] = {
@@ -48,6 +49,7 @@ const char * const tpg_pattern_strings[] = {
48 "Noise", 49 "Noise",
49 NULL 50 NULL
50}; 51};
52EXPORT_SYMBOL_GPL(tpg_pattern_strings);
51 53
52/* Must remain in sync with enum tpg_aspect */ 54/* Must remain in sync with enum tpg_aspect */
53const char * const tpg_aspect_strings[] = { 55const char * const tpg_aspect_strings[] = {
@@ -58,6 +60,7 @@ const char * const tpg_aspect_strings[] = {
58 "16x9 Anamorphic", 60 "16x9 Anamorphic",
59 NULL 61 NULL
60}; 62};
63EXPORT_SYMBOL_GPL(tpg_aspect_strings);
61 64
62/* 65/*
63 * Sine table: sin[0] = 127 * sin(-180 degrees) 66 * Sine table: sin[0] = 127 * sin(-180 degrees)
@@ -93,6 +96,7 @@ void tpg_set_font(const u8 *f)
93{ 96{
94 font8x16 = f; 97 font8x16 = f;
95} 98}
99EXPORT_SYMBOL_GPL(tpg_set_font);
96 100
97void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h) 101void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h)
98{ 102{
@@ -114,6 +118,7 @@ void tpg_init(struct tpg_data *tpg, unsigned w, unsigned h)
114 tpg->colorspace = V4L2_COLORSPACE_SRGB; 118 tpg->colorspace = V4L2_COLORSPACE_SRGB;
115 tpg->perc_fill = 100; 119 tpg->perc_fill = 100;
116} 120}
121EXPORT_SYMBOL_GPL(tpg_init);
117 122
118int tpg_alloc(struct tpg_data *tpg, unsigned max_w) 123int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
119{ 124{
@@ -150,6 +155,7 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
150 } 155 }
151 return 0; 156 return 0;
152} 157}
158EXPORT_SYMBOL_GPL(tpg_alloc);
153 159
154void tpg_free(struct tpg_data *tpg) 160void tpg_free(struct tpg_data *tpg)
155{ 161{
@@ -174,6 +180,7 @@ void tpg_free(struct tpg_data *tpg)
174 tpg->random_line[plane] = NULL; 180 tpg->random_line[plane] = NULL;
175 } 181 }
176} 182}
183EXPORT_SYMBOL_GPL(tpg_free);
177 184
178bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) 185bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
179{ 186{
@@ -403,6 +410,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
403 } 410 }
404 return true; 411 return true;
405} 412}
413EXPORT_SYMBOL_GPL(tpg_s_fourcc);
406 414
407void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop, 415void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop,
408 const struct v4l2_rect *compose) 416 const struct v4l2_rect *compose)
@@ -418,6 +426,7 @@ void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop,
418 tpg->scaled_width = 2; 426 tpg->scaled_width = 2;
419 tpg->recalc_lines = true; 427 tpg->recalc_lines = true;
420} 428}
429EXPORT_SYMBOL_GPL(tpg_s_crop_compose);
421 430
422void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height, 431void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
423 u32 field) 432 u32 field)
@@ -442,6 +451,7 @@ void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
442 (2 * tpg->hdownsampling[p]); 451 (2 * tpg->hdownsampling[p]);
443 tpg->recalc_square_border = true; 452 tpg->recalc_square_border = true;
444} 453}
454EXPORT_SYMBOL_GPL(tpg_reset_source);
445 455
446static enum tpg_color tpg_get_textbg_color(struct tpg_data *tpg) 456static enum tpg_color tpg_get_textbg_color(struct tpg_data *tpg)
447{ 457{
@@ -1250,6 +1260,7 @@ unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line)
1250 return 0; 1260 return 0;
1251 } 1261 }
1252} 1262}
1263EXPORT_SYMBOL_GPL(tpg_g_interleaved_plane);
1253 1264
1254/* Return how many pattern lines are used by the current pattern. */ 1265/* Return how many pattern lines are used by the current pattern. */
1255static unsigned tpg_get_pat_lines(const struct tpg_data *tpg) 1266static unsigned tpg_get_pat_lines(const struct tpg_data *tpg)
@@ -1725,6 +1736,7 @@ void tpg_gen_text(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
1725 } 1736 }
1726 } 1737 }
1727} 1738}
1739EXPORT_SYMBOL_GPL(tpg_gen_text);
1728 1740
1729void tpg_update_mv_step(struct tpg_data *tpg) 1741void tpg_update_mv_step(struct tpg_data *tpg)
1730{ 1742{
@@ -1773,6 +1785,7 @@ void tpg_update_mv_step(struct tpg_data *tpg)
1773 if (factor < 0) 1785 if (factor < 0)
1774 tpg->mv_vert_step = tpg->src_height - tpg->mv_vert_step; 1786 tpg->mv_vert_step = tpg->src_height - tpg->mv_vert_step;
1775} 1787}
1788EXPORT_SYMBOL_GPL(tpg_update_mv_step);
1776 1789
1777/* Map the line number relative to the crop rectangle to a frame line number */ 1790/* Map the line number relative to the crop rectangle to a frame line number */
1778static unsigned tpg_calc_frameline(const struct tpg_data *tpg, unsigned src_y, 1791static unsigned tpg_calc_frameline(const struct tpg_data *tpg, unsigned src_y,
@@ -1862,6 +1875,7 @@ void tpg_calc_text_basep(struct tpg_data *tpg,
1862 if (p == 0 && tpg->interleaved) 1875 if (p == 0 && tpg->interleaved)
1863 tpg_calc_text_basep(tpg, basep, 1, vbuf); 1876 tpg_calc_text_basep(tpg, basep, 1, vbuf);
1864} 1877}
1878EXPORT_SYMBOL_GPL(tpg_calc_text_basep);
1865 1879
1866static int tpg_pattern_avg(const struct tpg_data *tpg, 1880static int tpg_pattern_avg(const struct tpg_data *tpg,
1867 unsigned pat1, unsigned pat2) 1881 unsigned pat1, unsigned pat2)
@@ -1891,6 +1905,7 @@ void tpg_log_status(struct tpg_data *tpg)
1891 pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization); 1905 pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization);
1892 pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range); 1906 pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range);
1893} 1907}
1908EXPORT_SYMBOL_GPL(tpg_log_status);
1894 1909
1895/* 1910/*
1896 * This struct contains common parameters used by both the drawing of the 1911 * This struct contains common parameters used by both the drawing of the
@@ -2296,6 +2311,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
2296 vbuf + buf_line * params.stride); 2311 vbuf + buf_line * params.stride);
2297 } 2312 }
2298} 2313}
2314EXPORT_SYMBOL_GPL(tpg_fill_plane_buffer);
2299 2315
2300void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf) 2316void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
2301{ 2317{
@@ -2312,3 +2328,8 @@ void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
2312 offset += tpg_calc_plane_size(tpg, i); 2328 offset += tpg_calc_plane_size(tpg, i);
2313 } 2329 }
2314} 2330}
2331EXPORT_SYMBOL_GPL(tpg_fillbuffer);
2332
2333MODULE_DESCRIPTION("V4L2 Test Pattern Generator");
2334MODULE_AUTHOR("Hans Verkuil");
2335MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
index 0afad395ef97..a7a4674ccc40 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -58,6 +58,14 @@
58#define USB_VID_TELESTAR 0x10b9 58#define USB_VID_TELESTAR 0x10b9
59#define USB_VID_VISIONPLUS 0x13d3 59#define USB_VID_VISIONPLUS 0x13d3
60#define USB_VID_SONY 0x1415 60#define USB_VID_SONY 0x1415
61#define USB_PID_TEVII_S421 0xd421
62#define USB_PID_TEVII_S480_1 0xd481
63#define USB_PID_TEVII_S480_2 0xd482
64#define USB_PID_TEVII_S630 0xd630
65#define USB_PID_TEVII_S632 0xd632
66#define USB_PID_TEVII_S650 0xd650
67#define USB_PID_TEVII_S660 0xd660
68#define USB_PID_TEVII_S662 0xd662
61#define USB_VID_TWINHAN 0x1822 69#define USB_VID_TWINHAN 0x1822
62#define USB_VID_ULTIMA_ELECTRONIC 0x05d8 70#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
63#define USB_VID_UNIWILL 0x1584 71#define USB_VID_UNIWILL 0x1584
@@ -141,6 +149,7 @@
141#define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 149#define USB_PID_GENIUS_TVGO_DVB_T03 0x4012
142#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 150#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
143#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 151#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
152#define USB_PID_GOTVIEW_SAT_HD 0x5456
144#define USB_PID_INTEL_CE9500 0x9500 153#define USB_PID_INTEL_CE9500 0x9500
145#define USB_PID_ITETECH_IT9135 0x9135 154#define USB_PID_ITETECH_IT9135 0x9135
146#define USB_PID_ITETECH_IT9135_9005 0x9005 155#define USB_PID_ITETECH_IT9135_9005 0x9005
@@ -159,6 +168,8 @@
159#define USB_PID_KWORLD_UB499_2T_T09 0xe409 168#define USB_PID_KWORLD_UB499_2T_T09 0xe409
160#define USB_PID_KWORLD_VSTREAM_COLD 0x17de 169#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
161#define USB_PID_KWORLD_VSTREAM_WARM 0x17df 170#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
171#define USB_PID_PROF_1100 0xb012
172#define USB_PID_TERRATEC_CINERGY_S 0x0064
162#define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 173#define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055
163#define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 174#define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069
164#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093 175#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093
@@ -361,6 +372,8 @@
361#define USB_PID_YUAN_STK7700D 0x1efc 372#define USB_PID_YUAN_STK7700D 0x1efc
362#define USB_PID_YUAN_STK7700D_2 0x1e8c 373#define USB_PID_YUAN_STK7700D_2 0x1e8c
363#define USB_PID_DW2102 0x2102 374#define USB_PID_DW2102 0x2102
375#define USB_PID_DW2104 0x2104
376#define USB_PID_DW3101 0x3101
364#define USB_PID_XTENSIONS_XD_380 0x0381 377#define USB_PID_XTENSIONS_XD_380 0x0381
365#define USB_PID_TELESTAR_STARSTICK_2 0x8000 378#define USB_PID_TELESTAR_STARSTICK_2 0x8000
366#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 379#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807
@@ -373,6 +386,7 @@
373#define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 386#define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020
374#define USB_PID_ELGATO_EYETV_SAT 0x002a 387#define USB_PID_ELGATO_EYETV_SAT 0x002a
375#define USB_PID_ELGATO_EYETV_SAT_V2 0x0025 388#define USB_PID_ELGATO_EYETV_SAT_V2 0x0025
389#define USB_PID_ELGATO_EYETV_SAT_V3 0x0036
376#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 390#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000
377#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 391#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001
378#define USB_PID_FRIIO_WHITE 0x0001 392#define USB_PID_FRIIO_WHITE 0x0001
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index e1684c570e2f..75a3f4b57fd4 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -676,13 +676,13 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
676 demux, 0, MEDIA_LNK_FL_ENABLED, 676 demux, 0, MEDIA_LNK_FL_ENABLED,
677 false); 677 false);
678 if (ret) 678 if (ret)
679 return -ENOMEM; 679 return ret;
680 } 680 }
681 if (demux && ca) { 681 if (demux && ca) {
682 ret = media_create_pad_link(demux, 1, ca, 682 ret = media_create_pad_link(demux, 1, ca,
683 0, MEDIA_LNK_FL_ENABLED); 683 0, MEDIA_LNK_FL_ENABLED);
684 if (ret) 684 if (ret)
685 return -ENOMEM; 685 return ret;
686 } 686 }
687 687
688 /* Create demux links for each ringbuffer/pad */ 688 /* Create demux links for each ringbuffer/pad */
diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c
index dc2d41e144fd..d879dc0607f4 100644
--- a/drivers/media/dvb-frontends/dib0090.c
+++ b/drivers/media/dvb-frontends/dib0090.c
@@ -1121,7 +1121,7 @@ void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1121 (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND", 1121 (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND",
1122 state->identity.version & 0x1f); 1122 state->identity.version & 0x1f);
1123 1123
1124 if (rf_ramp && ((state->rf_ramp[0] == 0) || 1124 if (rf_ramp && ((state->rf_ramp && state->rf_ramp[0] == 0) ||
1125 (state->current_band == BAND_CBAND && 1125 (state->current_band == BAND_CBAND &&
1126 (state->identity.version & 0x1f) <= P1D_E_F))) { 1126 (state->identity.version & 0x1f) <= P1D_E_F))) {
1127 dprintk("DE-Engage mux for direct gain reg control"); 1127 dprintk("DE-Engage mux for direct gain reg control");
diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c
index e8fc0329ea64..addffc33993a 100644
--- a/drivers/media/dvb-frontends/ds3000.c
+++ b/drivers/media/dvb-frontends/ds3000.c
@@ -458,7 +458,7 @@ static int ds3000_read_status(struct dvb_frontend *fe, enum fe_status *status)
458 458
459 break; 459 break;
460 default: 460 default:
461 return 1; 461 return -EINVAL;
462 } 462 }
463 463
464 if (state->config->set_lock_led) 464 if (state->config->set_lock_led)
@@ -528,7 +528,7 @@ static int ds3000_read_ber(struct dvb_frontend *fe, u32* ber)
528 *ber = 0xffffffff; 528 *ber = 0xffffffff;
529 break; 529 break;
530 default: 530 default:
531 return 1; 531 return -EINVAL;
532 } 532 }
533 533
534 return 0; 534 return 0;
@@ -623,7 +623,7 @@ static int ds3000_read_snr(struct dvb_frontend *fe, u16 *snr)
623 snr_reading, *snr); 623 snr_reading, *snr);
624 break; 624 break;
625 default: 625 default:
626 return 1; 626 return -EINVAL;
627 } 627 }
628 628
629 return 0; 629 return 0;
@@ -661,7 +661,7 @@ static int ds3000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
661 state->prevUCBS2 = _ucblocks; 661 state->prevUCBS2 = _ucblocks;
662 break; 662 break;
663 default: 663 default:
664 return 1; 664 return -EINVAL;
665 } 665 }
666 666
667 return 0; 667 return 0;
@@ -754,7 +754,7 @@ static int ds3000_send_diseqc_msg(struct dvb_frontend *fe,
754 data |= 0x80; 754 data |= 0x80;
755 ds3000_writereg(state, 0xa2, data); 755 ds3000_writereg(state, 0xa2, data);
756 756
757 return 1; 757 return -ETIMEDOUT;
758 } 758 }
759 759
760 data = ds3000_readreg(state, 0xa2); 760 data = ds3000_readreg(state, 0xa2);
@@ -808,7 +808,7 @@ static int ds3000_diseqc_send_burst(struct dvb_frontend *fe,
808 data |= 0x80; 808 data |= 0x80;
809 ds3000_writereg(state, 0xa2, data); 809 ds3000_writereg(state, 0xa2, data);
810 810
811 return 1; 811 return -ETIMEDOUT;
812 } 812 }
813 813
814 data = ds3000_readreg(state, 0xa2); 814 data = ds3000_readreg(state, 0xa2);
@@ -951,7 +951,7 @@ static int ds3000_set_frontend(struct dvb_frontend *fe)
951 ds3000_writereg(state, 0xfe, 0x98); 951 ds3000_writereg(state, 0xfe, 0x98);
952 break; 952 break;
953 default: 953 default:
954 return 1; 954 return -EINVAL;
955 } 955 }
956 956
957 /* enable 27MHz clock output */ 957 /* enable 27MHz clock output */
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h
index eee8c22c51ec..651e005146b2 100644
--- a/drivers/media/dvb-frontends/m88ds3103_priv.h
+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h
@@ -46,7 +46,7 @@ struct m88ds3103_dev {
46 /* auto detect chip id to do different config */ 46 /* auto detect chip id to do different config */
47 u8 chip_id; 47 u8 chip_id;
48 /* main mclk is calculated for M88RS6000 dynamically */ 48 /* main mclk is calculated for M88RS6000 dynamically */
49 u32 mclk_khz; 49 s32 mclk_khz;
50 u64 post_bit_error; 50 u64 post_bit_error;
51 u64 post_bit_count; 51 u64 post_bit_count;
52}; 52};
diff --git a/drivers/media/dvb-frontends/zl10353.c b/drivers/media/dvb-frontends/zl10353.c
index 1832c2f7695c..3b08176d7bec 100644
--- a/drivers/media/dvb-frontends/zl10353.c
+++ b/drivers/media/dvb-frontends/zl10353.c
@@ -135,8 +135,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
135 135
136 value = (u64)10 * (1 << 23) / 7 * 125; 136 value = (u64)10 * (1 << 23) / 7 * 125;
137 value = (bw * value) + adc_clock / 2; 137 value = (bw * value) + adc_clock / 2;
138 do_div(value, adc_clock); 138 *nominal_rate = div_u64(value, adc_clock);
139 *nominal_rate = value;
140 139
141 dprintk("%s: bw %d, adc_clock %d => 0x%x\n", 140 dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
142 __func__, bw, adc_clock, *nominal_rate); 141 __func__, bw, adc_clock, *nominal_rate);
@@ -163,8 +162,7 @@ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
163 if (ife > adc_clock / 2) 162 if (ife > adc_clock / 2)
164 ife = adc_clock - ife; 163 ife = adc_clock - ife;
165 } 164 }
166 value = (u64)65536 * ife + adc_clock / 2; 165 value = div_u64((u64)65536 * ife + adc_clock / 2, adc_clock);
167 do_div(value, adc_clock);
168 *input_freq = -value; 166 *input_freq = -value;
169 167
170 dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n", 168 dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
index 788967dadd29..0462f461e679 100644
--- a/drivers/media/i2c/ad9389b.c
+++ b/drivers/media/i2c/ad9389b.c
@@ -1130,8 +1130,6 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id *
1130 hdl = &state->hdl; 1130 hdl = &state->hdl;
1131 v4l2_ctrl_handler_init(hdl, 5); 1131 v4l2_ctrl_handler_init(hdl, 5);
1132 1132
1133 /* private controls */
1134
1135 state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops, 1133 state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
1136 V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, 1134 V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
1137 0, V4L2_DV_TX_MODE_DVI_D); 1135 0, V4L2_DV_TX_MODE_DVI_D);
@@ -1151,12 +1149,6 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id *
1151 1149
1152 goto err_hdl; 1150 goto err_hdl;
1153 } 1151 }
1154 state->hdmi_mode_ctrl->is_private = true;
1155 state->hotplug_ctrl->is_private = true;
1156 state->rx_sense_ctrl->is_private = true;
1157 state->have_edid0_ctrl->is_private = true;
1158 state->rgb_quantization_range_ctrl->is_private = true;
1159
1160 state->pad.flags = MEDIA_PAD_FL_SINK; 1152 state->pad.flags = MEDIA_PAD_FL_SINK;
1161 err = media_entity_pads_init(&sd->entity, 1, &state->pad); 1153 err = media_entity_pads_init(&sd->entity, 1, &state->pad);
1162 if (err) 1154 if (err)
diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c
index fb7ed730d932..9e1731c565e7 100644
--- a/drivers/media/i2c/adp1653.c
+++ b/drivers/media/i2c/adp1653.c
@@ -466,9 +466,9 @@ static int adp1653_of_init(struct i2c_client *client,
466 of_node_put(child); 466 of_node_put(child);
467 467
468 pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW); 468 pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW);
469 if (!pd->enable_gpio) { 469 if (IS_ERR(pd->enable_gpio)) {
470 dev_err(&client->dev, "Error getting GPIO\n"); 470 dev_err(&client->dev, "Error getting GPIO\n");
471 return -EINVAL; 471 return PTR_ERR(pd->enable_gpio);
472 } 472 }
473 473
474 return 0; 474 return 0;
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index ff57c1dcb8af..b77b0a4dbf68 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -26,8 +26,9 @@
26#include <linux/i2c.h> 26#include <linux/i2c.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/of.h> 28#include <linux/of.h>
29#include <media/v4l2-ioctl.h>
30#include <linux/videodev2.h> 29#include <linux/videodev2.h>
30#include <media/v4l2-ioctl.h>
31#include <media/v4l2-event.h>
31#include <media/v4l2-device.h> 32#include <media/v4l2-device.h>
32#include <media/v4l2-ctrls.h> 33#include <media/v4l2-ctrls.h>
33#include <linux/mutex.h> 34#include <linux/mutex.h>
@@ -192,8 +193,8 @@ struct adv7180_state {
192 struct mutex mutex; /* mutual excl. when accessing chip */ 193 struct mutex mutex; /* mutual excl. when accessing chip */
193 int irq; 194 int irq;
194 v4l2_std_id curr_norm; 195 v4l2_std_id curr_norm;
195 bool autodetect;
196 bool powered; 196 bool powered;
197 bool streaming;
197 u8 input; 198 u8 input;
198 199
199 struct i2c_client *client; 200 struct i2c_client *client;
@@ -338,12 +339,26 @@ static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
338 if (err) 339 if (err)
339 return err; 340 return err;
340 341
341 /* when we are interrupt driven we know the state */ 342 if (state->streaming) {
342 if (!state->autodetect || state->irq > 0) 343 err = -EBUSY;
343 *std = state->curr_norm; 344 goto unlock;
344 else 345 }
345 err = __adv7180_status(state, NULL, std); 346
347 err = adv7180_set_video_standard(state,
348 ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM);
349 if (err)
350 goto unlock;
351
352 msleep(100);
353 __adv7180_status(state, NULL, std);
354
355 err = v4l2_std_to_adv7180(state->curr_norm);
356 if (err < 0)
357 goto unlock;
346 358
359 err = adv7180_set_video_standard(state, err);
360
361unlock:
347 mutex_unlock(&state->mutex); 362 mutex_unlock(&state->mutex);
348 return err; 363 return err;
349} 364}
@@ -387,23 +402,13 @@ static int adv7180_program_std(struct adv7180_state *state)
387{ 402{
388 int ret; 403 int ret;
389 404
390 if (state->autodetect) { 405 ret = v4l2_std_to_adv7180(state->curr_norm);
391 ret = adv7180_set_video_standard(state, 406 if (ret < 0)
392 ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM); 407 return ret;
393 if (ret < 0)
394 return ret;
395
396 __adv7180_status(state, NULL, &state->curr_norm);
397 } else {
398 ret = v4l2_std_to_adv7180(state->curr_norm);
399 if (ret < 0)
400 return ret;
401
402 ret = adv7180_set_video_standard(state, ret);
403 if (ret < 0)
404 return ret;
405 }
406 408
409 ret = adv7180_set_video_standard(state, ret);
410 if (ret < 0)
411 return ret;
407 return 0; 412 return 0;
408} 413}
409 414
@@ -415,18 +420,12 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
415 if (ret) 420 if (ret)
416 return ret; 421 return ret;
417 422
418 /* all standards -> autodetect */ 423 /* Make sure we can support this std */
419 if (std == V4L2_STD_ALL) { 424 ret = v4l2_std_to_adv7180(std);
420 state->autodetect = true; 425 if (ret < 0)
421 } else { 426 goto out;
422 /* Make sure we can support this std */
423 ret = v4l2_std_to_adv7180(std);
424 if (ret < 0)
425 goto out;
426 427
427 state->curr_norm = std; 428 state->curr_norm = std;
428 state->autodetect = false;
429 }
430 429
431 ret = adv7180_program_std(state); 430 ret = adv7180_program_std(state);
432out: 431out:
@@ -434,6 +433,15 @@ out:
434 return ret; 433 return ret;
435} 434}
436 435
436static int adv7180_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
437{
438 struct adv7180_state *state = to_state(sd);
439
440 *norm = state->curr_norm;
441
442 return 0;
443}
444
437static int adv7180_set_power(struct adv7180_state *state, bool on) 445static int adv7180_set_power(struct adv7180_state *state, bool on)
438{ 446{
439 u8 val; 447 u8 val;
@@ -717,17 +725,77 @@ static int adv7180_g_mbus_config(struct v4l2_subdev *sd,
717 return 0; 725 return 0;
718} 726}
719 727
728static int adv7180_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cropcap)
729{
730 struct adv7180_state *state = to_state(sd);
731
732 if (state->curr_norm & V4L2_STD_525_60) {
733 cropcap->pixelaspect.numerator = 11;
734 cropcap->pixelaspect.denominator = 10;
735 } else {
736 cropcap->pixelaspect.numerator = 54;
737 cropcap->pixelaspect.denominator = 59;
738 }
739
740 return 0;
741}
742
743static int adv7180_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm)
744{
745 *norm = V4L2_STD_ALL;
746 return 0;
747}
748
749static int adv7180_s_stream(struct v4l2_subdev *sd, int enable)
750{
751 struct adv7180_state *state = to_state(sd);
752 int ret;
753
754 /* It's always safe to stop streaming, no need to take the lock */
755 if (!enable) {
756 state->streaming = enable;
757 return 0;
758 }
759
760 /* Must wait until querystd released the lock */
761 ret = mutex_lock_interruptible(&state->mutex);
762 if (ret)
763 return ret;
764 state->streaming = enable;
765 mutex_unlock(&state->mutex);
766 return 0;
767}
768
769static int adv7180_subscribe_event(struct v4l2_subdev *sd,
770 struct v4l2_fh *fh,
771 struct v4l2_event_subscription *sub)
772{
773 switch (sub->type) {
774 case V4L2_EVENT_SOURCE_CHANGE:
775 return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
776 case V4L2_EVENT_CTRL:
777 return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
778 default:
779 return -EINVAL;
780 }
781}
782
720static const struct v4l2_subdev_video_ops adv7180_video_ops = { 783static const struct v4l2_subdev_video_ops adv7180_video_ops = {
721 .s_std = adv7180_s_std, 784 .s_std = adv7180_s_std,
785 .g_std = adv7180_g_std,
722 .querystd = adv7180_querystd, 786 .querystd = adv7180_querystd,
723 .g_input_status = adv7180_g_input_status, 787 .g_input_status = adv7180_g_input_status,
724 .s_routing = adv7180_s_routing, 788 .s_routing = adv7180_s_routing,
725 .g_mbus_config = adv7180_g_mbus_config, 789 .g_mbus_config = adv7180_g_mbus_config,
790 .cropcap = adv7180_cropcap,
791 .g_tvnorms = adv7180_g_tvnorms,
792 .s_stream = adv7180_s_stream,
726}; 793};
727 794
728
729static const struct v4l2_subdev_core_ops adv7180_core_ops = { 795static const struct v4l2_subdev_core_ops adv7180_core_ops = {
730 .s_power = adv7180_s_power, 796 .s_power = adv7180_s_power,
797 .subscribe_event = adv7180_subscribe_event,
798 .unsubscribe_event = v4l2_event_subdev_unsubscribe,
731}; 799};
732 800
733static const struct v4l2_subdev_pad_ops adv7180_pad_ops = { 801static const struct v4l2_subdev_pad_ops adv7180_pad_ops = {
@@ -752,8 +820,14 @@ static irqreturn_t adv7180_irq(int irq, void *devid)
752 /* clear */ 820 /* clear */
753 adv7180_write(state, ADV7180_REG_ICR3, isr3); 821 adv7180_write(state, ADV7180_REG_ICR3, isr3);
754 822
755 if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect) 823 if (isr3 & ADV7180_IRQ3_AD_CHANGE) {
756 __adv7180_status(state, NULL, &state->curr_norm); 824 static const struct v4l2_event src_ch = {
825 .type = V4L2_EVENT_SOURCE_CHANGE,
826 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
827 };
828
829 v4l2_subdev_notify_event(&state->sd, &src_ch);
830 }
757 mutex_unlock(&state->mutex); 831 mutex_unlock(&state->mutex);
758 832
759 return IRQ_HANDLED; 833 return IRQ_HANDLED;
@@ -1198,7 +1272,7 @@ static int adv7180_probe(struct i2c_client *client,
1198 1272
1199 state->irq = client->irq; 1273 state->irq = client->irq;
1200 mutex_init(&state->mutex); 1274 mutex_init(&state->mutex);
1201 state->autodetect = true; 1275 state->curr_norm = V4L2_STD_NTSC;
1202 if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED) 1276 if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED)
1203 state->powered = true; 1277 state->powered = true;
1204 else 1278 else
@@ -1206,7 +1280,7 @@ static int adv7180_probe(struct i2c_client *client,
1206 state->input = 0; 1280 state->input = 0;
1207 sd = &state->sd; 1281 sd = &state->sd;
1208 v4l2_i2c_subdev_init(sd, client, &adv7180_ops); 1282 v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
1209 sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; 1283 sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
1210 1284
1211 ret = adv7180_init_controls(state); 1285 ret = adv7180_init_controls(state);
1212 if (ret) 1286 if (ret)
@@ -1328,6 +1402,14 @@ static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume);
1328#ifdef CONFIG_OF 1402#ifdef CONFIG_OF
1329static const struct of_device_id adv7180_of_id[] = { 1403static const struct of_device_id adv7180_of_id[] = {
1330 { .compatible = "adi,adv7180", }, 1404 { .compatible = "adi,adv7180", },
1405 { .compatible = "adi,adv7182", },
1406 { .compatible = "adi,adv7280", },
1407 { .compatible = "adi,adv7280-m", },
1408 { .compatible = "adi,adv7281", },
1409 { .compatible = "adi,adv7281-m", },
1410 { .compatible = "adi,adv7281-ma", },
1411 { .compatible = "adi,adv7282", },
1412 { .compatible = "adi,adv7282-m", },
1331 { }, 1413 { },
1332}; 1414};
1333 1415
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index bd822f032b08..39271c35da48 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -1502,12 +1502,6 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
1502 err = hdl->error; 1502 err = hdl->error;
1503 goto err_hdl; 1503 goto err_hdl;
1504 } 1504 }
1505 state->hdmi_mode_ctrl->is_private = true;
1506 state->hotplug_ctrl->is_private = true;
1507 state->rx_sense_ctrl->is_private = true;
1508 state->have_edid0_ctrl->is_private = true;
1509 state->rgb_quantization_range_ctrl->is_private = true;
1510
1511 state->pad.flags = MEDIA_PAD_FL_SINK; 1505 state->pad.flags = MEDIA_PAD_FL_SINK;
1512 err = media_entity_pads_init(&sd->entity, 1, &state->pad); 1506 err = media_entity_pads_init(&sd->entity, 1, &state->pad);
1513 if (err) 1507 if (err)
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 41a1bfc5eaa7..beb2841ceae5 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -3141,7 +3141,6 @@ static int adv76xx_probe(struct i2c_client *client,
3141 if (ctrl) 3141 if (ctrl)
3142 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 3142 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
3143 3143
3144 /* private controls */
3145 state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, 3144 state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL,
3146 V4L2_CID_DV_RX_POWER_PRESENT, 0, 3145 V4L2_CID_DV_RX_POWER_PRESENT, 0,
3147 (1 << state->info->num_dv_ports) - 1, 0, 0); 3146 (1 << state->info->num_dv_ports) - 1, 0, 0);
@@ -3164,13 +3163,6 @@ static int adv76xx_probe(struct i2c_client *client,
3164 err = hdl->error; 3163 err = hdl->error;
3165 goto err_hdl; 3164 goto err_hdl;
3166 } 3165 }
3167 state->detect_tx_5v_ctrl->is_private = true;
3168 state->rgb_quantization_range_ctrl->is_private = true;
3169 if (adv76xx_has_afe(state))
3170 state->analog_sampling_phase_ctrl->is_private = true;
3171 state->free_run_color_manual_ctrl->is_private = true;
3172 state->free_run_color_ctrl->is_private = true;
3173
3174 if (adv76xx_s_detect_tx_5v_ctrl(sd)) { 3166 if (adv76xx_s_detect_tx_5v_ctrl(sd)) {
3175 err = -ENODEV; 3167 err = -ENODEV;
3176 goto err_hdl; 3168 goto err_hdl;
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 7ccb85d45224..ecaacb0a6fa1 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -3300,12 +3300,6 @@ static int adv7842_probe(struct i2c_client *client,
3300 err = hdl->error; 3300 err = hdl->error;
3301 goto err_hdl; 3301 goto err_hdl;
3302 } 3302 }
3303 state->detect_tx_5v_ctrl->is_private = true;
3304 state->rgb_quantization_range_ctrl->is_private = true;
3305 state->analog_sampling_phase_ctrl->is_private = true;
3306 state->free_run_color_ctrl_manual->is_private = true;
3307 state->free_run_color_ctrl->is_private = true;
3308
3309 if (adv7842_s_detect_tx_5v_ctrl(sd)) { 3303 if (adv7842_s_detect_tx_5v_ctrl(sd)) {
3310 err = -ENODEV; 3304 err = -ENODEV;
3311 goto err_hdl; 3305 goto err_hdl;
diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c
index a60931e66312..c2218c0a9e6f 100644
--- a/drivers/media/i2c/m5mols/m5mols_controls.c
+++ b/drivers/media/i2c/m5mols/m5mols_controls.c
@@ -405,7 +405,7 @@ static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
405 struct v4l2_subdev *sd = to_sd(ctrl); 405 struct v4l2_subdev *sd = to_sd(ctrl);
406 struct m5mols_info *info = to_m5mols(sd); 406 struct m5mols_info *info = to_m5mols(sd);
407 int ret = 0; 407 int ret = 0;
408 u8 status; 408 u8 status = REG_ISO_AUTO;
409 409
410 v4l2_dbg(1, m5mols_debug, sd, "%s: ctrl: %s (%d)\n", 410 v4l2_dbg(1, m5mols_debug, sd, "%s: ctrl: %s (%d)\n",
411 __func__, ctrl->name, info->isp_ready); 411 __func__, ctrl->name, info->isp_ready);
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
index d2a1ce2bc7f5..bd3526bdd539 100644
--- a/drivers/media/i2c/saa7115.c
+++ b/drivers/media/i2c/saa7115.c
@@ -1798,6 +1798,21 @@ static int saa711x_detect_chip(struct i2c_client *client,
1798 return GM7113C; 1798 return GM7113C;
1799 } 1799 }
1800 1800
1801 /* Check if it is a CJC7113 */
1802 if (!memcmp(name, "1111111111111111", CHIP_VER_SIZE)) {
1803 strlcpy(name, "cjc7113", CHIP_VER_SIZE);
1804
1805 if (!autodetect && strcmp(name, id->name))
1806 return -EINVAL;
1807
1808 v4l_dbg(1, debug, client,
1809 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1810 name, 16, chip_ver, client->addr << 1);
1811
1812 /* CJC7113 seems to be SAA7113-compatible */
1813 return SAA7113;
1814 }
1815
1801 /* Chip was not discovered. Return its ID and don't bind */ 1816 /* Chip was not discovered. Return its ID and don't bind */
1802 v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n", 1817 v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n",
1803 16, chip_ver, client->addr << 1); 1818 16, chip_ver, client->addr << 1);
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index a215efe7a8ba..3dfe387abf6e 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -188,6 +188,8 @@ static int smiapp_read_frame_fmt(struct smiapp_sensor *sensor)
188 embedded_end = 0; 188 embedded_end = 0;
189 } 189 }
190 190
191 sensor->image_start = image_start;
192
191 dev_dbg(&client->dev, "embedded data from lines %d to %d\n", 193 dev_dbg(&client->dev, "embedded data from lines %d to %d\n",
192 embedded_start, embedded_end); 194 embedded_start, embedded_end);
193 dev_dbg(&client->dev, "image data starts at line %d\n", image_start); 195 dev_dbg(&client->dev, "image data starts at line %d\n", image_start);
@@ -2280,6 +2282,15 @@ static int smiapp_get_skip_frames(struct v4l2_subdev *subdev, u32 *frames)
2280 return 0; 2282 return 0;
2281} 2283}
2282 2284
2285static int smiapp_get_skip_top_lines(struct v4l2_subdev *subdev, u32 *lines)
2286{
2287 struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
2288
2289 *lines = sensor->image_start;
2290
2291 return 0;
2292}
2293
2283/* ----------------------------------------------------------------------------- 2294/* -----------------------------------------------------------------------------
2284 * sysfs attributes 2295 * sysfs attributes
2285 */ 2296 */
@@ -2890,6 +2901,7 @@ static const struct v4l2_subdev_pad_ops smiapp_pad_ops = {
2890 2901
2891static const struct v4l2_subdev_sensor_ops smiapp_sensor_ops = { 2902static const struct v4l2_subdev_sensor_ops smiapp_sensor_ops = {
2892 .g_skip_frames = smiapp_get_skip_frames, 2903 .g_skip_frames = smiapp_get_skip_frames,
2904 .g_skip_top_lines = smiapp_get_skip_top_lines,
2893}; 2905};
2894 2906
2895static const struct v4l2_subdev_ops smiapp_ops = { 2907static const struct v4l2_subdev_ops smiapp_ops = {
diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h
index f6af0cc4a256..2174f89a00db 100644
--- a/drivers/media/i2c/smiapp/smiapp.h
+++ b/drivers/media/i2c/smiapp/smiapp.h
@@ -217,6 +217,7 @@ struct smiapp_sensor {
217 217
218 u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */ 218 u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
219 u8 frame_skip; 219 u8 frame_skip;
220 u16 image_start; /* Offset to first line after metadata lines */
220 221
221 int power_count; 222 int power_count;
222 223
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
index 972e0d47259d..6cf6d06737a5 100644
--- a/drivers/media/i2c/tc358743.c
+++ b/drivers/media/i2c/tc358743.c
@@ -1551,6 +1551,8 @@ static int tc358743_g_edid(struct v4l2_subdev *sd,
1551{ 1551{
1552 struct tc358743_state *state = to_state(sd); 1552 struct tc358743_state *state = to_state(sd);
1553 1553
1554 memset(edid->reserved, 0, sizeof(edid->reserved));
1555
1554 if (edid->pad != 0) 1556 if (edid->pad != 0)
1555 return -EINVAL; 1557 return -EINVAL;
1556 1558
@@ -1585,6 +1587,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd,
1585 v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n", 1587 v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n",
1586 __func__, edid->pad, edid->start_block, edid->blocks); 1588 __func__, edid->pad, edid->start_block, edid->blocks);
1587 1589
1590 memset(edid->reserved, 0, sizeof(edid->reserved));
1591
1588 if (edid->pad != 0) 1592 if (edid->pad != 0)
1589 return -EINVAL; 1593 return -EINVAL;
1590 1594
@@ -1859,7 +1863,6 @@ static int tc358743_probe(struct i2c_client *client,
1859 /* control handlers */ 1863 /* control handlers */
1860 v4l2_ctrl_handler_init(&state->hdl, 3); 1864 v4l2_ctrl_handler_init(&state->hdl, 3);
1861 1865
1862 /* private controls */
1863 state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&state->hdl, NULL, 1866 state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&state->hdl, NULL,
1864 V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0); 1867 V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0);
1865 1868
diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c
index 5bbfcab01c75..71a31352135c 100644
--- a/drivers/media/i2c/ths7303.c
+++ b/drivers/media/i2c/ths7303.c
@@ -285,7 +285,7 @@ static int ths7303_log_status(struct v4l2_subdev *sd)
285 v4l2_info(sd, "stream %s\n", state->stream_on ? "On" : "Off"); 285 v4l2_info(sd, "stream %s\n", state->stream_on ? "On" : "Off");
286 286
287 if (state->bt.pixelclock) { 287 if (state->bt.pixelclock) {
288 struct v4l2_bt_timings *bt = bt = &state->bt; 288 struct v4l2_bt_timings *bt = &state->bt;
289 u32 frame_width, frame_height; 289 u32 frame_width, frame_height;
290 290
291 frame_width = V4L2_DV_BT_FRAME_WIDTH(bt); 291 frame_width = V4L2_DV_BT_FRAME_WIDTH(bt);
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index ff18444e19e4..0b6d46c453bf 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -83,7 +83,7 @@ static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
83 return rc; 83 return rc;
84} 84}
85 85
86static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr, 86static int tvp5150_write(struct v4l2_subdev *sd, unsigned char addr,
87 unsigned char value) 87 unsigned char value)
88{ 88{
89 struct i2c_client *c = v4l2_get_subdevdata(sd); 89 struct i2c_client *c = v4l2_get_subdevdata(sd);
@@ -92,7 +92,9 @@ static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr,
92 v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", addr, value); 92 v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", addr, value);
93 rc = i2c_smbus_write_byte_data(c, addr, value); 93 rc = i2c_smbus_write_byte_data(c, addr, value);
94 if (rc < 0) 94 if (rc < 0)
95 v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d\n", rc); 95 v4l2_err(sd, "i2c i/o error: rc == %d\n", rc);
96
97 return rc;
96} 98}
97 99
98static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init, 100static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init,
@@ -1159,8 +1161,7 @@ static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
1159 1161
1160static int tvp5150_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) 1162static int tvp5150_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
1161{ 1163{
1162 tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff); 1164 return tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff);
1163 return 0;
1164} 1165}
1165#endif 1166#endif
1166 1167
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 3cfd7af8c5ca..a1cd50f331f1 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -90,18 +90,13 @@ static struct media_entity *find_entity(struct media_device *mdev, u32 id)
90 90
91 id &= ~MEDIA_ENT_ID_FLAG_NEXT; 91 id &= ~MEDIA_ENT_ID_FLAG_NEXT;
92 92
93 spin_lock(&mdev->lock);
94
95 media_device_for_each_entity(entity, mdev) { 93 media_device_for_each_entity(entity, mdev) {
96 if (((media_entity_id(entity) == id) && !next) || 94 if (((media_entity_id(entity) == id) && !next) ||
97 ((media_entity_id(entity) > id) && next)) { 95 ((media_entity_id(entity) > id) && next)) {
98 spin_unlock(&mdev->lock);
99 return entity; 96 return entity;
100 } 97 }
101 } 98 }
102 99
103 spin_unlock(&mdev->lock);
104
105 return NULL; 100 return NULL;
106} 101}
107 102
@@ -431,6 +426,7 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
431 struct media_device *dev = to_media_device(devnode); 426 struct media_device *dev = to_media_device(devnode);
432 long ret; 427 long ret;
433 428
429 mutex_lock(&dev->graph_mutex);
434 switch (cmd) { 430 switch (cmd) {
435 case MEDIA_IOC_DEVICE_INFO: 431 case MEDIA_IOC_DEVICE_INFO:
436 ret = media_device_get_info(dev, 432 ret = media_device_get_info(dev,
@@ -443,29 +439,24 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
443 break; 439 break;
444 440
445 case MEDIA_IOC_ENUM_LINKS: 441 case MEDIA_IOC_ENUM_LINKS:
446 mutex_lock(&dev->graph_mutex);
447 ret = media_device_enum_links(dev, 442 ret = media_device_enum_links(dev,
448 (struct media_links_enum __user *)arg); 443 (struct media_links_enum __user *)arg);
449 mutex_unlock(&dev->graph_mutex);
450 break; 444 break;
451 445
452 case MEDIA_IOC_SETUP_LINK: 446 case MEDIA_IOC_SETUP_LINK:
453 mutex_lock(&dev->graph_mutex);
454 ret = media_device_setup_link(dev, 447 ret = media_device_setup_link(dev,
455 (struct media_link_desc __user *)arg); 448 (struct media_link_desc __user *)arg);
456 mutex_unlock(&dev->graph_mutex);
457 break; 449 break;
458 450
459 case MEDIA_IOC_G_TOPOLOGY: 451 case MEDIA_IOC_G_TOPOLOGY:
460 mutex_lock(&dev->graph_mutex);
461 ret = media_device_get_topology(dev, 452 ret = media_device_get_topology(dev,
462 (struct media_v2_topology __user *)arg); 453 (struct media_v2_topology __user *)arg);
463 mutex_unlock(&dev->graph_mutex);
464 break; 454 break;
465 455
466 default: 456 default:
467 ret = -ENOIOCTLCMD; 457 ret = -ENOIOCTLCMD;
468 } 458 }
459 mutex_unlock(&dev->graph_mutex);
469 460
470 return ret; 461 return ret;
471} 462}
@@ -508,12 +499,6 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd,
508 long ret; 499 long ret;
509 500
510 switch (cmd) { 501 switch (cmd) {
511 case MEDIA_IOC_DEVICE_INFO:
512 case MEDIA_IOC_ENUM_ENTITIES:
513 case MEDIA_IOC_SETUP_LINK:
514 case MEDIA_IOC_G_TOPOLOGY:
515 return media_device_ioctl(filp, cmd, arg);
516
517 case MEDIA_IOC_ENUM_LINKS32: 502 case MEDIA_IOC_ENUM_LINKS32:
518 mutex_lock(&dev->graph_mutex); 503 mutex_lock(&dev->graph_mutex);
519 ret = media_device_enum_links32(dev, 504 ret = media_device_enum_links32(dev,
@@ -522,7 +507,7 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd,
522 break; 507 break;
523 508
524 default: 509 default:
525 ret = -ENOIOCTLCMD; 510 return media_device_ioctl(filp, cmd, arg);
526 } 511 }
527 512
528 return ret; 513 return ret;
@@ -590,12 +575,12 @@ int __must_check media_device_register_entity(struct media_device *mdev,
590 if (!ida_pre_get(&mdev->entity_internal_idx, GFP_KERNEL)) 575 if (!ida_pre_get(&mdev->entity_internal_idx, GFP_KERNEL))
591 return -ENOMEM; 576 return -ENOMEM;
592 577
593 spin_lock(&mdev->lock); 578 mutex_lock(&mdev->graph_mutex);
594 579
595 ret = ida_get_new_above(&mdev->entity_internal_idx, 1, 580 ret = ida_get_new_above(&mdev->entity_internal_idx, 1,
596 &entity->internal_idx); 581 &entity->internal_idx);
597 if (ret < 0) { 582 if (ret < 0) {
598 spin_unlock(&mdev->lock); 583 mutex_unlock(&mdev->graph_mutex);
599 return ret; 584 return ret;
600 } 585 }
601 586
@@ -615,9 +600,6 @@ int __must_check media_device_register_entity(struct media_device *mdev,
615 (notify)->notify(entity, notify->notify_data); 600 (notify)->notify(entity, notify->notify_data);
616 } 601 }
617 602
618 spin_unlock(&mdev->lock);
619
620 mutex_lock(&mdev->graph_mutex);
621 if (mdev->entity_internal_idx_max 603 if (mdev->entity_internal_idx_max
622 >= mdev->pm_count_walk.ent_enum.idx_max) { 604 >= mdev->pm_count_walk.ent_enum.idx_max) {
623 struct media_entity_graph new = { .top = 0 }; 605 struct media_entity_graph new = { .top = 0 };
@@ -680,9 +662,9 @@ void media_device_unregister_entity(struct media_entity *entity)
680 if (mdev == NULL) 662 if (mdev == NULL)
681 return; 663 return;
682 664
683 spin_lock(&mdev->lock); 665 mutex_lock(&mdev->graph_mutex);
684 __media_device_unregister_entity(entity); 666 __media_device_unregister_entity(entity);
685 spin_unlock(&mdev->lock); 667 mutex_unlock(&mdev->graph_mutex);
686} 668}
687EXPORT_SYMBOL_GPL(media_device_unregister_entity); 669EXPORT_SYMBOL_GPL(media_device_unregister_entity);
688 670
@@ -703,7 +685,6 @@ void media_device_init(struct media_device *mdev)
703 INIT_LIST_HEAD(&mdev->pads); 685 INIT_LIST_HEAD(&mdev->pads);
704 INIT_LIST_HEAD(&mdev->links); 686 INIT_LIST_HEAD(&mdev->links);
705 INIT_LIST_HEAD(&mdev->entity_notify); 687 INIT_LIST_HEAD(&mdev->entity_notify);
706 spin_lock_init(&mdev->lock);
707 mutex_init(&mdev->graph_mutex); 688 mutex_init(&mdev->graph_mutex);
708 ida_init(&mdev->entity_internal_idx); 689 ida_init(&mdev->entity_internal_idx);
709 690
@@ -752,9 +733,9 @@ EXPORT_SYMBOL_GPL(__media_device_register);
752int __must_check media_device_register_entity_notify(struct media_device *mdev, 733int __must_check media_device_register_entity_notify(struct media_device *mdev,
753 struct media_entity_notify *nptr) 734 struct media_entity_notify *nptr)
754{ 735{
755 spin_lock(&mdev->lock); 736 mutex_lock(&mdev->graph_mutex);
756 list_add_tail(&nptr->list, &mdev->entity_notify); 737 list_add_tail(&nptr->list, &mdev->entity_notify);
757 spin_unlock(&mdev->lock); 738 mutex_unlock(&mdev->graph_mutex);
758 return 0; 739 return 0;
759} 740}
760EXPORT_SYMBOL_GPL(media_device_register_entity_notify); 741EXPORT_SYMBOL_GPL(media_device_register_entity_notify);
@@ -771,9 +752,9 @@ static void __media_device_unregister_entity_notify(struct media_device *mdev,
771void media_device_unregister_entity_notify(struct media_device *mdev, 752void media_device_unregister_entity_notify(struct media_device *mdev,
772 struct media_entity_notify *nptr) 753 struct media_entity_notify *nptr)
773{ 754{
774 spin_lock(&mdev->lock); 755 mutex_lock(&mdev->graph_mutex);
775 __media_device_unregister_entity_notify(mdev, nptr); 756 __media_device_unregister_entity_notify(mdev, nptr);
776 spin_unlock(&mdev->lock); 757 mutex_unlock(&mdev->graph_mutex);
777} 758}
778EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify); 759EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify);
779 760
@@ -787,11 +768,11 @@ void media_device_unregister(struct media_device *mdev)
787 if (mdev == NULL) 768 if (mdev == NULL)
788 return; 769 return;
789 770
790 spin_lock(&mdev->lock); 771 mutex_lock(&mdev->graph_mutex);
791 772
792 /* Check if mdev was ever registered at all */ 773 /* Check if mdev was ever registered at all */
793 if (!media_devnode_is_registered(&mdev->devnode)) { 774 if (!media_devnode_is_registered(&mdev->devnode)) {
794 spin_unlock(&mdev->lock); 775 mutex_unlock(&mdev->graph_mutex);
795 return; 776 return;
796 } 777 }
797 778
@@ -811,12 +792,11 @@ void media_device_unregister(struct media_device *mdev)
811 kfree(intf); 792 kfree(intf);
812 } 793 }
813 794
814 spin_unlock(&mdev->lock); 795 mutex_unlock(&mdev->graph_mutex);
815 796
816 device_remove_file(&mdev->devnode.dev, &dev_attr_model); 797 device_remove_file(&mdev->devnode.dev, &dev_attr_model);
798 dev_dbg(mdev->dev, "Media device unregistering\n");
817 media_devnode_unregister(&mdev->devnode); 799 media_devnode_unregister(&mdev->devnode);
818
819 dev_dbg(mdev->dev, "Media device unregistered\n");
820} 800}
821EXPORT_SYMBOL_GPL(media_device_unregister); 801EXPORT_SYMBOL_GPL(media_device_unregister);
822 802
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 29409f440f1c..b66dc9d0766b 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -197,10 +197,11 @@ static int media_release(struct inode *inode, struct file *filp)
197 if (mdev->fops->release) 197 if (mdev->fops->release)
198 mdev->fops->release(filp); 198 mdev->fops->release(filp);
199 199
200 filp->private_data = NULL;
201
200 /* decrease the refcount unconditionally since the release() 202 /* decrease the refcount unconditionally since the release()
201 return value is ignored. */ 203 return value is ignored. */
202 put_device(&mdev->dev); 204 put_device(&mdev->dev);
203 filp->private_data = NULL;
204 return 0; 205 return 0;
205} 206}
206 207
@@ -267,8 +268,11 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
267 return 0; 268 return 0;
268 269
269error: 270error:
271 mutex_lock(&media_devnode_lock);
270 cdev_del(&mdev->cdev); 272 cdev_del(&mdev->cdev);
271 clear_bit(mdev->minor, media_devnode_nums); 273 clear_bit(mdev->minor, media_devnode_nums);
274 mutex_unlock(&media_devnode_lock);
275
272 return ret; 276 return ret;
273} 277}
274 278
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index e95070b3a3d4..d8a2299f0c2a 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -219,7 +219,7 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
219 entity->pads = pads; 219 entity->pads = pads;
220 220
221 if (mdev) 221 if (mdev)
222 spin_lock(&mdev->lock); 222 mutex_lock(&mdev->graph_mutex);
223 223
224 for (i = 0; i < num_pads; i++) { 224 for (i = 0; i < num_pads; i++) {
225 pads[i].entity = entity; 225 pads[i].entity = entity;
@@ -230,7 +230,7 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
230 } 230 }
231 231
232 if (mdev) 232 if (mdev)
233 spin_unlock(&mdev->lock); 233 mutex_unlock(&mdev->graph_mutex);
234 234
235 return 0; 235 return 0;
236} 236}
@@ -445,7 +445,7 @@ __must_check int __media_entity_pipeline_start(struct media_entity *entity,
445 bitmap_or(active, active, has_no_links, entity->num_pads); 445 bitmap_or(active, active, has_no_links, entity->num_pads);
446 446
447 if (!bitmap_full(active, entity->num_pads)) { 447 if (!bitmap_full(active, entity->num_pads)) {
448 ret = -EPIPE; 448 ret = -ENOLINK;
449 dev_dbg(entity->graph_obj.mdev->dev, 449 dev_dbg(entity->graph_obj.mdev->dev,
450 "\"%s\":%u must be connected by an enabled link\n", 450 "\"%s\":%u must be connected by an enabled link\n",
451 entity->name, 451 entity->name,
@@ -747,9 +747,9 @@ void media_entity_remove_links(struct media_entity *entity)
747 if (mdev == NULL) 747 if (mdev == NULL)
748 return; 748 return;
749 749
750 spin_lock(&mdev->lock); 750 mutex_lock(&mdev->graph_mutex);
751 __media_entity_remove_links(entity); 751 __media_entity_remove_links(entity);
752 spin_unlock(&mdev->lock); 752 mutex_unlock(&mdev->graph_mutex);
753} 753}
754EXPORT_SYMBOL_GPL(media_entity_remove_links); 754EXPORT_SYMBOL_GPL(media_entity_remove_links);
755 755
@@ -951,9 +951,9 @@ void media_remove_intf_link(struct media_link *link)
951 if (mdev == NULL) 951 if (mdev == NULL)
952 return; 952 return;
953 953
954 spin_lock(&mdev->lock); 954 mutex_lock(&mdev->graph_mutex);
955 __media_remove_intf_link(link); 955 __media_remove_intf_link(link);
956 spin_unlock(&mdev->lock); 956 mutex_unlock(&mdev->graph_mutex);
957} 957}
958EXPORT_SYMBOL_GPL(media_remove_intf_link); 958EXPORT_SYMBOL_GPL(media_remove_intf_link);
959 959
@@ -975,8 +975,8 @@ void media_remove_intf_links(struct media_interface *intf)
975 if (mdev == NULL) 975 if (mdev == NULL)
976 return; 976 return;
977 977
978 spin_lock(&mdev->lock); 978 mutex_lock(&mdev->graph_mutex);
979 __media_remove_intf_links(intf); 979 __media_remove_intf_links(intf);
980 spin_unlock(&mdev->lock); 980 mutex_unlock(&mdev->graph_mutex);
981} 981}
982EXPORT_SYMBOL_GPL(media_remove_intf_links); 982EXPORT_SYMBOL_GPL(media_remove_intf_links);
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
index 48a611bc3e18..4f6467fbaeb4 100644
--- a/drivers/media/pci/Kconfig
+++ b/drivers/media/pci/Kconfig
@@ -14,6 +14,7 @@ source "drivers/media/pci/meye/Kconfig"
14source "drivers/media/pci/solo6x10/Kconfig" 14source "drivers/media/pci/solo6x10/Kconfig"
15source "drivers/media/pci/sta2x11/Kconfig" 15source "drivers/media/pci/sta2x11/Kconfig"
16source "drivers/media/pci/tw68/Kconfig" 16source "drivers/media/pci/tw68/Kconfig"
17source "drivers/media/pci/tw686x/Kconfig"
17source "drivers/media/pci/zoran/Kconfig" 18source "drivers/media/pci/zoran/Kconfig"
18endif 19endif
19 20
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
index 5f8aacb8b9b8..2e54c36441f7 100644
--- a/drivers/media/pci/Makefile
+++ b/drivers/media/pci/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_VIDEO_BT848) += bt8xx/
25obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ 25obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
26obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ 26obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
27obj-$(CONFIG_VIDEO_TW68) += tw68/ 27obj-$(CONFIG_VIDEO_TW68) += tw68/
28obj-$(CONFIG_VIDEO_TW686X) += tw686x/
28obj-$(CONFIG_VIDEO_DT3155) += dt3155/ 29obj-$(CONFIG_VIDEO_DT3155) += dt3155/
29obj-$(CONFIG_VIDEO_MEYE) += meye/ 30obj-$(CONFIG_VIDEO_MEYE) += meye/
30obj-$(CONFIG_STA2X11_VIP) += sta2x11/ 31obj-$(CONFIG_STA2X11_VIP) += sta2x11/
diff --git a/drivers/media/pci/cobalt/Kconfig b/drivers/media/pci/cobalt/Kconfig
index a01f0cc745cc..70343829a125 100644
--- a/drivers/media/pci/cobalt/Kconfig
+++ b/drivers/media/pci/cobalt/Kconfig
@@ -4,6 +4,7 @@ config VIDEO_COBALT
4 depends on PCI_MSI && MTD_COMPLEX_MAPPINGS 4 depends on PCI_MSI && MTD_COMPLEX_MAPPINGS
5 depends on GPIOLIB || COMPILE_TEST 5 depends on GPIOLIB || COMPILE_TEST
6 depends on SND 6 depends on SND
7 depends on MTD
7 select I2C_ALGOBIT 8 select I2C_ALGOBIT
8 select VIDEO_ADV7604 9 select VIDEO_ADV7604
9 select VIDEO_ADV7511 10 select VIDEO_ADV7511
diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h
index 7e31f2a2e085..47ce80fa73b9 100644
--- a/drivers/media/pci/cx18/cx18-driver.h
+++ b/drivers/media/pci/cx18/cx18-driver.h
@@ -707,11 +707,7 @@ static inline int cx18_raw_vbi(const struct cx18 *cx)
707/* Call the specified callback for all subdevs with a grp_id bit matching the 707/* Call the specified callback for all subdevs with a grp_id bit matching the
708 * mask in hw (if 0, then match them all). Ignore any errors. */ 708 * mask in hw (if 0, then match them all). Ignore any errors. */
709#define cx18_call_hw(cx, hw, o, f, args...) \ 709#define cx18_call_hw(cx, hw, o, f, args...) \
710 do { \ 710 v4l2_device_mask_call_all(&(cx)->v4l2_dev, hw, o, f, ##args)
711 struct v4l2_subdev *__sd; \
712 __v4l2_device_call_subdevs_p(&(cx)->v4l2_dev, __sd, \
713 !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \
714 } while (0)
715 711
716#define cx18_call_all(cx, o, f, args...) cx18_call_hw(cx, 0, o, f , ##args) 712#define cx18_call_all(cx, o, f, args...) cx18_call_hw(cx, 0, o, f , ##args)
717 713
@@ -719,12 +715,7 @@ static inline int cx18_raw_vbi(const struct cx18 *cx)
719 * mask in hw (if 0, then match them all). If the callback returns an error 715 * mask in hw (if 0, then match them all). If the callback returns an error
720 * other than 0 or -ENOIOCTLCMD, then return with that error code. */ 716 * other than 0 or -ENOIOCTLCMD, then return with that error code. */
721#define cx18_call_hw_err(cx, hw, o, f, args...) \ 717#define cx18_call_hw_err(cx, hw, o, f, args...) \
722({ \ 718 v4l2_device_mask_call_until_err(&(cx)->v4l2_dev, hw, o, f, ##args)
723 struct v4l2_subdev *__sd; \
724 __v4l2_device_call_subdevs_until_err_p(&(cx)->v4l2_dev, \
725 __sd, !(hw) || (__sd->grp_id & (hw)), o, f, \
726 ##args); \
727})
728 719
729#define cx18_call_all_err(cx, o, f, args...) \ 720#define cx18_call_all_err(cx, o, f, args...) \
730 cx18_call_hw_err(cx, 0, o, f , ##args) 721 cx18_call_hw_err(cx, 0, o, f , ##args)
diff --git a/drivers/media/pci/cx23885/cx23885-av.c b/drivers/media/pci/cx23885/cx23885-av.c
index 877dad89107e..e7d4406f9abd 100644
--- a/drivers/media/pci/cx23885/cx23885-av.c
+++ b/drivers/media/pci/cx23885/cx23885-av.c
@@ -24,7 +24,7 @@ void cx23885_av_work_handler(struct work_struct *work)
24{ 24{
25 struct cx23885_dev *dev = 25 struct cx23885_dev *dev =
26 container_of(work, struct cx23885_dev, cx25840_work); 26 container_of(work, struct cx23885_dev, cx25840_work);
27 bool handled; 27 bool handled = false;
28 28
29 v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine, 29 v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine,
30 PCI_MSK_AV_CORE, &handled); 30 PCI_MSK_AV_CORE, &handled);
diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h
index 6c08dae67a73..10cba305dbd2 100644
--- a/drivers/media/pci/ivtv/ivtv-driver.h
+++ b/drivers/media/pci/ivtv/ivtv-driver.h
@@ -827,12 +827,7 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv)
827/* Call the specified callback for all subdevs matching hw (if 0, then 827/* Call the specified callback for all subdevs matching hw (if 0, then
828 match them all). Ignore any errors. */ 828 match them all). Ignore any errors. */
829#define ivtv_call_hw(itv, hw, o, f, args...) \ 829#define ivtv_call_hw(itv, hw, o, f, args...) \
830 do { \ 830 v4l2_device_mask_call_all(&(itv)->v4l2_dev, hw, o, f, ##args)
831 struct v4l2_subdev *__sd; \
832 __v4l2_device_call_subdevs_p(&(itv)->v4l2_dev, __sd, \
833 !(hw) ? true : (__sd->grp_id & (hw)), \
834 o, f, ##args); \
835 } while (0)
836 831
837#define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args) 832#define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args)
838 833
@@ -840,11 +835,7 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv)
840 match them all). If the callback returns an error other than 0 or 835 match them all). If the callback returns an error other than 0 or
841 -ENOIOCTLCMD, then return with that error code. */ 836 -ENOIOCTLCMD, then return with that error code. */
842#define ivtv_call_hw_err(itv, hw, o, f, args...) \ 837#define ivtv_call_hw_err(itv, hw, o, f, args...) \
843({ \ 838 v4l2_device_mask_call_until_err(&(itv)->v4l2_dev, hw, o, f, ##args)
844 struct v4l2_subdev *__sd; \
845 __v4l2_device_call_subdevs_until_err_p(&(itv)->v4l2_dev, __sd, \
846 !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \
847})
848 839
849#define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args) 840#define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args)
850 841
diff --git a/drivers/media/pci/smipcie/smipcie-ir.c b/drivers/media/pci/smipcie/smipcie-ir.c
index d018673c71f6..826c7c75e64d 100644
--- a/drivers/media/pci/smipcie/smipcie-ir.c
+++ b/drivers/media/pci/smipcie/smipcie-ir.c
@@ -203,7 +203,7 @@ int smi_ir_init(struct smi_dev *dev)
203 rc_dev->dev.parent = &dev->pci_dev->dev; 203 rc_dev->dev.parent = &dev->pci_dev->dev;
204 204
205 rc_dev->driver_type = RC_DRIVER_SCANCODE; 205 rc_dev->driver_type = RC_DRIVER_SCANCODE;
206 rc_dev->map_name = RC_MAP_DVBSKY; 206 rc_dev->map_name = dev->info->rc_map;
207 207
208 ir->rc_dev = rc_dev; 208 ir->rc_dev = rc_dev;
209 ir->dev = dev; 209 ir->dev = dev;
diff --git a/drivers/media/pci/smipcie/smipcie-main.c b/drivers/media/pci/smipcie/smipcie-main.c
index b039a229b7d2..83981d611a79 100644
--- a/drivers/media/pci/smipcie/smipcie-main.c
+++ b/drivers/media/pci/smipcie/smipcie-main.c
@@ -716,7 +716,8 @@ static int smi_fe_init(struct smi_port *port)
716 /* init MAC.*/ 716 /* init MAC.*/
717 ret = smi_read_eeprom(&dev->i2c_bus[0], 0xc0, mac_ee, 16); 717 ret = smi_read_eeprom(&dev->i2c_bus[0], 0xc0, mac_ee, 16);
718 dev_info(&port->dev->pci_dev->dev, 718 dev_info(&port->dev->pci_dev->dev,
719 "DVBSky SMI PCIe MAC= %pM\n", mac_ee + (port->idx)*8); 719 "%s port %d MAC: %pM\n", dev->info->name,
720 port->idx, mac_ee + (port->idx)*8);
720 memcpy(adap->proposed_mac, mac_ee + (port->idx)*8, 6); 721 memcpy(adap->proposed_mac, mac_ee + (port->idx)*8, 6);
721 return ret; 722 return ret;
722} 723}
@@ -1066,6 +1067,7 @@ static struct smi_cfg_info dvbsky_s950_cfg = {
1066 .ts_1 = SMI_TS_DMA_BOTH, 1067 .ts_1 = SMI_TS_DMA_BOTH,
1067 .fe_0 = DVBSKY_FE_NULL, 1068 .fe_0 = DVBSKY_FE_NULL,
1068 .fe_1 = DVBSKY_FE_M88DS3103, 1069 .fe_1 = DVBSKY_FE_M88DS3103,
1070 .rc_map = RC_MAP_DVBSKY,
1069}; 1071};
1070 1072
1071static struct smi_cfg_info dvbsky_s952_cfg = { 1073static struct smi_cfg_info dvbsky_s952_cfg = {
@@ -1075,6 +1077,7 @@ static struct smi_cfg_info dvbsky_s952_cfg = {
1075 .ts_1 = SMI_TS_DMA_BOTH, 1077 .ts_1 = SMI_TS_DMA_BOTH,
1076 .fe_0 = DVBSKY_FE_M88RS6000, 1078 .fe_0 = DVBSKY_FE_M88RS6000,
1077 .fe_1 = DVBSKY_FE_M88RS6000, 1079 .fe_1 = DVBSKY_FE_M88RS6000,
1080 .rc_map = RC_MAP_DVBSKY,
1078}; 1081};
1079 1082
1080static struct smi_cfg_info dvbsky_t9580_cfg = { 1083static struct smi_cfg_info dvbsky_t9580_cfg = {
@@ -1084,6 +1087,17 @@ static struct smi_cfg_info dvbsky_t9580_cfg = {
1084 .ts_1 = SMI_TS_DMA_BOTH, 1087 .ts_1 = SMI_TS_DMA_BOTH,
1085 .fe_0 = DVBSKY_FE_SIT2, 1088 .fe_0 = DVBSKY_FE_SIT2,
1086 .fe_1 = DVBSKY_FE_M88DS3103, 1089 .fe_1 = DVBSKY_FE_M88DS3103,
1090 .rc_map = RC_MAP_DVBSKY,
1091};
1092
1093static struct smi_cfg_info technotrend_s2_4200_cfg = {
1094 .type = SMI_TECHNOTREND_S2_4200,
1095 .name = "TechnoTrend TT-budget S2-4200 Twin",
1096 .ts_0 = SMI_TS_DMA_BOTH,
1097 .ts_1 = SMI_TS_DMA_BOTH,
1098 .fe_0 = DVBSKY_FE_M88RS6000,
1099 .fe_1 = DVBSKY_FE_M88RS6000,
1100 .rc_map = RC_MAP_TT_1500,
1087}; 1101};
1088 1102
1089/* PCI IDs */ 1103/* PCI IDs */
@@ -1096,6 +1110,7 @@ static const struct pci_device_id smi_id_table[] = {
1096 SMI_ID(0x4254, 0x0550, dvbsky_s950_cfg), 1110 SMI_ID(0x4254, 0x0550, dvbsky_s950_cfg),
1097 SMI_ID(0x4254, 0x0552, dvbsky_s952_cfg), 1111 SMI_ID(0x4254, 0x0552, dvbsky_s952_cfg),
1098 SMI_ID(0x4254, 0x5580, dvbsky_t9580_cfg), 1112 SMI_ID(0x4254, 0x5580, dvbsky_t9580_cfg),
1113 SMI_ID(0x13c2, 0x3016, technotrend_s2_4200_cfg),
1099 {0} 1114 {0}
1100}; 1115};
1101MODULE_DEVICE_TABLE(pci, smi_id_table); 1116MODULE_DEVICE_TABLE(pci, smi_id_table);
diff --git a/drivers/media/pci/smipcie/smipcie.h b/drivers/media/pci/smipcie/smipcie.h
index 68cdda28fd98..611e4f02cadd 100644
--- a/drivers/media/pci/smipcie/smipcie.h
+++ b/drivers/media/pci/smipcie/smipcie.h
@@ -216,6 +216,7 @@ struct smi_cfg_info {
216#define SMI_DVBSKY_S950 1 216#define SMI_DVBSKY_S950 1
217#define SMI_DVBSKY_T9580 2 217#define SMI_DVBSKY_T9580 2
218#define SMI_DVBSKY_T982 3 218#define SMI_DVBSKY_T982 3
219#define SMI_TECHNOTREND_S2_4200 4
219 int type; 220 int type;
220 char *name; 221 char *name;
221#define SMI_TS_NULL 0 222#define SMI_TS_NULL 0
@@ -232,6 +233,7 @@ struct smi_cfg_info {
232#define DVBSKY_FE_SIT2 3 233#define DVBSKY_FE_SIT2 3
233 int fe_0; 234 int fe_0;
234 int fe_1; 235 int fe_1;
236 char *rc_map;
235}; 237};
236 238
237struct smi_rc { 239struct smi_rc {
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 753411cbbc9a..1fc195f89686 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -444,27 +444,19 @@ static int vidioc_querycap(struct file *file, void *priv,
444static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) 444static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std)
445{ 445{
446 struct sta2x11_vip *vip = video_drvdata(file); 446 struct sta2x11_vip *vip = video_drvdata(file);
447 v4l2_std_id oldstd = vip->std, newstd; 447
448 int status; 448 /*
449 449 * This is here for backwards compatibility only.
450 if (V4L2_STD_ALL == std) { 450 * The use of V4L2_STD_ALL to trigger a querystd is non-standard.
451 v4l2_subdev_call(vip->decoder, video, s_std, std); 451 */
452 ssleep(2); 452 if (std == V4L2_STD_ALL) {
453 v4l2_subdev_call(vip->decoder, video, querystd, &newstd); 453 v4l2_subdev_call(vip->decoder, video, querystd, &std);
454 v4l2_subdev_call(vip->decoder, video, g_input_status, &status); 454 if (std == V4L2_STD_UNKNOWN)
455 if (status & V4L2_IN_ST_NO_SIGNAL)
456 return -EIO; 455 return -EIO;
457 std = vip->std = newstd;
458 if (oldstd != std) {
459 if (V4L2_STD_525_60 & std)
460 vip->format = formats_60[0];
461 else
462 vip->format = formats_50[0];
463 }
464 return 0;
465 } 456 }
466 457
467 if (oldstd != std) { 458 if (vip->std != std) {
459 vip->std = std;
468 if (V4L2_STD_525_60 & std) 460 if (V4L2_STD_525_60 & std)
469 vip->format = formats_60[0]; 461 vip->format = formats_60[0];
470 else 462 else
diff --git a/drivers/media/pci/tw686x/Kconfig b/drivers/media/pci/tw686x/Kconfig
new file mode 100644
index 000000000000..fb8536974052
--- /dev/null
+++ b/drivers/media/pci/tw686x/Kconfig
@@ -0,0 +1,18 @@
1config VIDEO_TW686X
2 tristate "Intersil/Techwell TW686x video capture cards"
3 depends on PCI && VIDEO_DEV && VIDEO_V4L2 && SND
4 depends on HAS_DMA
5 select VIDEOBUF2_VMALLOC
6 select SND_PCM
7 help
8 Support for Intersil/Techwell TW686x-based frame grabber cards.
9
10 Currently supported chips:
11 - TW6864 (4 video channels),
12 - TW6865 (4 video channels, not tested, second generation chip),
13 - TW6868 (8 video channels but only 4 first channels using
14 built-in video decoder are supported, not tested),
15 - TW6869 (8 video channels, second generation chip).
16
17 To compile this driver as a module, choose M here: the module
18 will be named tw686x.
diff --git a/drivers/media/pci/tw686x/Makefile b/drivers/media/pci/tw686x/Makefile
new file mode 100644
index 000000000000..99819542b733
--- /dev/null
+++ b/drivers/media/pci/tw686x/Makefile
@@ -0,0 +1,3 @@
1tw686x-objs := tw686x-core.o tw686x-video.o tw686x-audio.o
2
3obj-$(CONFIG_VIDEO_TW686X) += tw686x.o
diff --git a/drivers/media/pci/tw686x/tw686x-audio.c b/drivers/media/pci/tw686x/tw686x-audio.c
new file mode 100644
index 000000000000..91459ab715b2
--- /dev/null
+++ b/drivers/media/pci/tw686x/tw686x-audio.c
@@ -0,0 +1,386 @@
1/*
2 * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar
3 *
4 * Based on the audio support from the tw6869 driver:
5 * Copyright 2015 www.starterkit.ru <info@starterkit.ru>
6 *
7 * Based on:
8 * Driver for Intersil|Techwell TW6869 based DVR cards
9 * (c) 2011-12 liran <jli11@intersil.com> [Intersil|Techwell China]
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of version 2 of the GNU General Public License
13 * as published by the Free Software Foundation.
14 */
15
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/kmod.h>
21#include <linux/mutex.h>
22#include <linux/pci.h>
23#include <linux/delay.h>
24
25#include <sound/core.h>
26#include <sound/initval.h>
27#include <sound/pcm.h>
28#include <sound/control.h>
29#include "tw686x.h"
30#include "tw686x-regs.h"
31
32#define AUDIO_CHANNEL_OFFSET 8
33
34void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests,
35 unsigned int pb_status)
36{
37 unsigned long flags;
38 unsigned int ch, pb;
39
40 for_each_set_bit(ch, &requests, max_channels(dev)) {
41 struct tw686x_audio_channel *ac = &dev->audio_channels[ch];
42 struct tw686x_audio_buf *done = NULL;
43 struct tw686x_audio_buf *next = NULL;
44 struct tw686x_dma_desc *desc;
45
46 pb = !!(pb_status & BIT(AUDIO_CHANNEL_OFFSET + ch));
47
48 spin_lock_irqsave(&ac->lock, flags);
49
50 /* Sanity check */
51 if (!ac->ss || !ac->curr_bufs[0] || !ac->curr_bufs[1]) {
52 spin_unlock_irqrestore(&ac->lock, flags);
53 continue;
54 }
55
56 if (!list_empty(&ac->buf_list)) {
57 next = list_first_entry(&ac->buf_list,
58 struct tw686x_audio_buf, list);
59 list_move_tail(&next->list, &ac->buf_list);
60 done = ac->curr_bufs[!pb];
61 ac->curr_bufs[pb] = next;
62 }
63 spin_unlock_irqrestore(&ac->lock, flags);
64
65 desc = &ac->dma_descs[pb];
66 if (done && next && desc->virt) {
67 memcpy(done->virt, desc->virt, desc->size);
68 ac->ptr = done->dma - ac->buf[0].dma;
69 snd_pcm_period_elapsed(ac->ss);
70 }
71 }
72}
73
74static int tw686x_pcm_hw_params(struct snd_pcm_substream *ss,
75 struct snd_pcm_hw_params *hw_params)
76{
77 return snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params));
78}
79
80static int tw686x_pcm_hw_free(struct snd_pcm_substream *ss)
81{
82 return snd_pcm_lib_free_pages(ss);
83}
84
85/*
86 * The audio device rate is global and shared among all
87 * capture channels. The driver makes no effort to prevent
88 * rate modifications. User is free change the rate, but it
89 * means changing the rate for all capture sub-devices.
90 */
91static const struct snd_pcm_hardware tw686x_capture_hw = {
92 .info = (SNDRV_PCM_INFO_MMAP |
93 SNDRV_PCM_INFO_INTERLEAVED |
94 SNDRV_PCM_INFO_BLOCK_TRANSFER |
95 SNDRV_PCM_INFO_MMAP_VALID),
96 .formats = SNDRV_PCM_FMTBIT_S16_LE,
97 .rates = SNDRV_PCM_RATE_8000_48000,
98 .rate_min = 8000,
99 .rate_max = 48000,
100 .channels_min = 1,
101 .channels_max = 1,
102 .buffer_bytes_max = TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ,
103 .period_bytes_min = TW686X_AUDIO_PAGE_SZ,
104 .period_bytes_max = TW686X_AUDIO_PAGE_SZ,
105 .periods_min = TW686X_AUDIO_PERIODS_MIN,
106 .periods_max = TW686X_AUDIO_PERIODS_MAX,
107};
108
109static int tw686x_pcm_open(struct snd_pcm_substream *ss)
110{
111 struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
112 struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
113 struct snd_pcm_runtime *rt = ss->runtime;
114 int err;
115
116 ac->ss = ss;
117 rt->hw = tw686x_capture_hw;
118
119 err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
120 if (err < 0)
121 return err;
122
123 return 0;
124}
125
126static int tw686x_pcm_close(struct snd_pcm_substream *ss)
127{
128 struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
129 struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
130
131 ac->ss = NULL;
132 return 0;
133}
134
135static int tw686x_pcm_prepare(struct snd_pcm_substream *ss)
136{
137 struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
138 struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
139 struct snd_pcm_runtime *rt = ss->runtime;
140 unsigned int period_size = snd_pcm_lib_period_bytes(ss);
141 struct tw686x_audio_buf *p_buf, *b_buf;
142 unsigned long flags;
143 int i;
144
145 spin_lock_irqsave(&dev->lock, flags);
146 tw686x_disable_channel(dev, AUDIO_CHANNEL_OFFSET + ac->ch);
147 spin_unlock_irqrestore(&dev->lock, flags);
148
149 if (dev->audio_rate != rt->rate) {
150 u32 reg;
151
152 dev->audio_rate = rt->rate;
153 reg = ((125000000 / rt->rate) << 16) +
154 ((125000000 % rt->rate) << 16) / rt->rate;
155
156 reg_write(dev, AUDIO_CONTROL2, reg);
157 }
158
159 if (period_size != TW686X_AUDIO_PAGE_SZ ||
160 rt->periods < TW686X_AUDIO_PERIODS_MIN ||
161 rt->periods > TW686X_AUDIO_PERIODS_MAX) {
162 return -EINVAL;
163 }
164
165 spin_lock_irqsave(&ac->lock, flags);
166 INIT_LIST_HEAD(&ac->buf_list);
167
168 for (i = 0; i < rt->periods; i++) {
169 ac->buf[i].dma = rt->dma_addr + period_size * i;
170 ac->buf[i].virt = rt->dma_area + period_size * i;
171 INIT_LIST_HEAD(&ac->buf[i].list);
172 list_add_tail(&ac->buf[i].list, &ac->buf_list);
173 }
174
175 p_buf = list_first_entry(&ac->buf_list, struct tw686x_audio_buf, list);
176 list_move_tail(&p_buf->list, &ac->buf_list);
177
178 b_buf = list_first_entry(&ac->buf_list, struct tw686x_audio_buf, list);
179 list_move_tail(&b_buf->list, &ac->buf_list);
180
181 ac->curr_bufs[0] = p_buf;
182 ac->curr_bufs[1] = b_buf;
183 ac->ptr = 0;
184 spin_unlock_irqrestore(&ac->lock, flags);
185
186 return 0;
187}
188
189static int tw686x_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
190{
191 struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
192 struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
193 unsigned long flags;
194 int err = 0;
195
196 switch (cmd) {
197 case SNDRV_PCM_TRIGGER_START:
198 if (ac->curr_bufs[0] && ac->curr_bufs[1]) {
199 spin_lock_irqsave(&dev->lock, flags);
200 tw686x_enable_channel(dev,
201 AUDIO_CHANNEL_OFFSET + ac->ch);
202 spin_unlock_irqrestore(&dev->lock, flags);
203
204 mod_timer(&dev->dma_delay_timer,
205 jiffies + msecs_to_jiffies(100));
206 } else {
207 err = -EIO;
208 }
209 break;
210 case SNDRV_PCM_TRIGGER_STOP:
211 spin_lock_irqsave(&dev->lock, flags);
212 tw686x_disable_channel(dev, AUDIO_CHANNEL_OFFSET + ac->ch);
213 spin_unlock_irqrestore(&dev->lock, flags);
214
215 spin_lock_irqsave(&ac->lock, flags);
216 ac->curr_bufs[0] = NULL;
217 ac->curr_bufs[1] = NULL;
218 spin_unlock_irqrestore(&ac->lock, flags);
219 break;
220 default:
221 err = -EINVAL;
222 }
223 return err;
224}
225
226static snd_pcm_uframes_t tw686x_pcm_pointer(struct snd_pcm_substream *ss)
227{
228 struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
229 struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
230
231 return bytes_to_frames(ss->runtime, ac->ptr);
232}
233
234static struct snd_pcm_ops tw686x_pcm_ops = {
235 .open = tw686x_pcm_open,
236 .close = tw686x_pcm_close,
237 .ioctl = snd_pcm_lib_ioctl,
238 .hw_params = tw686x_pcm_hw_params,
239 .hw_free = tw686x_pcm_hw_free,
240 .prepare = tw686x_pcm_prepare,
241 .trigger = tw686x_pcm_trigger,
242 .pointer = tw686x_pcm_pointer,
243};
244
245static int tw686x_snd_pcm_init(struct tw686x_dev *dev)
246{
247 struct snd_card *card = dev->snd_card;
248 struct snd_pcm *pcm;
249 struct snd_pcm_substream *ss;
250 unsigned int i;
251 int err;
252
253 err = snd_pcm_new(card, card->driver, 0, 0, max_channels(dev), &pcm);
254 if (err < 0)
255 return err;
256
257 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &tw686x_pcm_ops);
258 snd_pcm_chip(pcm) = dev;
259 pcm->info_flags = 0;
260 strlcpy(pcm->name, "tw686x PCM", sizeof(pcm->name));
261
262 for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
263 ss; ss = ss->next, i++)
264 snprintf(ss->name, sizeof(ss->name), "vch%u audio", i);
265
266 return snd_pcm_lib_preallocate_pages_for_all(pcm,
267 SNDRV_DMA_TYPE_DEV,
268 snd_dma_pci_data(dev->pci_dev),
269 TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ,
270 TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ);
271}
272
273static void tw686x_audio_dma_free(struct tw686x_dev *dev,
274 struct tw686x_audio_channel *ac)
275{
276 int pb;
277
278 for (pb = 0; pb < 2; pb++) {
279 if (!ac->dma_descs[pb].virt)
280 continue;
281 pci_free_consistent(dev->pci_dev, ac->dma_descs[pb].size,
282 ac->dma_descs[pb].virt,
283 ac->dma_descs[pb].phys);
284 ac->dma_descs[pb].virt = NULL;
285 }
286}
287
288static int tw686x_audio_dma_alloc(struct tw686x_dev *dev,
289 struct tw686x_audio_channel *ac)
290{
291 int pb;
292
293 for (pb = 0; pb < 2; pb++) {
294 u32 reg = pb ? ADMA_B_ADDR[ac->ch] : ADMA_P_ADDR[ac->ch];
295 void *virt;
296
297 virt = pci_alloc_consistent(dev->pci_dev, TW686X_AUDIO_PAGE_SZ,
298 &ac->dma_descs[pb].phys);
299 if (!virt) {
300 dev_err(&dev->pci_dev->dev,
301 "dma%d: unable to allocate audio DMA %s-buffer\n",
302 ac->ch, pb ? "B" : "P");
303 return -ENOMEM;
304 }
305 ac->dma_descs[pb].virt = virt;
306 ac->dma_descs[pb].size = TW686X_AUDIO_PAGE_SZ;
307 reg_write(dev, reg, ac->dma_descs[pb].phys);
308 }
309 return 0;
310}
311
312void tw686x_audio_free(struct tw686x_dev *dev)
313{
314 unsigned long flags;
315 u32 dma_ch_mask;
316 u32 dma_cmd;
317
318 spin_lock_irqsave(&dev->lock, flags);
319 dma_cmd = reg_read(dev, DMA_CMD);
320 dma_ch_mask = reg_read(dev, DMA_CHANNEL_ENABLE);
321 reg_write(dev, DMA_CMD, dma_cmd & ~0xff00);
322 reg_write(dev, DMA_CHANNEL_ENABLE, dma_ch_mask & ~0xff00);
323 spin_unlock_irqrestore(&dev->lock, flags);
324
325 if (!dev->snd_card)
326 return;
327 snd_card_free(dev->snd_card);
328 dev->snd_card = NULL;
329}
330
331int tw686x_audio_init(struct tw686x_dev *dev)
332{
333 struct pci_dev *pci_dev = dev->pci_dev;
334 struct snd_card *card;
335 int err, ch;
336
337 /*
338 * AUDIO_CONTROL1
339 * DMA byte length [31:19] = 4096 (i.e. ALSA period)
340 * External audio enable [0] = enabled
341 */
342 reg_write(dev, AUDIO_CONTROL1, 0x80000001);
343
344 err = snd_card_new(&pci_dev->dev, SNDRV_DEFAULT_IDX1,
345 SNDRV_DEFAULT_STR1,
346 THIS_MODULE, 0, &card);
347 if (err < 0)
348 return err;
349
350 dev->snd_card = card;
351 strlcpy(card->driver, "tw686x", sizeof(card->driver));
352 strlcpy(card->shortname, "tw686x", sizeof(card->shortname));
353 strlcpy(card->longname, pci_name(pci_dev), sizeof(card->longname));
354 snd_card_set_dev(card, &pci_dev->dev);
355
356 for (ch = 0; ch < max_channels(dev); ch++) {
357 struct tw686x_audio_channel *ac;
358
359 ac = &dev->audio_channels[ch];
360 spin_lock_init(&ac->lock);
361 ac->dev = dev;
362 ac->ch = ch;
363
364 err = tw686x_audio_dma_alloc(dev, ac);
365 if (err < 0)
366 goto err_cleanup;
367 }
368
369 err = tw686x_snd_pcm_init(dev);
370 if (err < 0)
371 goto err_cleanup;
372
373 err = snd_card_register(card);
374 if (!err)
375 return 0;
376
377err_cleanup:
378 for (ch = 0; ch < max_channels(dev); ch++) {
379 if (!dev->audio_channels[ch].dev)
380 continue;
381 tw686x_audio_dma_free(dev, &dev->audio_channels[ch]);
382 }
383 snd_card_free(card);
384 dev->snd_card = NULL;
385 return err;
386}
diff --git a/drivers/media/pci/tw686x/tw686x-core.c b/drivers/media/pci/tw686x/tw686x-core.c
new file mode 100644
index 000000000000..cf53b0e97be2
--- /dev/null
+++ b/drivers/media/pci/tw686x/tw686x-core.c
@@ -0,0 +1,415 @@
1/*
2 * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar
3 *
4 * Based on original driver by Krzysztof Ha?asa:
5 * Copyright (C) 2015 Industrial Research Institute for Automation
6 * and Measurements PIAP
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of version 2 of the GNU General Public License
10 * as published by the Free Software Foundation.
11 *
12 * Notes
13 * -----
14 *
15 * 1. Under stress-testing, it has been observed that the PCIe link
16 * goes down, without reason. Therefore, the driver takes special care
17 * to allow device hot-unplugging.
18 *
19 * 2. TW686X devices are capable of setting a few different DMA modes,
20 * including: scatter-gather, field and frame modes. However,
21 * under stress testings it has been found that the machine can
22 * freeze completely if DMA registers are programmed while streaming
23 * is active.
24 * This driver tries to access hardware registers as infrequently
25 * as possible by:
26 * i. allocating fixed DMA buffers and memcpy'ing into
27 * vmalloc'ed buffers
28 * ii. using a timer to mitigate the rate of DMA reset operations,
29 * on DMA channels error.
30 */
31
32#include <linux/init.h>
33#include <linux/interrupt.h>
34#include <linux/delay.h>
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/pci_ids.h>
38#include <linux/slab.h>
39#include <linux/timer.h>
40
41#include "tw686x.h"
42#include "tw686x-regs.h"
43
44/*
45 * This module parameter allows to control the DMA_TIMER_INTERVAL value.
46 * The DMA_TIMER_INTERVAL register controls the minimum DMA interrupt
47 * time span (iow, the maximum DMA interrupt rate) thus allowing for
48 * IRQ coalescing.
49 *
50 * The chip datasheet does not mention a time unit for this value, so
51 * users wanting fine-grain control over the interrupt rate should
52 * determine the desired value through testing.
53 */
54static u32 dma_interval = 0x00098968;
55module_param(dma_interval, int, 0444);
56MODULE_PARM_DESC(dma_interval, "Minimum time span for DMA interrupting host");
57
58void tw686x_disable_channel(struct tw686x_dev *dev, unsigned int channel)
59{
60 u32 dma_en = reg_read(dev, DMA_CHANNEL_ENABLE);
61 u32 dma_cmd = reg_read(dev, DMA_CMD);
62
63 dma_en &= ~BIT(channel);
64 dma_cmd &= ~BIT(channel);
65
66 /* Must remove it from pending too */
67 dev->pending_dma_en &= ~BIT(channel);
68 dev->pending_dma_cmd &= ~BIT(channel);
69
70 /* Stop DMA if no channels are enabled */
71 if (!dma_en)
72 dma_cmd = 0;
73 reg_write(dev, DMA_CHANNEL_ENABLE, dma_en);
74 reg_write(dev, DMA_CMD, dma_cmd);
75}
76
77void tw686x_enable_channel(struct tw686x_dev *dev, unsigned int channel)
78{
79 u32 dma_en = reg_read(dev, DMA_CHANNEL_ENABLE);
80 u32 dma_cmd = reg_read(dev, DMA_CMD);
81
82 dev->pending_dma_en |= dma_en | BIT(channel);
83 dev->pending_dma_cmd |= dma_cmd | DMA_CMD_ENABLE | BIT(channel);
84}
85
86/*
87 * The purpose of this awful hack is to avoid enabling the DMA
88 * channels "too fast" which makes some TW686x devices very
89 * angry and freeze the CPU (see note 1).
90 */
91static void tw686x_dma_delay(unsigned long data)
92{
93 struct tw686x_dev *dev = (struct tw686x_dev *)data;
94 unsigned long flags;
95
96 spin_lock_irqsave(&dev->lock, flags);
97
98 reg_write(dev, DMA_CHANNEL_ENABLE, dev->pending_dma_en);
99 reg_write(dev, DMA_CMD, dev->pending_dma_cmd);
100 dev->pending_dma_en = 0;
101 dev->pending_dma_cmd = 0;
102
103 spin_unlock_irqrestore(&dev->lock, flags);
104}
105
106static void tw686x_reset_channels(struct tw686x_dev *dev, unsigned int ch_mask)
107{
108 u32 dma_en, dma_cmd;
109
110 dma_en = reg_read(dev, DMA_CHANNEL_ENABLE);
111 dma_cmd = reg_read(dev, DMA_CMD);
112
113 /*
114 * Save pending register status, the timer will
115 * restore them.
116 */
117 dev->pending_dma_en |= dma_en;
118 dev->pending_dma_cmd |= dma_cmd;
119
120 /* Disable the reset channels */
121 reg_write(dev, DMA_CHANNEL_ENABLE, dma_en & ~ch_mask);
122
123 if ((dma_en & ~ch_mask) == 0) {
124 dev_dbg(&dev->pci_dev->dev, "reset: stopping DMA\n");
125 dma_cmd &= ~DMA_CMD_ENABLE;
126 }
127 reg_write(dev, DMA_CMD, dma_cmd & ~ch_mask);
128}
129
130static irqreturn_t tw686x_irq(int irq, void *dev_id)
131{
132 struct tw686x_dev *dev = (struct tw686x_dev *)dev_id;
133 unsigned int video_requests, audio_requests, reset_ch;
134 u32 fifo_status, fifo_signal, fifo_ov, fifo_bad, fifo_errors;
135 u32 int_status, dma_en, video_en, pb_status;
136 unsigned long flags;
137
138 int_status = reg_read(dev, INT_STATUS); /* cleared on read */
139 fifo_status = reg_read(dev, VIDEO_FIFO_STATUS);
140
141 /* INT_STATUS does not include FIFO_STATUS errors! */
142 if (!int_status && !TW686X_FIFO_ERROR(fifo_status))
143 return IRQ_NONE;
144
145 if (int_status & INT_STATUS_DMA_TOUT) {
146 dev_dbg(&dev->pci_dev->dev,
147 "DMA timeout. Resetting DMA for all channels\n");
148 reset_ch = ~0;
149 goto reset_channels;
150 }
151
152 spin_lock_irqsave(&dev->lock, flags);
153 dma_en = reg_read(dev, DMA_CHANNEL_ENABLE);
154 spin_unlock_irqrestore(&dev->lock, flags);
155
156 video_en = dma_en & 0xff;
157 fifo_signal = ~(fifo_status & 0xff) & video_en;
158 fifo_ov = fifo_status >> 24;
159 fifo_bad = fifo_status >> 16;
160
161 /* Mask of channels with signal and FIFO errors */
162 fifo_errors = fifo_signal & (fifo_ov | fifo_bad);
163
164 reset_ch = 0;
165 pb_status = reg_read(dev, PB_STATUS);
166
167 /* Coalesce video frame/error events */
168 video_requests = (int_status & video_en) | fifo_errors;
169 audio_requests = (int_status & dma_en) >> 8;
170
171 if (video_requests)
172 tw686x_video_irq(dev, video_requests, pb_status,
173 fifo_status, &reset_ch);
174 if (audio_requests)
175 tw686x_audio_irq(dev, audio_requests, pb_status);
176
177reset_channels:
178 if (reset_ch) {
179 spin_lock_irqsave(&dev->lock, flags);
180 tw686x_reset_channels(dev, reset_ch);
181 spin_unlock_irqrestore(&dev->lock, flags);
182 mod_timer(&dev->dma_delay_timer,
183 jiffies + msecs_to_jiffies(100));
184 }
185
186 return IRQ_HANDLED;
187}
188
189static void tw686x_dev_release(struct v4l2_device *v4l2_dev)
190{
191 struct tw686x_dev *dev = container_of(v4l2_dev, struct tw686x_dev,
192 v4l2_dev);
193 unsigned int ch;
194
195 for (ch = 0; ch < max_channels(dev); ch++)
196 v4l2_ctrl_handler_free(&dev->video_channels[ch].ctrl_handler);
197
198 v4l2_device_unregister(&dev->v4l2_dev);
199
200 kfree(dev->audio_channels);
201 kfree(dev->video_channels);
202 kfree(dev);
203}
204
205static int tw686x_probe(struct pci_dev *pci_dev,
206 const struct pci_device_id *pci_id)
207{
208 struct tw686x_dev *dev;
209 int err;
210
211 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
212 if (!dev)
213 return -ENOMEM;
214 dev->type = pci_id->driver_data;
215 sprintf(dev->name, "tw%04X", pci_dev->device);
216
217 dev->video_channels = kcalloc(max_channels(dev),
218 sizeof(*dev->video_channels), GFP_KERNEL);
219 if (!dev->video_channels) {
220 err = -ENOMEM;
221 goto free_dev;
222 }
223
224 dev->audio_channels = kcalloc(max_channels(dev),
225 sizeof(*dev->audio_channels), GFP_KERNEL);
226 if (!dev->audio_channels) {
227 err = -ENOMEM;
228 goto free_video;
229 }
230
231 pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx\n", dev->name,
232 pci_name(pci_dev), pci_dev->irq,
233 (unsigned long)pci_resource_start(pci_dev, 0));
234
235 dev->pci_dev = pci_dev;
236 if (pci_enable_device(pci_dev)) {
237 err = -EIO;
238 goto free_audio;
239 }
240
241 pci_set_master(pci_dev);
242 err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
243 if (err) {
244 dev_err(&pci_dev->dev, "32-bit PCI DMA not supported\n");
245 err = -EIO;
246 goto disable_pci;
247 }
248
249 err = pci_request_regions(pci_dev, dev->name);
250 if (err) {
251 dev_err(&pci_dev->dev, "unable to request PCI region\n");
252 goto disable_pci;
253 }
254
255 dev->mmio = pci_ioremap_bar(pci_dev, 0);
256 if (!dev->mmio) {
257 dev_err(&pci_dev->dev, "unable to remap PCI region\n");
258 err = -ENOMEM;
259 goto free_region;
260 }
261
262 /* Reset all subsystems */
263 reg_write(dev, SYS_SOFT_RST, 0x0f);
264 mdelay(1);
265
266 reg_write(dev, SRST[0], 0x3f);
267 if (max_channels(dev) > 4)
268 reg_write(dev, SRST[1], 0x3f);
269
270 /* Disable the DMA engine */
271 reg_write(dev, DMA_CMD, 0);
272 reg_write(dev, DMA_CHANNEL_ENABLE, 0);
273
274 /* Enable DMA FIFO overflow and pointer check */
275 reg_write(dev, DMA_CONFIG, 0xffffff04);
276 reg_write(dev, DMA_CHANNEL_TIMEOUT, 0x140c8584);
277 reg_write(dev, DMA_TIMER_INTERVAL, dma_interval);
278
279 spin_lock_init(&dev->lock);
280
281 err = request_irq(pci_dev->irq, tw686x_irq, IRQF_SHARED,
282 dev->name, dev);
283 if (err < 0) {
284 dev_err(&pci_dev->dev, "unable to request interrupt\n");
285 goto iounmap;
286 }
287
288 setup_timer(&dev->dma_delay_timer,
289 tw686x_dma_delay, (unsigned long) dev);
290
291 /*
292 * This must be set right before initializing v4l2_dev.
293 * It's used to release resources after the last handle
294 * held is released.
295 */
296 dev->v4l2_dev.release = tw686x_dev_release;
297 err = tw686x_video_init(dev);
298 if (err) {
299 dev_err(&pci_dev->dev, "can't register video\n");
300 goto free_irq;
301 }
302
303 err = tw686x_audio_init(dev);
304 if (err)
305 dev_warn(&pci_dev->dev, "can't register audio\n");
306
307 pci_set_drvdata(pci_dev, dev);
308 return 0;
309
310free_irq:
311 free_irq(pci_dev->irq, dev);
312iounmap:
313 pci_iounmap(pci_dev, dev->mmio);
314free_region:
315 pci_release_regions(pci_dev);
316disable_pci:
317 pci_disable_device(pci_dev);
318free_audio:
319 kfree(dev->audio_channels);
320free_video:
321 kfree(dev->video_channels);
322free_dev:
323 kfree(dev);
324 return err;
325}
326
327static void tw686x_remove(struct pci_dev *pci_dev)
328{
329 struct tw686x_dev *dev = pci_get_drvdata(pci_dev);
330 unsigned long flags;
331
332 /* This guarantees the IRQ handler is no longer running,
333 * which means we can kiss good-bye some resources.
334 */
335 free_irq(pci_dev->irq, dev);
336
337 tw686x_video_free(dev);
338 tw686x_audio_free(dev);
339 del_timer_sync(&dev->dma_delay_timer);
340
341 pci_iounmap(pci_dev, dev->mmio);
342 pci_release_regions(pci_dev);
343 pci_disable_device(pci_dev);
344
345 /*
346 * Setting pci_dev to NULL allows to detect hardware is no longer
347 * available and will be used by vb2_ops. This is required because
348 * the device sometimes hot-unplugs itself as the result of a PCIe
349 * link down.
350 * The lock is really important here.
351 */
352 spin_lock_irqsave(&dev->lock, flags);
353 dev->pci_dev = NULL;
354 spin_unlock_irqrestore(&dev->lock, flags);
355
356 /*
357 * This calls tw686x_dev_release if it's the last reference.
358 * Otherwise, release is postponed until there are no users left.
359 */
360 v4l2_device_put(&dev->v4l2_dev);
361}
362
363/*
364 * On TW6864 and TW6868, all channels share the pair of video DMA SG tables,
365 * with 10-bit start_idx and end_idx determining start and end of frame buffer
366 * for particular channel.
367 * TW6868 with all its 8 channels would be problematic (only 127 SG entries per
368 * channel) but we support only 4 channels on this chip anyway (the first
369 * 4 channels are driven with internal video decoder, the other 4 would require
370 * an external TW286x part).
371 *
372 * On TW6865 and TW6869, each channel has its own DMA SG table, with indexes
373 * starting with 0. Both chips have complete sets of internal video decoders
374 * (respectively 4 or 8-channel).
375 *
376 * All chips have separate SG tables for two video frames.
377 */
378
379/* driver_data is number of A/V channels */
380static const struct pci_device_id tw686x_pci_tbl[] = {
381 {
382 PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6864),
383 .driver_data = 4
384 },
385 {
386 PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6865), /* not tested */
387 .driver_data = 4 | TYPE_SECOND_GEN
388 },
389 /*
390 * TW6868 supports 8 A/V channels with an external TW2865 chip;
391 * not supported by the driver.
392 */
393 {
394 PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6868), /* not tested */
395 .driver_data = 4
396 },
397 {
398 PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6869),
399 .driver_data = 8 | TYPE_SECOND_GEN},
400 {}
401};
402MODULE_DEVICE_TABLE(pci, tw686x_pci_tbl);
403
404static struct pci_driver tw686x_pci_driver = {
405 .name = "tw686x",
406 .id_table = tw686x_pci_tbl,
407 .probe = tw686x_probe,
408 .remove = tw686x_remove,
409};
410module_pci_driver(tw686x_pci_driver);
411
412MODULE_DESCRIPTION("Driver for video frame grabber cards based on Intersil/Techwell TW686[4589]");
413MODULE_AUTHOR("Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>");
414MODULE_AUTHOR("Krzysztof Ha?asa <khalasa@piap.pl>");
415MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/pci/tw686x/tw686x-regs.h b/drivers/media/pci/tw686x/tw686x-regs.h
new file mode 100644
index 000000000000..fcef586a4c8c
--- /dev/null
+++ b/drivers/media/pci/tw686x/tw686x-regs.h
@@ -0,0 +1,122 @@
1/* DMA controller registers */
2#define REG8_1(a0) ((const u16[8]) { a0, a0 + 1, a0 + 2, a0 + 3, \
3 a0 + 4, a0 + 5, a0 + 6, a0 + 7})
4#define REG8_2(a0) ((const u16[8]) { a0, a0 + 2, a0 + 4, a0 + 6, \
5 a0 + 8, a0 + 0xa, a0 + 0xc, a0 + 0xe})
6#define REG8_8(a0) ((const u16[8]) { a0, a0 + 8, a0 + 0x10, a0 + 0x18, \
7 a0 + 0x20, a0 + 0x28, a0 + 0x30, \
8 a0 + 0x38})
9#define INT_STATUS 0x00
10#define PB_STATUS 0x01
11#define DMA_CMD 0x02
12#define VIDEO_FIFO_STATUS 0x03
13#define VIDEO_CHANNEL_ID 0x04
14#define VIDEO_PARSER_STATUS 0x05
15#define SYS_SOFT_RST 0x06
16#define DMA_PAGE_TABLE0_ADDR ((const u16[8]) { 0x08, 0xd0, 0xd2, 0xd4, \
17 0xd6, 0xd8, 0xda, 0xdc })
18#define DMA_PAGE_TABLE1_ADDR ((const u16[8]) { 0x09, 0xd1, 0xd3, 0xd5, \
19 0xd7, 0xd9, 0xdb, 0xdd })
20#define DMA_CHANNEL_ENABLE 0x0a
21#define DMA_CONFIG 0x0b
22#define DMA_TIMER_INTERVAL 0x0c
23#define DMA_CHANNEL_TIMEOUT 0x0d
24#define VDMA_CHANNEL_CONFIG REG8_1(0x10)
25#define ADMA_P_ADDR REG8_2(0x18)
26#define ADMA_B_ADDR REG8_2(0x19)
27#define DMA10_P_ADDR 0x28
28#define DMA10_B_ADDR 0x29
29#define VIDEO_CONTROL1 0x2a
30#define VIDEO_CONTROL2 0x2b
31#define AUDIO_CONTROL1 0x2c
32#define AUDIO_CONTROL2 0x2d
33#define PHASE_REF 0x2e
34#define GPIO_REG 0x2f
35#define INTL_HBAR_CTRL REG8_1(0x30)
36#define AUDIO_CONTROL3 0x38
37#define VIDEO_FIELD_CTRL REG8_1(0x39)
38#define HSCALER_CTRL REG8_1(0x42)
39#define VIDEO_SIZE REG8_1(0x4A)
40#define VIDEO_SIZE_F2 REG8_1(0x52)
41#define MD_CONF REG8_1(0x60)
42#define MD_INIT REG8_1(0x68)
43#define MD_MAP0 REG8_1(0x70)
44#define VDMA_P_ADDR REG8_8(0x80) /* not used in DMA SG mode */
45#define VDMA_WHP REG8_8(0x81)
46#define VDMA_B_ADDR REG8_8(0x82)
47#define VDMA_F2_P_ADDR REG8_8(0x84)
48#define VDMA_F2_WHP REG8_8(0x85)
49#define VDMA_F2_B_ADDR REG8_8(0x86)
50#define EP_REG_ADDR 0xfe
51#define EP_REG_DATA 0xff
52
53/* Video decoder registers */
54#define VDREG8(a0) ((const u16[8]) { \
55 a0 + 0x000, a0 + 0x010, a0 + 0x020, a0 + 0x030, \
56 a0 + 0x100, a0 + 0x110, a0 + 0x120, a0 + 0x130})
57#define VIDSTAT VDREG8(0x100)
58#define BRIGHT VDREG8(0x101)
59#define CONTRAST VDREG8(0x102)
60#define SHARPNESS VDREG8(0x103)
61#define SAT_U VDREG8(0x104)
62#define SAT_V VDREG8(0x105)
63#define HUE VDREG8(0x106)
64#define CROP_HI VDREG8(0x107)
65#define VDELAY_LO VDREG8(0x108)
66#define VACTIVE_LO VDREG8(0x109)
67#define HDELAY_LO VDREG8(0x10a)
68#define HACTIVE_LO VDREG8(0x10b)
69#define MVSN VDREG8(0x10c)
70#define STATUS2 VDREG8(0x10d)
71#define SDT VDREG8(0x10e)
72#define SDT_EN VDREG8(0x10f)
73
74#define VSCALE_LO VDREG8(0x144)
75#define SCALE_HI VDREG8(0x145)
76#define HSCALE_LO VDREG8(0x146)
77#define F2CROP_HI VDREG8(0x147)
78#define F2VDELAY_LO VDREG8(0x148)
79#define F2VACTIVE_LO VDREG8(0x149)
80#define F2HDELAY_LO VDREG8(0x14a)
81#define F2HACTIVE_LO VDREG8(0x14b)
82#define F2VSCALE_LO VDREG8(0x14c)
83#define F2SCALE_HI VDREG8(0x14d)
84#define F2HSCALE_LO VDREG8(0x14e)
85#define F2CNT VDREG8(0x14f)
86
87#define VDREG2(a0) ((const u16[2]) { a0, a0 + 0x100 })
88#define SRST VDREG2(0x180)
89#define ACNTL VDREG2(0x181)
90#define ACNTL2 VDREG2(0x182)
91#define CNTRL1 VDREG2(0x183)
92#define CKHY VDREG2(0x184)
93#define SHCOR VDREG2(0x185)
94#define CORING VDREG2(0x186)
95#define CLMPG VDREG2(0x187)
96#define IAGC VDREG2(0x188)
97#define VCTRL1 VDREG2(0x18f)
98#define MISC1 VDREG2(0x194)
99#define LOOP VDREG2(0x195)
100#define MISC2 VDREG2(0x196)
101
102#define CLMD VDREG2(0x197)
103#define ANPWRDOWN VDREG2(0x1ce)
104#define AIGAIN ((const u16[8]) { 0x1d0, 0x1d1, 0x1d2, 0x1d3, \
105 0x2d0, 0x2d1, 0x2d2, 0x2d3 })
106
107#define SYS_MODE_DMA_SHIFT 13
108
109#define DMA_CMD_ENABLE BIT(31)
110#define INT_STATUS_DMA_TOUT BIT(17)
111#define TW686X_VIDSTAT_HLOCK BIT(6)
112#define TW686X_VIDSTAT_VDLOSS BIT(7)
113
114#define TW686X_STD_NTSC_M 0
115#define TW686X_STD_PAL 1
116#define TW686X_STD_SECAM 2
117#define TW686X_STD_NTSC_443 3
118#define TW686X_STD_PAL_M 4
119#define TW686X_STD_PAL_CN 5
120#define TW686X_STD_PAL_60 6
121
122#define TW686X_FIFO_ERROR(x) (x & ~(0xff))
diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c
new file mode 100644
index 000000000000..253e10823ba3
--- /dev/null
+++ b/drivers/media/pci/tw686x/tw686x-video.c
@@ -0,0 +1,937 @@
1/*
2 * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar
3 *
4 * Based on original driver by Krzysztof Ha?asa:
5 * Copyright (C) 2015 Industrial Research Institute for Automation
6 * and Measurements PIAP
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of version 2 of the GNU General Public License
10 * as published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/init.h>
15#include <linux/delay.h>
16#include <linux/list.h>
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/slab.h>
20#include <media/v4l2-common.h>
21#include <media/v4l2-event.h>
22#include <media/videobuf2-vmalloc.h>
23#include "tw686x.h"
24#include "tw686x-regs.h"
25
26#define TW686X_INPUTS_PER_CH 4
27#define TW686X_VIDEO_WIDTH 720
28#define TW686X_VIDEO_HEIGHT(id) ((id & V4L2_STD_525_60) ? 480 : 576)
29
30static const struct tw686x_format formats[] = {
31 {
32 .fourcc = V4L2_PIX_FMT_UYVY,
33 .mode = 0,
34 .depth = 16,
35 }, {
36 .fourcc = V4L2_PIX_FMT_RGB565,
37 .mode = 5,
38 .depth = 16,
39 }, {
40 .fourcc = V4L2_PIX_FMT_YUYV,
41 .mode = 6,
42 .depth = 16,
43 }
44};
45
46static unsigned int tw686x_fields_map(v4l2_std_id std, unsigned int fps)
47{
48 static const unsigned int map[15] = {
49 0x00000000, 0x00000001, 0x00004001, 0x00104001, 0x00404041,
50 0x01041041, 0x01104411, 0x01111111, 0x04444445, 0x04511445,
51 0x05145145, 0x05151515, 0x05515455, 0x05551555, 0x05555555
52 };
53
54 static const unsigned int std_625_50[26] = {
55 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7,
56 8, 8, 9, 10, 10, 11, 11, 12, 13, 13, 14, 14, 0
57 };
58
59 static const unsigned int std_525_60[31] = {
60 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
61 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 0, 0
62 };
63
64 unsigned int i;
65
66 if (std & V4L2_STD_525_60) {
67 if (fps >= ARRAY_SIZE(std_525_60))
68 fps = 30;
69 i = std_525_60[fps];
70 } else {
71 if (fps >= ARRAY_SIZE(std_625_50))
72 fps = 25;
73 i = std_625_50[fps];
74 }
75
76 return map[i];
77}
78
79static void tw686x_set_framerate(struct tw686x_video_channel *vc,
80 unsigned int fps)
81{
82 unsigned int map;
83
84 if (vc->fps == fps)
85 return;
86
87 map = tw686x_fields_map(vc->video_standard, fps) << 1;
88 map |= map << 1;
89 if (map > 0)
90 map |= BIT(31);
91 reg_write(vc->dev, VIDEO_FIELD_CTRL[vc->ch], map);
92 vc->fps = fps;
93}
94
95static const struct tw686x_format *format_by_fourcc(unsigned int fourcc)
96{
97 unsigned int cnt;
98
99 for (cnt = 0; cnt < ARRAY_SIZE(formats); cnt++)
100 if (formats[cnt].fourcc == fourcc)
101 return &formats[cnt];
102 return NULL;
103}
104
105static int tw686x_queue_setup(struct vb2_queue *vq,
106 unsigned int *nbuffers, unsigned int *nplanes,
107 unsigned int sizes[], void *alloc_ctxs[])
108{
109 struct tw686x_video_channel *vc = vb2_get_drv_priv(vq);
110 unsigned int szimage =
111 (vc->width * vc->height * vc->format->depth) >> 3;
112
113 /*
114 * Let's request at least three buffers: two for the
115 * DMA engine and one for userspace.
116 */
117 if (vq->num_buffers + *nbuffers < 3)
118 *nbuffers = 3 - vq->num_buffers;
119
120 if (*nplanes) {
121 if (*nplanes != 1 || sizes[0] < szimage)
122 return -EINVAL;
123 return 0;
124 }
125
126 sizes[0] = szimage;
127 *nplanes = 1;
128 return 0;
129}
130
131static void tw686x_buf_queue(struct vb2_buffer *vb)
132{
133 struct tw686x_video_channel *vc = vb2_get_drv_priv(vb->vb2_queue);
134 struct tw686x_dev *dev = vc->dev;
135 struct pci_dev *pci_dev;
136 unsigned long flags;
137 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
138 struct tw686x_v4l2_buf *buf =
139 container_of(vbuf, struct tw686x_v4l2_buf, vb);
140
141 /* Check device presence */
142 spin_lock_irqsave(&dev->lock, flags);
143 pci_dev = dev->pci_dev;
144 spin_unlock_irqrestore(&dev->lock, flags);
145 if (!pci_dev) {
146 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
147 return;
148 }
149
150 spin_lock_irqsave(&vc->qlock, flags);
151 list_add_tail(&buf->list, &vc->vidq_queued);
152 spin_unlock_irqrestore(&vc->qlock, flags);
153}
154
155/*
156 * We can call this even when alloc_dma failed for the given channel
157 */
158static void tw686x_free_dma(struct tw686x_video_channel *vc, unsigned int pb)
159{
160 struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
161 struct tw686x_dev *dev = vc->dev;
162 struct pci_dev *pci_dev;
163 unsigned long flags;
164
165 /* Check device presence. Shouldn't really happen! */
166 spin_lock_irqsave(&dev->lock, flags);
167 pci_dev = dev->pci_dev;
168 spin_unlock_irqrestore(&dev->lock, flags);
169 if (!pci_dev) {
170 WARN(1, "trying to deallocate on missing device\n");
171 return;
172 }
173
174 if (desc->virt) {
175 pci_free_consistent(dev->pci_dev, desc->size,
176 desc->virt, desc->phys);
177 desc->virt = NULL;
178 }
179}
180
181static int tw686x_alloc_dma(struct tw686x_video_channel *vc, unsigned int pb)
182{
183 struct tw686x_dev *dev = vc->dev;
184 u32 reg = pb ? VDMA_B_ADDR[vc->ch] : VDMA_P_ADDR[vc->ch];
185 unsigned int len;
186 void *virt;
187
188 WARN(vc->dma_descs[pb].virt,
189 "Allocating buffer but previous still here\n");
190
191 len = (vc->width * vc->height * vc->format->depth) >> 3;
192 virt = pci_alloc_consistent(dev->pci_dev, len,
193 &vc->dma_descs[pb].phys);
194 if (!virt) {
195 v4l2_err(&dev->v4l2_dev,
196 "dma%d: unable to allocate %s-buffer\n",
197 vc->ch, pb ? "B" : "P");
198 return -ENOMEM;
199 }
200 vc->dma_descs[pb].size = len;
201 vc->dma_descs[pb].virt = virt;
202 reg_write(dev, reg, vc->dma_descs[pb].phys);
203
204 return 0;
205}
206
207static void tw686x_buffer_refill(struct tw686x_video_channel *vc,
208 unsigned int pb)
209{
210 struct tw686x_v4l2_buf *buf;
211
212 while (!list_empty(&vc->vidq_queued)) {
213
214 buf = list_first_entry(&vc->vidq_queued,
215 struct tw686x_v4l2_buf, list);
216 list_del(&buf->list);
217
218 vc->curr_bufs[pb] = buf;
219 return;
220 }
221 vc->curr_bufs[pb] = NULL;
222}
223
224static void tw686x_clear_queue(struct tw686x_video_channel *vc,
225 enum vb2_buffer_state state)
226{
227 unsigned int pb;
228
229 while (!list_empty(&vc->vidq_queued)) {
230 struct tw686x_v4l2_buf *buf;
231
232 buf = list_first_entry(&vc->vidq_queued,
233 struct tw686x_v4l2_buf, list);
234 list_del(&buf->list);
235 vb2_buffer_done(&buf->vb.vb2_buf, state);
236 }
237
238 for (pb = 0; pb < 2; pb++) {
239 if (vc->curr_bufs[pb])
240 vb2_buffer_done(&vc->curr_bufs[pb]->vb.vb2_buf, state);
241 vc->curr_bufs[pb] = NULL;
242 }
243}
244
245static int tw686x_start_streaming(struct vb2_queue *vq, unsigned int count)
246{
247 struct tw686x_video_channel *vc = vb2_get_drv_priv(vq);
248 struct tw686x_dev *dev = vc->dev;
249 struct pci_dev *pci_dev;
250 unsigned long flags;
251 int pb, err;
252
253 /* Check device presence */
254 spin_lock_irqsave(&dev->lock, flags);
255 pci_dev = dev->pci_dev;
256 spin_unlock_irqrestore(&dev->lock, flags);
257 if (!pci_dev) {
258 err = -ENODEV;
259 goto err_clear_queue;
260 }
261
262 spin_lock_irqsave(&vc->qlock, flags);
263
264 /* Sanity check */
265 if (!vc->dma_descs[0].virt || !vc->dma_descs[1].virt) {
266 spin_unlock_irqrestore(&vc->qlock, flags);
267 v4l2_err(&dev->v4l2_dev,
268 "video%d: refusing to start without DMA buffers\n",
269 vc->num);
270 err = -ENOMEM;
271 goto err_clear_queue;
272 }
273
274 for (pb = 0; pb < 2; pb++)
275 tw686x_buffer_refill(vc, pb);
276 spin_unlock_irqrestore(&vc->qlock, flags);
277
278 vc->sequence = 0;
279 vc->pb = 0;
280
281 spin_lock_irqsave(&dev->lock, flags);
282 tw686x_enable_channel(dev, vc->ch);
283 spin_unlock_irqrestore(&dev->lock, flags);
284
285 mod_timer(&dev->dma_delay_timer, jiffies + msecs_to_jiffies(100));
286
287 return 0;
288
289err_clear_queue:
290 spin_lock_irqsave(&vc->qlock, flags);
291 tw686x_clear_queue(vc, VB2_BUF_STATE_QUEUED);
292 spin_unlock_irqrestore(&vc->qlock, flags);
293 return err;
294}
295
296static void tw686x_stop_streaming(struct vb2_queue *vq)
297{
298 struct tw686x_video_channel *vc = vb2_get_drv_priv(vq);
299 struct tw686x_dev *dev = vc->dev;
300 struct pci_dev *pci_dev;
301 unsigned long flags;
302
303 /* Check device presence */
304 spin_lock_irqsave(&dev->lock, flags);
305 pci_dev = dev->pci_dev;
306 spin_unlock_irqrestore(&dev->lock, flags);
307 if (pci_dev)
308 tw686x_disable_channel(dev, vc->ch);
309
310 spin_lock_irqsave(&vc->qlock, flags);
311 tw686x_clear_queue(vc, VB2_BUF_STATE_ERROR);
312 spin_unlock_irqrestore(&vc->qlock, flags);
313}
314
315static int tw686x_buf_prepare(struct vb2_buffer *vb)
316{
317 struct tw686x_video_channel *vc = vb2_get_drv_priv(vb->vb2_queue);
318 unsigned int size =
319 (vc->width * vc->height * vc->format->depth) >> 3;
320
321 if (vb2_plane_size(vb, 0) < size)
322 return -EINVAL;
323 vb2_set_plane_payload(vb, 0, size);
324 return 0;
325}
326
327static struct vb2_ops tw686x_video_qops = {
328 .queue_setup = tw686x_queue_setup,
329 .buf_queue = tw686x_buf_queue,
330 .buf_prepare = tw686x_buf_prepare,
331 .start_streaming = tw686x_start_streaming,
332 .stop_streaming = tw686x_stop_streaming,
333 .wait_prepare = vb2_ops_wait_prepare,
334 .wait_finish = vb2_ops_wait_finish,
335};
336
337static int tw686x_s_ctrl(struct v4l2_ctrl *ctrl)
338{
339 struct tw686x_video_channel *vc;
340 struct tw686x_dev *dev;
341 unsigned int ch;
342
343 vc = container_of(ctrl->handler, struct tw686x_video_channel,
344 ctrl_handler);
345 dev = vc->dev;
346 ch = vc->ch;
347
348 switch (ctrl->id) {
349 case V4L2_CID_BRIGHTNESS:
350 reg_write(dev, BRIGHT[ch], ctrl->val & 0xff);
351 return 0;
352
353 case V4L2_CID_CONTRAST:
354 reg_write(dev, CONTRAST[ch], ctrl->val);
355 return 0;
356
357 case V4L2_CID_SATURATION:
358 reg_write(dev, SAT_U[ch], ctrl->val);
359 reg_write(dev, SAT_V[ch], ctrl->val);
360 return 0;
361
362 case V4L2_CID_HUE:
363 reg_write(dev, HUE[ch], ctrl->val & 0xff);
364 return 0;
365 }
366
367 return -EINVAL;
368}
369
370static const struct v4l2_ctrl_ops ctrl_ops = {
371 .s_ctrl = tw686x_s_ctrl,
372};
373
374static int tw686x_g_fmt_vid_cap(struct file *file, void *priv,
375 struct v4l2_format *f)
376{
377 struct tw686x_video_channel *vc = video_drvdata(file);
378
379 f->fmt.pix.width = vc->width;
380 f->fmt.pix.height = vc->height;
381 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
382 f->fmt.pix.pixelformat = vc->format->fourcc;
383 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
384 f->fmt.pix.bytesperline = (f->fmt.pix.width * vc->format->depth) / 8;
385 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
386 return 0;
387}
388
389static int tw686x_try_fmt_vid_cap(struct file *file, void *priv,
390 struct v4l2_format *f)
391{
392 struct tw686x_video_channel *vc = video_drvdata(file);
393 unsigned int video_height = TW686X_VIDEO_HEIGHT(vc->video_standard);
394 const struct tw686x_format *format;
395
396 format = format_by_fourcc(f->fmt.pix.pixelformat);
397 if (!format) {
398 format = &formats[0];
399 f->fmt.pix.pixelformat = format->fourcc;
400 }
401
402 if (f->fmt.pix.width <= TW686X_VIDEO_WIDTH / 2)
403 f->fmt.pix.width = TW686X_VIDEO_WIDTH / 2;
404 else
405 f->fmt.pix.width = TW686X_VIDEO_WIDTH;
406
407 if (f->fmt.pix.height <= video_height / 2)
408 f->fmt.pix.height = video_height / 2;
409 else
410 f->fmt.pix.height = video_height;
411
412 f->fmt.pix.bytesperline = (f->fmt.pix.width * format->depth) / 8;
413 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
414 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
415 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
416
417 return 0;
418}
419
420static int tw686x_s_fmt_vid_cap(struct file *file, void *priv,
421 struct v4l2_format *f)
422{
423 struct tw686x_video_channel *vc = video_drvdata(file);
424 u32 val, width, line_width, height;
425 unsigned long bitsperframe;
426 int err, pb;
427
428 if (vb2_is_busy(&vc->vidq))
429 return -EBUSY;
430
431 bitsperframe = vc->width * vc->height * vc->format->depth;
432 err = tw686x_try_fmt_vid_cap(file, priv, f);
433 if (err)
434 return err;
435
436 vc->format = format_by_fourcc(f->fmt.pix.pixelformat);
437 vc->width = f->fmt.pix.width;
438 vc->height = f->fmt.pix.height;
439
440 /* We need new DMA buffers if the framesize has changed */
441 if (bitsperframe != vc->width * vc->height * vc->format->depth) {
442 for (pb = 0; pb < 2; pb++)
443 tw686x_free_dma(vc, pb);
444
445 for (pb = 0; pb < 2; pb++) {
446 err = tw686x_alloc_dma(vc, pb);
447 if (err) {
448 if (pb > 0)
449 tw686x_free_dma(vc, 0);
450 return err;
451 }
452 }
453 }
454
455 val = reg_read(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch]);
456
457 if (vc->width <= TW686X_VIDEO_WIDTH / 2)
458 val |= BIT(23);
459 else
460 val &= ~BIT(23);
461
462 if (vc->height <= TW686X_VIDEO_HEIGHT(vc->video_standard) / 2)
463 val |= BIT(24);
464 else
465 val &= ~BIT(24);
466
467 val &= ~(0x7 << 20);
468 val |= vc->format->mode << 20;
469 reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], val);
470
471 /* Program the DMA frame size */
472 width = (vc->width * 2) & 0x7ff;
473 height = vc->height / 2;
474 line_width = (vc->width * 2) & 0x7ff;
475 val = (height << 22) | (line_width << 11) | width;
476 reg_write(vc->dev, VDMA_WHP[vc->ch], val);
477 return 0;
478}
479
480static int tw686x_querycap(struct file *file, void *priv,
481 struct v4l2_capability *cap)
482{
483 struct tw686x_video_channel *vc = video_drvdata(file);
484 struct tw686x_dev *dev = vc->dev;
485
486 strlcpy(cap->driver, "tw686x", sizeof(cap->driver));
487 strlcpy(cap->card, dev->name, sizeof(cap->card));
488 snprintf(cap->bus_info, sizeof(cap->bus_info),
489 "PCI:%s", pci_name(dev->pci_dev));
490 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
491 V4L2_CAP_READWRITE;
492 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
493 return 0;
494}
495
496static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id)
497{
498 struct tw686x_video_channel *vc = video_drvdata(file);
499 struct v4l2_format f;
500 u32 val, ret;
501
502 if (vc->video_standard == id)
503 return 0;
504
505 if (vb2_is_busy(&vc->vidq))
506 return -EBUSY;
507
508 if (id & V4L2_STD_NTSC)
509 val = 0;
510 else if (id & V4L2_STD_PAL)
511 val = 1;
512 else if (id & V4L2_STD_SECAM)
513 val = 2;
514 else if (id & V4L2_STD_NTSC_443)
515 val = 3;
516 else if (id & V4L2_STD_PAL_M)
517 val = 4;
518 else if (id & V4L2_STD_PAL_Nc)
519 val = 5;
520 else if (id & V4L2_STD_PAL_60)
521 val = 6;
522 else
523 return -EINVAL;
524
525 vc->video_standard = id;
526 reg_write(vc->dev, SDT[vc->ch], val);
527
528 val = reg_read(vc->dev, VIDEO_CONTROL1);
529 if (id & V4L2_STD_525_60)
530 val &= ~(1 << (SYS_MODE_DMA_SHIFT + vc->ch));
531 else
532 val |= (1 << (SYS_MODE_DMA_SHIFT + vc->ch));
533 reg_write(vc->dev, VIDEO_CONTROL1, val);
534
535 /*
536 * Adjust format after V4L2_STD_525_60/V4L2_STD_625_50 change,
537 * calling g_fmt and s_fmt will sanitize the height
538 * according to the standard.
539 */
540 ret = tw686x_g_fmt_vid_cap(file, priv, &f);
541 if (!ret)
542 tw686x_s_fmt_vid_cap(file, priv, &f);
543 return 0;
544}
545
546static int tw686x_querystd(struct file *file, void *priv, v4l2_std_id *std)
547{
548 struct tw686x_video_channel *vc = video_drvdata(file);
549 struct tw686x_dev *dev = vc->dev;
550 unsigned int old_std, detected_std = 0;
551 unsigned long end;
552
553 if (vb2_is_streaming(&vc->vidq))
554 return -EBUSY;
555
556 /* Enable and start standard detection */
557 old_std = reg_read(dev, SDT[vc->ch]);
558 reg_write(dev, SDT[vc->ch], 0x7);
559 reg_write(dev, SDT_EN[vc->ch], 0xff);
560
561 end = jiffies + msecs_to_jiffies(500);
562 while (time_is_after_jiffies(end)) {
563
564 detected_std = reg_read(dev, SDT[vc->ch]);
565 if (!(detected_std & BIT(7)))
566 break;
567 msleep(100);
568 }
569 reg_write(dev, SDT[vc->ch], old_std);
570
571 /* Exit if still busy */
572 if (detected_std & BIT(7))
573 return 0;
574
575 detected_std = (detected_std >> 4) & 0x7;
576 switch (detected_std) {
577 case TW686X_STD_NTSC_M:
578 *std &= V4L2_STD_NTSC;
579 break;
580 case TW686X_STD_NTSC_443:
581 *std &= V4L2_STD_NTSC_443;
582 break;
583 case TW686X_STD_PAL_M:
584 *std &= V4L2_STD_PAL_M;
585 break;
586 case TW686X_STD_PAL_60:
587 *std &= V4L2_STD_PAL_60;
588 break;
589 case TW686X_STD_PAL:
590 *std &= V4L2_STD_PAL;
591 break;
592 case TW686X_STD_PAL_CN:
593 *std &= V4L2_STD_PAL_Nc;
594 break;
595 case TW686X_STD_SECAM:
596 *std &= V4L2_STD_SECAM;
597 break;
598 default:
599 *std = 0;
600 }
601 return 0;
602}
603
604static int tw686x_g_std(struct file *file, void *priv, v4l2_std_id *id)
605{
606 struct tw686x_video_channel *vc = video_drvdata(file);
607
608 *id = vc->video_standard;
609 return 0;
610}
611
612static int tw686x_enum_fmt_vid_cap(struct file *file, void *priv,
613 struct v4l2_fmtdesc *f)
614{
615 if (f->index >= ARRAY_SIZE(formats))
616 return -EINVAL;
617 f->pixelformat = formats[f->index].fourcc;
618 return 0;
619}
620
621static int tw686x_s_input(struct file *file, void *priv, unsigned int i)
622{
623 struct tw686x_video_channel *vc = video_drvdata(file);
624 u32 val;
625
626 if (i >= TW686X_INPUTS_PER_CH)
627 return -EINVAL;
628 if (i == vc->input)
629 return 0;
630 /*
631 * Not sure we are able to support on the fly input change
632 */
633 if (vb2_is_busy(&vc->vidq))
634 return -EBUSY;
635
636 vc->input = i;
637
638 val = reg_read(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch]);
639 val &= ~(0x3 << 30);
640 val |= i << 30;
641 reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], val);
642 return 0;
643}
644
645static int tw686x_g_input(struct file *file, void *priv, unsigned int *i)
646{
647 struct tw686x_video_channel *vc = video_drvdata(file);
648
649 *i = vc->input;
650 return 0;
651}
652
653static int tw686x_enum_input(struct file *file, void *priv,
654 struct v4l2_input *i)
655{
656 struct tw686x_video_channel *vc = video_drvdata(file);
657 unsigned int vidstat;
658
659 if (i->index >= TW686X_INPUTS_PER_CH)
660 return -EINVAL;
661
662 snprintf(i->name, sizeof(i->name), "Composite%d", i->index);
663 i->type = V4L2_INPUT_TYPE_CAMERA;
664 i->std = vc->device->tvnorms;
665 i->capabilities = V4L2_IN_CAP_STD;
666
667 vidstat = reg_read(vc->dev, VIDSTAT[vc->ch]);
668 i->status = 0;
669 if (vidstat & TW686X_VIDSTAT_VDLOSS)
670 i->status |= V4L2_IN_ST_NO_SIGNAL;
671 if (!(vidstat & TW686X_VIDSTAT_HLOCK))
672 i->status |= V4L2_IN_ST_NO_H_LOCK;
673
674 return 0;
675}
676
677static const struct v4l2_file_operations tw686x_video_fops = {
678 .owner = THIS_MODULE,
679 .open = v4l2_fh_open,
680 .unlocked_ioctl = video_ioctl2,
681 .release = vb2_fop_release,
682 .poll = vb2_fop_poll,
683 .read = vb2_fop_read,
684 .mmap = vb2_fop_mmap,
685};
686
687static const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = {
688 .vidioc_querycap = tw686x_querycap,
689 .vidioc_g_fmt_vid_cap = tw686x_g_fmt_vid_cap,
690 .vidioc_s_fmt_vid_cap = tw686x_s_fmt_vid_cap,
691 .vidioc_enum_fmt_vid_cap = tw686x_enum_fmt_vid_cap,
692 .vidioc_try_fmt_vid_cap = tw686x_try_fmt_vid_cap,
693
694 .vidioc_querystd = tw686x_querystd,
695 .vidioc_g_std = tw686x_g_std,
696 .vidioc_s_std = tw686x_s_std,
697
698 .vidioc_enum_input = tw686x_enum_input,
699 .vidioc_g_input = tw686x_g_input,
700 .vidioc_s_input = tw686x_s_input,
701
702 .vidioc_reqbufs = vb2_ioctl_reqbufs,
703 .vidioc_querybuf = vb2_ioctl_querybuf,
704 .vidioc_qbuf = vb2_ioctl_qbuf,
705 .vidioc_dqbuf = vb2_ioctl_dqbuf,
706 .vidioc_create_bufs = vb2_ioctl_create_bufs,
707 .vidioc_streamon = vb2_ioctl_streamon,
708 .vidioc_streamoff = vb2_ioctl_streamoff,
709 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
710
711 .vidioc_log_status = v4l2_ctrl_log_status,
712 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
713 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
714};
715
716static void tw686x_buffer_copy(struct tw686x_video_channel *vc,
717 unsigned int pb, struct vb2_v4l2_buffer *vb)
718{
719 struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
720 struct vb2_buffer *vb2_buf = &vb->vb2_buf;
721
722 vb->field = V4L2_FIELD_INTERLACED;
723 vb->sequence = vc->sequence++;
724
725 memcpy(vb2_plane_vaddr(vb2_buf, 0), desc->virt, desc->size);
726 vb2_buf->timestamp = ktime_get_ns();
727 vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE);
728}
729
730void tw686x_video_irq(struct tw686x_dev *dev, unsigned long requests,
731 unsigned int pb_status, unsigned int fifo_status,
732 unsigned int *reset_ch)
733{
734 struct tw686x_video_channel *vc;
735 struct vb2_v4l2_buffer *vb;
736 unsigned long flags;
737 unsigned int ch, pb;
738
739 for_each_set_bit(ch, &requests, max_channels(dev)) {
740 vc = &dev->video_channels[ch];
741
742 /*
743 * This can either be a blue frame (with signal-lost bit set)
744 * or a good frame (with signal-lost bit clear). If we have just
745 * got signal, then this channel needs resetting.
746 */
747 if (vc->no_signal && !(fifo_status & BIT(ch))) {
748 v4l2_printk(KERN_DEBUG, &dev->v4l2_dev,
749 "video%d: signal recovered\n", vc->num);
750 vc->no_signal = false;
751 *reset_ch |= BIT(ch);
752 vc->pb = 0;
753 continue;
754 }
755 vc->no_signal = !!(fifo_status & BIT(ch));
756
757 /* Check FIFO errors only if there's signal */
758 if (!vc->no_signal) {
759 u32 fifo_ov, fifo_bad;
760
761 fifo_ov = (fifo_status >> 24) & BIT(ch);
762 fifo_bad = (fifo_status >> 16) & BIT(ch);
763 if (fifo_ov || fifo_bad) {
764 /* Mark this channel for reset */
765 v4l2_printk(KERN_DEBUG, &dev->v4l2_dev,
766 "video%d: FIFO error\n", vc->num);
767 *reset_ch |= BIT(ch);
768 vc->pb = 0;
769 continue;
770 }
771 }
772
773 pb = !!(pb_status & BIT(ch));
774 if (vc->pb != pb) {
775 /* Mark this channel for reset */
776 v4l2_printk(KERN_DEBUG, &dev->v4l2_dev,
777 "video%d: unexpected p-b buffer!\n",
778 vc->num);
779 *reset_ch |= BIT(ch);
780 vc->pb = 0;
781 continue;
782 }
783
784 /* handle video stream */
785 spin_lock_irqsave(&vc->qlock, flags);
786 if (vc->curr_bufs[pb]) {
787 vb = &vc->curr_bufs[pb]->vb;
788 tw686x_buffer_copy(vc, pb, vb);
789 }
790 vc->pb = !pb;
791 tw686x_buffer_refill(vc, pb);
792 spin_unlock_irqrestore(&vc->qlock, flags);
793 }
794}
795
796void tw686x_video_free(struct tw686x_dev *dev)
797{
798 unsigned int ch, pb;
799
800 for (ch = 0; ch < max_channels(dev); ch++) {
801 struct tw686x_video_channel *vc = &dev->video_channels[ch];
802
803 if (vc->device)
804 video_unregister_device(vc->device);
805
806 for (pb = 0; pb < 2; pb++)
807 tw686x_free_dma(vc, pb);
808 }
809}
810
811int tw686x_video_init(struct tw686x_dev *dev)
812{
813 unsigned int ch, val, pb;
814 int err;
815
816 err = v4l2_device_register(&dev->pci_dev->dev, &dev->v4l2_dev);
817 if (err)
818 return err;
819
820 for (ch = 0; ch < max_channels(dev); ch++) {
821 struct tw686x_video_channel *vc = &dev->video_channels[ch];
822 struct video_device *vdev;
823
824 mutex_init(&vc->vb_mutex);
825 spin_lock_init(&vc->qlock);
826 INIT_LIST_HEAD(&vc->vidq_queued);
827
828 vc->dev = dev;
829 vc->ch = ch;
830
831 /* default settings */
832 vc->format = &formats[0];
833 vc->video_standard = V4L2_STD_NTSC;
834 vc->width = TW686X_VIDEO_WIDTH;
835 vc->height = TW686X_VIDEO_HEIGHT(vc->video_standard);
836 vc->input = 0;
837
838 reg_write(vc->dev, SDT[ch], 0);
839 tw686x_set_framerate(vc, 30);
840
841 reg_write(dev, VDELAY_LO[ch], 0x14);
842 reg_write(dev, HACTIVE_LO[ch], 0xd0);
843 reg_write(dev, VIDEO_SIZE[ch], 0);
844
845 for (pb = 0; pb < 2; pb++) {
846 err = tw686x_alloc_dma(vc, pb);
847 if (err)
848 goto error;
849 }
850
851 vc->vidq.io_modes = VB2_READ | VB2_MMAP | VB2_DMABUF;
852 vc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
853 vc->vidq.drv_priv = vc;
854 vc->vidq.buf_struct_size = sizeof(struct tw686x_v4l2_buf);
855 vc->vidq.ops = &tw686x_video_qops;
856 vc->vidq.mem_ops = &vb2_vmalloc_memops;
857 vc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
858 vc->vidq.min_buffers_needed = 2;
859 vc->vidq.lock = &vc->vb_mutex;
860 vc->vidq.gfp_flags = GFP_DMA32;
861
862 err = vb2_queue_init(&vc->vidq);
863 if (err) {
864 v4l2_err(&dev->v4l2_dev,
865 "dma%d: cannot init vb2 queue\n", ch);
866 goto error;
867 }
868
869 err = v4l2_ctrl_handler_init(&vc->ctrl_handler, 4);
870 if (err) {
871 v4l2_err(&dev->v4l2_dev,
872 "dma%d: cannot init ctrl handler\n", ch);
873 goto error;
874 }
875 v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops,
876 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
877 v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops,
878 V4L2_CID_CONTRAST, 0, 255, 1, 100);
879 v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops,
880 V4L2_CID_SATURATION, 0, 255, 1, 128);
881 v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops,
882 V4L2_CID_HUE, -128, 127, 1, 0);
883 err = vc->ctrl_handler.error;
884 if (err)
885 goto error;
886
887 err = v4l2_ctrl_handler_setup(&vc->ctrl_handler);
888 if (err)
889 goto error;
890
891 vdev = video_device_alloc();
892 if (!vdev) {
893 v4l2_err(&dev->v4l2_dev,
894 "dma%d: unable to allocate device\n", ch);
895 err = -ENOMEM;
896 goto error;
897 }
898
899 snprintf(vdev->name, sizeof(vdev->name), "%s video", dev->name);
900 vdev->fops = &tw686x_video_fops;
901 vdev->ioctl_ops = &tw686x_video_ioctl_ops;
902 vdev->release = video_device_release;
903 vdev->v4l2_dev = &dev->v4l2_dev;
904 vdev->queue = &vc->vidq;
905 vdev->tvnorms = V4L2_STD_525_60 | V4L2_STD_625_50;
906 vdev->minor = -1;
907 vdev->lock = &vc->vb_mutex;
908 vdev->ctrl_handler = &vc->ctrl_handler;
909 vc->device = vdev;
910 video_set_drvdata(vdev, vc);
911
912 err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
913 if (err < 0)
914 goto error;
915 vc->num = vdev->num;
916 }
917
918 /* Set DMA frame mode on all channels. Only supported mode for now. */
919 val = TW686X_DEF_PHASE_REF;
920 for (ch = 0; ch < max_channels(dev); ch++)
921 val |= TW686X_FRAME_MODE << (16 + ch * 2);
922 reg_write(dev, PHASE_REF, val);
923
924 reg_write(dev, MISC2[0], 0xe7);
925 reg_write(dev, VCTRL1[0], 0xcc);
926 reg_write(dev, LOOP[0], 0xa5);
927 if (max_channels(dev) > 4) {
928 reg_write(dev, VCTRL1[1], 0xcc);
929 reg_write(dev, LOOP[1], 0xa5);
930 reg_write(dev, MISC2[1], 0xe7);
931 }
932 return 0;
933
934error:
935 tw686x_video_free(dev);
936 return err;
937}
diff --git a/drivers/media/pci/tw686x/tw686x.h b/drivers/media/pci/tw686x/tw686x.h
new file mode 100644
index 000000000000..44b5755acf02
--- /dev/null
+++ b/drivers/media/pci/tw686x/tw686x.h
@@ -0,0 +1,158 @@
1/*
2 * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar
3 *
4 * Copyright (C) 2015 Industrial Research Institute for Automation
5 * and Measurements PIAP
6 * Written by Krzysztof Ha?asa
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of version 2 of the GNU General Public License
10 * as published by the Free Software Foundation.
11 */
12
13#include <linux/mutex.h>
14#include <linux/pci.h>
15#include <linux/timer.h>
16#include <linux/videodev2.h>
17#include <media/v4l2-common.h>
18#include <media/v4l2-ctrls.h>
19#include <media/v4l2-device.h>
20#include <media/v4l2-ioctl.h>
21#include <media/videobuf2-v4l2.h>
22#include <sound/pcm.h>
23
24#include "tw686x-regs.h"
25
26#define TYPE_MAX_CHANNELS 0x0f
27#define TYPE_SECOND_GEN 0x10
28#define TW686X_DEF_PHASE_REF 0x1518
29
30#define TW686X_FIELD_MODE 0x3
31#define TW686X_FRAME_MODE 0x2
32/* 0x1 is reserved */
33#define TW686X_SG_MODE 0x0
34
35#define TW686X_AUDIO_PAGE_SZ 4096
36#define TW686X_AUDIO_PAGE_MAX 16
37#define TW686X_AUDIO_PERIODS_MIN 2
38#define TW686X_AUDIO_PERIODS_MAX TW686X_AUDIO_PAGE_MAX
39
40struct tw686x_format {
41 char *name;
42 unsigned int fourcc;
43 unsigned int depth;
44 unsigned int mode;
45};
46
47struct tw686x_dma_desc {
48 dma_addr_t phys;
49 void *virt;
50 unsigned int size;
51};
52
53struct tw686x_audio_buf {
54 dma_addr_t dma;
55 void *virt;
56 struct list_head list;
57};
58
59struct tw686x_v4l2_buf {
60 struct vb2_v4l2_buffer vb;
61 struct list_head list;
62};
63
64struct tw686x_audio_channel {
65 struct tw686x_dev *dev;
66 struct snd_pcm_substream *ss;
67 unsigned int ch;
68 struct tw686x_audio_buf *curr_bufs[2];
69 struct tw686x_dma_desc dma_descs[2];
70 dma_addr_t ptr;
71
72 struct tw686x_audio_buf buf[TW686X_AUDIO_PAGE_MAX];
73 struct list_head buf_list;
74 spinlock_t lock;
75};
76
77struct tw686x_video_channel {
78 struct tw686x_dev *dev;
79
80 struct vb2_queue vidq;
81 struct list_head vidq_queued;
82 struct video_device *device;
83 struct tw686x_v4l2_buf *curr_bufs[2];
84 struct tw686x_dma_desc dma_descs[2];
85
86 struct v4l2_ctrl_handler ctrl_handler;
87 const struct tw686x_format *format;
88 struct mutex vb_mutex;
89 spinlock_t qlock;
90 v4l2_std_id video_standard;
91 unsigned int width, height;
92 unsigned int h_halve, v_halve;
93 unsigned int ch;
94 unsigned int num;
95 unsigned int fps;
96 unsigned int input;
97 unsigned int sequence;
98 unsigned int pb;
99 bool no_signal;
100};
101
102/**
103 * struct tw686x_dev - global device status
104 * @lock: spinlock controlling access to the
105 * shared device registers (DMA enable/disable).
106 */
107struct tw686x_dev {
108 spinlock_t lock;
109
110 struct v4l2_device v4l2_dev;
111 struct snd_card *snd_card;
112
113 char name[32];
114 unsigned int type;
115 struct pci_dev *pci_dev;
116 __u32 __iomem *mmio;
117
118 void *alloc_ctx;
119
120 struct tw686x_video_channel *video_channels;
121 struct tw686x_audio_channel *audio_channels;
122
123 int audio_rate; /* per-device value */
124
125 struct timer_list dma_delay_timer;
126 u32 pending_dma_en; /* must be protected by lock */
127 u32 pending_dma_cmd; /* must be protected by lock */
128};
129
130static inline uint32_t reg_read(struct tw686x_dev *dev, unsigned int reg)
131{
132 return readl(dev->mmio + reg);
133}
134
135static inline void reg_write(struct tw686x_dev *dev, unsigned int reg,
136 uint32_t value)
137{
138 writel(value, dev->mmio + reg);
139}
140
141static inline unsigned int max_channels(struct tw686x_dev *dev)
142{
143 return dev->type & TYPE_MAX_CHANNELS; /* 4 or 8 channels */
144}
145
146void tw686x_enable_channel(struct tw686x_dev *dev, unsigned int channel);
147void tw686x_disable_channel(struct tw686x_dev *dev, unsigned int channel);
148
149int tw686x_video_init(struct tw686x_dev *dev);
150void tw686x_video_free(struct tw686x_dev *dev);
151void tw686x_video_irq(struct tw686x_dev *dev, unsigned long requests,
152 unsigned int pb_status, unsigned int fifo_status,
153 unsigned int *reset_ch);
154
155int tw686x_audio_init(struct tw686x_dev *dev);
156void tw686x_audio_free(struct tw686x_dev *dev);
157void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests,
158 unsigned int pb_status);
diff --git a/drivers/media/pci/zoran/videocodec.c b/drivers/media/pci/zoran/videocodec.c
index c01071635290..13a3c07cd259 100644
--- a/drivers/media/pci/zoran/videocodec.c
+++ b/drivers/media/pci/zoran/videocodec.c
@@ -116,8 +116,9 @@ videocodec_attach (struct videocodec_master *master)
116 goto out_module_put; 116 goto out_module_put;
117 } 117 }
118 118
119 snprintf(codec->name, sizeof(codec->name), 119 res = strlen(codec->name);
120 "%s[%d]", codec->name, h->attached); 120 snprintf(codec->name + res, sizeof(codec->name) - res,
121 "[%d]", h->attached);
121 codec->master_data = master; 122 codec->master_data = master;
122 res = codec->setup(codec); 123 res = codec->setup(codec);
123 if (res == 0) { 124 if (res == 0) {
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 201f5c296a95..84e041c0a70e 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -238,7 +238,7 @@ config VIDEO_SH_VEU
238config VIDEO_RENESAS_JPU 238config VIDEO_RENESAS_JPU
239 tristate "Renesas JPEG Processing Unit" 239 tristate "Renesas JPEG Processing Unit"
240 depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA 240 depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
241 depends on ARCH_SHMOBILE || COMPILE_TEST 241 depends on ARCH_RENESAS || COMPILE_TEST
242 select VIDEOBUF2_DMA_CONTIG 242 select VIDEOBUF2_DMA_CONTIG
243 select V4L2_MEM2MEM_DEV 243 select V4L2_MEM2MEM_DEV
244 ---help--- 244 ---help---
@@ -250,7 +250,7 @@ config VIDEO_RENESAS_JPU
250config VIDEO_RENESAS_VSP1 250config VIDEO_RENESAS_VSP1
251 tristate "Renesas VSP1 Video Processing Engine" 251 tristate "Renesas VSP1 Video Processing Engine"
252 depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA 252 depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA
253 depends on (ARCH_SHMOBILE && OF) || COMPILE_TEST 253 depends on (ARCH_RENESAS && OF) || COMPILE_TEST
254 select VIDEOBUF2_DMA_CONTIG 254 select VIDEOBUF2_DMA_CONTIG
255 ---help--- 255 ---help---
256 This is a V4L2 driver for the Renesas VSP1 video processing engine. 256 This is a V4L2 driver for the Renesas VSP1 video processing engine.
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index de32e3a3d4d1..e749eb7c3be9 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -1047,7 +1047,7 @@ static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe,
1047static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe) 1047static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe)
1048{ 1048{
1049 enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED; 1049 enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED;
1050 int ret; 1050 int ret = 0;
1051 1051
1052 vpfe_dbg(2, vpfe, "vpfe_config_ccdc_image_format\n"); 1052 vpfe_dbg(2, vpfe, "vpfe_config_ccdc_image_format\n");
1053 1053
@@ -1706,7 +1706,7 @@ static int vpfe_get_app_input_index(struct vpfe_device *vpfe,
1706 sdinfo = &cfg->sub_devs[i]; 1706 sdinfo = &cfg->sub_devs[i];
1707 client = v4l2_get_subdevdata(sdinfo->sd); 1707 client = v4l2_get_subdevdata(sdinfo->sd);
1708 if (client->addr == curr_client->addr && 1708 if (client->addr == curr_client->addr &&
1709 client->adapter->nr == client->adapter->nr) { 1709 client->adapter->nr == curr_client->adapter->nr) {
1710 if (vpfe->current_input >= 1) 1710 if (vpfe->current_input >= 1)
1711 return -1; 1711 return -1;
1712 *app_input_index = j + vpfe->current_input; 1712 *app_input_index = j + vpfe->current_input;
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
index 9b9e423e4fc4..c04973669a47 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.c
+++ b/drivers/media/platform/exynos-gsc/gsc-core.c
@@ -967,15 +967,6 @@ static struct gsc_driverdata gsc_v_100_drvdata = {
967 .lclk_frequency = 266000000UL, 967 .lclk_frequency = 266000000UL,
968}; 968};
969 969
970static const struct platform_device_id gsc_driver_ids[] = {
971 {
972 .name = "exynos-gsc",
973 .driver_data = (unsigned long)&gsc_v_100_drvdata,
974 },
975 {},
976};
977MODULE_DEVICE_TABLE(platform, gsc_driver_ids);
978
979static const struct of_device_id exynos_gsc_match[] = { 970static const struct of_device_id exynos_gsc_match[] = {
980 { 971 {
981 .compatible = "samsung,exynos5-gsc", 972 .compatible = "samsung,exynos5-gsc",
@@ -988,17 +979,11 @@ MODULE_DEVICE_TABLE(of, exynos_gsc_match);
988static void *gsc_get_drv_data(struct platform_device *pdev) 979static void *gsc_get_drv_data(struct platform_device *pdev)
989{ 980{
990 struct gsc_driverdata *driver_data = NULL; 981 struct gsc_driverdata *driver_data = NULL;
982 const struct of_device_id *match;
991 983
992 if (pdev->dev.of_node) { 984 match = of_match_node(exynos_gsc_match, pdev->dev.of_node);
993 const struct of_device_id *match; 985 if (match)
994 match = of_match_node(exynos_gsc_match, 986 driver_data = (struct gsc_driverdata *)match->data;
995 pdev->dev.of_node);
996 if (match)
997 driver_data = (struct gsc_driverdata *)match->data;
998 } else {
999 driver_data = (struct gsc_driverdata *)
1000 platform_get_device_id(pdev)->driver_data;
1001 }
1002 987
1003 return driver_data; 988 return driver_data;
1004} 989}
@@ -1078,17 +1063,17 @@ static int gsc_probe(struct platform_device *pdev)
1078 struct resource *res; 1063 struct resource *res;
1079 struct gsc_driverdata *drv_data = gsc_get_drv_data(pdev); 1064 struct gsc_driverdata *drv_data = gsc_get_drv_data(pdev);
1080 struct device *dev = &pdev->dev; 1065 struct device *dev = &pdev->dev;
1081 int ret = 0; 1066 int ret;
1082 1067
1083 gsc = devm_kzalloc(dev, sizeof(struct gsc_dev), GFP_KERNEL); 1068 gsc = devm_kzalloc(dev, sizeof(struct gsc_dev), GFP_KERNEL);
1084 if (!gsc) 1069 if (!gsc)
1085 return -ENOMEM; 1070 return -ENOMEM;
1086 1071
1087 if (dev->of_node) 1072 ret = of_alias_get_id(pdev->dev.of_node, "gsc");
1088 gsc->id = of_alias_get_id(pdev->dev.of_node, "gsc"); 1073 if (ret < 0)
1089 else 1074 return ret;
1090 gsc->id = pdev->id;
1091 1075
1076 gsc->id = ret;
1092 if (gsc->id >= drv_data->num_entities) { 1077 if (gsc->id >= drv_data->num_entities) {
1093 dev_err(dev, "Invalid platform device id: %d\n", gsc->id); 1078 dev_err(dev, "Invalid platform device id: %d\n", gsc->id);
1094 return -EINVAL; 1079 return -EINVAL;
@@ -1096,7 +1081,6 @@ static int gsc_probe(struct platform_device *pdev)
1096 1081
1097 gsc->variant = drv_data->variant[gsc->id]; 1082 gsc->variant = drv_data->variant[gsc->id];
1098 gsc->pdev = pdev; 1083 gsc->pdev = pdev;
1099 gsc->pdata = dev->platform_data;
1100 1084
1101 init_waitqueue_head(&gsc->irq_queue); 1085 init_waitqueue_head(&gsc->irq_queue);
1102 spin_lock_init(&gsc->slock); 1086 spin_lock_init(&gsc->slock);
@@ -1253,7 +1237,6 @@ static const struct dev_pm_ops gsc_pm_ops = {
1253static struct platform_driver gsc_driver = { 1237static struct platform_driver gsc_driver = {
1254 .probe = gsc_probe, 1238 .probe = gsc_probe,
1255 .remove = gsc_remove, 1239 .remove = gsc_remove,
1256 .id_table = gsc_driver_ids,
1257 .driver = { 1240 .driver = {
1258 .name = GSC_MODULE_NAME, 1241 .name = GSC_MODULE_NAME,
1259 .pm = &gsc_pm_ops, 1242 .pm = &gsc_pm_ops,
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index e93a2336cfa2..ec4000c72172 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -340,7 +340,6 @@ struct gsc_dev {
340 void __iomem *regs; 340 void __iomem *regs;
341 wait_queue_head_t irq_queue; 341 wait_queue_head_t irq_queue;
342 struct gsc_m2m_device m2m; 342 struct gsc_m2m_device m2m;
343 struct exynos_platform_gscaler *pdata;
344 unsigned long state; 343 unsigned long state;
345 struct vb2_alloc_ctx *alloc_ctx; 344 struct vb2_alloc_ctx *alloc_ctx;
346 struct video_device vdev; 345 struct video_device vdev;
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
index cef2a7f07cdb..b1c1cea82a27 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -1154,26 +1154,6 @@ static const struct fimc_pix_limit s5p_pix_limit[4] = {
1154 }, 1154 },
1155}; 1155};
1156 1156
1157static const struct fimc_variant fimc0_variant_s5p = {
1158 .has_inp_rot = 1,
1159 .has_out_rot = 1,
1160 .has_cam_if = 1,
1161 .min_inp_pixsize = 16,
1162 .min_out_pixsize = 16,
1163 .hor_offs_align = 8,
1164 .min_vsize_align = 16,
1165 .pix_limit = &s5p_pix_limit[0],
1166};
1167
1168static const struct fimc_variant fimc2_variant_s5p = {
1169 .has_cam_if = 1,
1170 .min_inp_pixsize = 16,
1171 .min_out_pixsize = 16,
1172 .hor_offs_align = 8,
1173 .min_vsize_align = 16,
1174 .pix_limit = &s5p_pix_limit[1],
1175};
1176
1177static const struct fimc_variant fimc0_variant_s5pv210 = { 1157static const struct fimc_variant fimc0_variant_s5pv210 = {
1178 .has_inp_rot = 1, 1158 .has_inp_rot = 1,
1179 .has_out_rot = 1, 1159 .has_out_rot = 1,
@@ -1206,18 +1186,6 @@ static const struct fimc_variant fimc2_variant_s5pv210 = {
1206 .pix_limit = &s5p_pix_limit[2], 1186 .pix_limit = &s5p_pix_limit[2],
1207}; 1187};
1208 1188
1209/* S5PC100 */
1210static const struct fimc_drvdata fimc_drvdata_s5p = {
1211 .variant = {
1212 [0] = &fimc0_variant_s5p,
1213 [1] = &fimc0_variant_s5p,
1214 [2] = &fimc2_variant_s5p,
1215 },
1216 .num_entities = 3,
1217 .lclk_frequency = 133000000UL,
1218 .out_buf_count = 4,
1219};
1220
1221/* S5PV210, S5PC110 */ 1189/* S5PV210, S5PC110 */
1222static const struct fimc_drvdata fimc_drvdata_s5pv210 = { 1190static const struct fimc_drvdata fimc_drvdata_s5pv210 = {
1223 .variant = { 1191 .variant = {
@@ -1251,23 +1219,6 @@ static const struct fimc_drvdata fimc_drvdata_exynos4x12 = {
1251 .out_buf_count = 32, 1219 .out_buf_count = 32,
1252}; 1220};
1253 1221
1254static const struct platform_device_id fimc_driver_ids[] = {
1255 {
1256 .name = "s5p-fimc",
1257 .driver_data = (unsigned long)&fimc_drvdata_s5p,
1258 }, {
1259 .name = "s5pv210-fimc",
1260 .driver_data = (unsigned long)&fimc_drvdata_s5pv210,
1261 }, {
1262 .name = "exynos4-fimc",
1263 .driver_data = (unsigned long)&fimc_drvdata_exynos4210,
1264 }, {
1265 .name = "exynos4x12-fimc",
1266 .driver_data = (unsigned long)&fimc_drvdata_exynos4x12,
1267 },
1268 { },
1269};
1270
1271static const struct of_device_id fimc_of_match[] = { 1222static const struct of_device_id fimc_of_match[] = {
1272 { 1223 {
1273 .compatible = "samsung,s5pv210-fimc", 1224 .compatible = "samsung,s5pv210-fimc",
@@ -1290,7 +1241,6 @@ static const struct dev_pm_ops fimc_pm_ops = {
1290static struct platform_driver fimc_driver = { 1241static struct platform_driver fimc_driver = {
1291 .probe = fimc_probe, 1242 .probe = fimc_probe,
1292 .remove = fimc_remove, 1243 .remove = fimc_remove,
1293 .id_table = fimc_driver_ids,
1294 .driver = { 1244 .driver = {
1295 .of_match_table = fimc_of_match, 1245 .of_match_table = fimc_of_match,
1296 .name = FIMC_DRIVER_NAME, 1246 .name = FIMC_DRIVER_NAME,
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index 4f494acd8150..891625e77ef5 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -446,8 +446,10 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
446 else 446 else
447 pd->fimc_bus_type = pd->sensor_bus_type; 447 pd->fimc_bus_type = pd->sensor_bus_type;
448 448
449 if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) 449 if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) {
450 of_node_put(rem);
450 return -EINVAL; 451 return -EINVAL;
452 }
451 453
452 fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_OF; 454 fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_OF;
453 fmd->sensor[index].asd.match.of.node = rem; 455 fmd->sensor[index].asd.match.of.node = rem;
@@ -1130,7 +1132,7 @@ static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable,
1130 media_entity_graph_walk_start(graph, entity); 1132 media_entity_graph_walk_start(graph, entity);
1131 1133
1132 while ((entity = media_entity_graph_walk_next(graph))) { 1134 while ((entity = media_entity_graph_walk_next(graph))) {
1133 if (!is_media_entity_v4l2_io(entity)) 1135 if (!is_media_entity_v4l2_video_device(entity))
1134 continue; 1136 continue;
1135 1137
1136 ret = __fimc_md_modify_pipeline(entity, enable); 1138 ret = __fimc_md_modify_pipeline(entity, enable);
@@ -1145,7 +1147,7 @@ err:
1145 media_entity_graph_walk_start(graph, entity_err); 1147 media_entity_graph_walk_start(graph, entity_err);
1146 1148
1147 while ((entity_err = media_entity_graph_walk_next(graph))) { 1149 while ((entity_err = media_entity_graph_walk_next(graph))) {
1148 if (!is_media_entity_v4l2_io(entity_err)) 1150 if (!is_media_entity_v4l2_video_device(entity_err))
1149 continue; 1151 continue;
1150 1152
1151 __fimc_md_modify_pipeline(entity_err, !enable); 1153 __fimc_md_modify_pipeline(entity_err, !enable);
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
index bd5c46c3d4b7..bf954424e7be 100644
--- a/drivers/media/platform/exynos4-is/mipi-csis.c
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -757,8 +757,10 @@ static int s5pcsis_parse_dt(struct platform_device *pdev,
757 goto err; 757 goto err;
758 758
759 state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0; 759 state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0;
760 if (state->index >= CSIS_MAX_ENTITIES) 760 if (state->index >= CSIS_MAX_ENTITIES) {
761 return -ENXIO; 761 ret = -ENXIO;
762 goto err;
763 }
762 764
763 /* Get MIPI CSI-2 bus configration from the endpoint node. */ 765 /* Get MIPI CSI-2 bus configration from the endpoint node. */
764 of_property_read_u32(node, "samsung,csis-hs-settle", 766 of_property_read_u32(node, "samsung,csis-hs-settle",
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index ac76d2901501..1b1a95d546f6 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -251,7 +251,7 @@ static int isp_video_get_graph_data(struct isp_video *video,
251 if (entity == &video->video.entity) 251 if (entity == &video->video.entity)
252 continue; 252 continue;
253 253
254 if (!is_media_entity_v4l2_io(entity)) 254 if (!is_media_entity_v4l2_video_device(entity))
255 continue; 255 continue;
256 256
257 __video = to_isp_video(media_entity_to_video_device(entity)); 257 __video = to_isp_video(media_entity_to_video_device(entity));
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index 74bd46ca7942..612d1ea514f1 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -719,16 +719,12 @@ static int g2d_probe(struct platform_device *pdev)
719 719
720 def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; 720 def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
721 721
722 if (!pdev->dev.of_node) { 722 of_id = of_match_node(exynos_g2d_match, pdev->dev.of_node);
723 dev->variant = g2d_get_drv_data(pdev); 723 if (!of_id) {
724 } else { 724 ret = -ENODEV;
725 of_id = of_match_node(exynos_g2d_match, pdev->dev.of_node); 725 goto unreg_video_dev;
726 if (!of_id) {
727 ret = -ENODEV;
728 goto unreg_video_dev;
729 }
730 dev->variant = (struct g2d_variant *)of_id->data;
731 } 726 }
727 dev->variant = (struct g2d_variant *)of_id->data;
732 728
733 return 0; 729 return 0;
734 730
@@ -788,22 +784,9 @@ static const struct of_device_id exynos_g2d_match[] = {
788}; 784};
789MODULE_DEVICE_TABLE(of, exynos_g2d_match); 785MODULE_DEVICE_TABLE(of, exynos_g2d_match);
790 786
791static const struct platform_device_id g2d_driver_ids[] = {
792 {
793 .name = "s5p-g2d",
794 .driver_data = (unsigned long)&g2d_drvdata_v3x,
795 }, {
796 .name = "s5p-g2d-v4x",
797 .driver_data = (unsigned long)&g2d_drvdata_v4x,
798 },
799 {},
800};
801MODULE_DEVICE_TABLE(platform, g2d_driver_ids);
802
803static struct platform_driver g2d_pdrv = { 787static struct platform_driver g2d_pdrv = {
804 .probe = g2d_probe, 788 .probe = g2d_probe,
805 .remove = g2d_remove, 789 .remove = g2d_remove,
806 .id_table = g2d_driver_ids,
807 .driver = { 790 .driver = {
808 .name = G2D_NAME, 791 .name = G2D_NAME,
809 .of_match_table = exynos_g2d_match, 792 .of_match_table = exynos_g2d_match,
diff --git a/drivers/media/platform/s5p-g2d/g2d.h b/drivers/media/platform/s5p-g2d/g2d.h
index b0e52ab7ecdb..e31df541aa62 100644
--- a/drivers/media/platform/s5p-g2d/g2d.h
+++ b/drivers/media/platform/s5p-g2d/g2d.h
@@ -89,8 +89,3 @@ void g2d_set_flip(struct g2d_dev *d, u32 r);
89void g2d_set_v41_stretch(struct g2d_dev *d, 89void g2d_set_v41_stretch(struct g2d_dev *d,
90 struct g2d_frame *src, struct g2d_frame *dst); 90 struct g2d_frame *src, struct g2d_frame *dst);
91void g2d_set_cmd(struct g2d_dev *d, u32 c); 91void g2d_set_cmd(struct g2d_dev *d, u32 c);
92
93static inline struct g2d_variant *g2d_get_drv_data(struct platform_device *pdev)
94{
95 return (struct g2d_variant *)platform_get_device_id(pdev)->driver_data;
96}
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index c3b13a630edf..caa19b408551 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -1548,8 +1548,10 @@ static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
1548 struct v4l2_pix_format *pix = &f->fmt.pix; 1548 struct v4l2_pix_format *pix = &f->fmt.pix;
1549 u32 pix_fmt = f->fmt.pix.pixelformat; 1549 u32 pix_fmt = f->fmt.pix.pixelformat;
1550 int w = pix->width, h = pix->height, wh_align; 1550 int w = pix->width, h = pix->height, wh_align;
1551 int padding = 0;
1551 1552
1552 if (pix_fmt == V4L2_PIX_FMT_RGB32 || 1553 if (pix_fmt == V4L2_PIX_FMT_RGB32 ||
1554 pix_fmt == V4L2_PIX_FMT_RGB565 ||
1553 pix_fmt == V4L2_PIX_FMT_NV24 || 1555 pix_fmt == V4L2_PIX_FMT_NV24 ||
1554 pix_fmt == V4L2_PIX_FMT_NV42 || 1556 pix_fmt == V4L2_PIX_FMT_NV42 ||
1555 pix_fmt == V4L2_PIX_FMT_NV12 || 1557 pix_fmt == V4L2_PIX_FMT_NV12 ||
@@ -1564,7 +1566,10 @@ static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
1564 &h, S5P_JPEG_MIN_HEIGHT, 1566 &h, S5P_JPEG_MIN_HEIGHT,
1565 S5P_JPEG_MAX_HEIGHT, wh_align); 1567 S5P_JPEG_MAX_HEIGHT, wh_align);
1566 1568
1567 return w * h * fmt_depth >> 3; 1569 if (ctx->jpeg->variant->version == SJPEG_EXYNOS4)
1570 padding = PAGE_SIZE;
1571
1572 return (w * h * fmt_depth >> 3) + padding;
1568} 1573}
1569 1574
1570static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx, 1575static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 927ab4928779..b16466fe35ee 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1489,27 +1489,6 @@ static struct s5p_mfc_variant mfc_drvdata_v8 = {
1489 .fw_name[0] = "s5p-mfc-v8.fw", 1489 .fw_name[0] = "s5p-mfc-v8.fw",
1490}; 1490};
1491 1491
1492static const struct platform_device_id mfc_driver_ids[] = {
1493 {
1494 .name = "s5p-mfc",
1495 .driver_data = (unsigned long)&mfc_drvdata_v5,
1496 }, {
1497 .name = "s5p-mfc-v5",
1498 .driver_data = (unsigned long)&mfc_drvdata_v5,
1499 }, {
1500 .name = "s5p-mfc-v6",
1501 .driver_data = (unsigned long)&mfc_drvdata_v6,
1502 }, {
1503 .name = "s5p-mfc-v7",
1504 .driver_data = (unsigned long)&mfc_drvdata_v7,
1505 }, {
1506 .name = "s5p-mfc-v8",
1507 .driver_data = (unsigned long)&mfc_drvdata_v8,
1508 },
1509 {},
1510};
1511MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
1512
1513static const struct of_device_id exynos_mfc_match[] = { 1492static const struct of_device_id exynos_mfc_match[] = {
1514 { 1493 {
1515 .compatible = "samsung,mfc-v5", 1494 .compatible = "samsung,mfc-v5",
@@ -1531,24 +1510,18 @@ MODULE_DEVICE_TABLE(of, exynos_mfc_match);
1531static void *mfc_get_drv_data(struct platform_device *pdev) 1510static void *mfc_get_drv_data(struct platform_device *pdev)
1532{ 1511{
1533 struct s5p_mfc_variant *driver_data = NULL; 1512 struct s5p_mfc_variant *driver_data = NULL;
1513 const struct of_device_id *match;
1514
1515 match = of_match_node(exynos_mfc_match, pdev->dev.of_node);
1516 if (match)
1517 driver_data = (struct s5p_mfc_variant *)match->data;
1534 1518
1535 if (pdev->dev.of_node) {
1536 const struct of_device_id *match;
1537 match = of_match_node(exynos_mfc_match,
1538 pdev->dev.of_node);
1539 if (match)
1540 driver_data = (struct s5p_mfc_variant *)match->data;
1541 } else {
1542 driver_data = (struct s5p_mfc_variant *)
1543 platform_get_device_id(pdev)->driver_data;
1544 }
1545 return driver_data; 1519 return driver_data;
1546} 1520}
1547 1521
1548static struct platform_driver s5p_mfc_driver = { 1522static struct platform_driver s5p_mfc_driver = {
1549 .probe = s5p_mfc_probe, 1523 .probe = s5p_mfc_probe,
1550 .remove = s5p_mfc_remove, 1524 .remove = s5p_mfc_remove,
1551 .id_table = mfc_driver_ids,
1552 .driver = { 1525 .driver = {
1553 .name = S5P_MFC_NAME, 1526 .name = S5P_MFC_NAME,
1554 .pm = &s5p_mfc_pm_ops, 1527 .pm = &s5p_mfc_pm_ops,
diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h
index 42cd2709c41c..4dd62a918fcf 100644
--- a/drivers/media/platform/s5p-tv/mixer.h
+++ b/drivers/media/platform/s5p-tv/mixer.h
@@ -300,7 +300,7 @@ void mxr_release_video(struct mxr_device *mdev);
300struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx); 300struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx);
301struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx); 301struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx);
302struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, 302struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
303 int idx, char *name, struct mxr_layer_ops *ops); 303 int idx, char *name, const struct mxr_layer_ops *ops);
304 304
305void mxr_base_layer_release(struct mxr_layer *layer); 305void mxr_base_layer_release(struct mxr_layer *layer);
306void mxr_layer_release(struct mxr_layer *layer); 306void mxr_layer_release(struct mxr_layer *layer);
diff --git a/drivers/media/platform/s5p-tv/mixer_grp_layer.c b/drivers/media/platform/s5p-tv/mixer_grp_layer.c
index db3163b23ea0..d4d2564f7de7 100644
--- a/drivers/media/platform/s5p-tv/mixer_grp_layer.c
+++ b/drivers/media/platform/s5p-tv/mixer_grp_layer.c
@@ -235,7 +235,7 @@ struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx)
235{ 235{
236 struct mxr_layer *layer; 236 struct mxr_layer *layer;
237 int ret; 237 int ret;
238 struct mxr_layer_ops ops = { 238 const struct mxr_layer_ops ops = {
239 .release = mxr_graph_layer_release, 239 .release = mxr_graph_layer_release,
240 .buffer_set = mxr_graph_buffer_set, 240 .buffer_set = mxr_graph_buffer_set,
241 .stream_set = mxr_graph_stream_set, 241 .stream_set = mxr_graph_stream_set,
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index d9e7f030294c..7ab5578a0405 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -1070,7 +1070,7 @@ static void mxr_vfd_release(struct video_device *vdev)
1070} 1070}
1071 1071
1072struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, 1072struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
1073 int idx, char *name, struct mxr_layer_ops *ops) 1073 int idx, char *name, const struct mxr_layer_ops *ops)
1074{ 1074{
1075 struct mxr_layer *layer; 1075 struct mxr_layer *layer;
1076 1076
diff --git a/drivers/media/platform/s5p-tv/mixer_vp_layer.c b/drivers/media/platform/s5p-tv/mixer_vp_layer.c
index dd002a497dbb..6fa6f673f53b 100644
--- a/drivers/media/platform/s5p-tv/mixer_vp_layer.c
+++ b/drivers/media/platform/s5p-tv/mixer_vp_layer.c
@@ -207,7 +207,7 @@ struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx)
207{ 207{
208 struct mxr_layer *layer; 208 struct mxr_layer *layer;
209 int ret; 209 int ret;
210 struct mxr_layer_ops ops = { 210 const struct mxr_layer_ops ops = {
211 .release = mxr_vp_layer_release, 211 .release = mxr_vp_layer_release,
212 .buffer_set = mxr_vp_buffer_set, 212 .buffer_set = mxr_vp_buffer_set,
213 .stream_set = mxr_vp_stream_set, 213 .stream_set = mxr_vp_stream_set,
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
index 355298989dd8..83029a4854ae 100644
--- a/drivers/media/platform/soc_camera/Kconfig
+++ b/drivers/media/platform/soc_camera/Kconfig
@@ -28,7 +28,7 @@ config VIDEO_PXA27x
28config VIDEO_RCAR_VIN 28config VIDEO_RCAR_VIN
29 tristate "R-Car Video Input (VIN) support" 29 tristate "R-Car Video Input (VIN) support"
30 depends on VIDEO_DEV && SOC_CAMERA 30 depends on VIDEO_DEV && SOC_CAMERA
31 depends on ARCH_SHMOBILE || COMPILE_TEST 31 depends on ARCH_RENESAS || COMPILE_TEST
32 depends on HAS_DMA 32 depends on HAS_DMA
33 select VIDEOBUF2_DMA_CONTIG 33 select VIDEOBUF2_DMA_CONTIG
34 select SOC_CAMERA_SCALE_CROP 34 select SOC_CAMERA_SCALE_CROP
@@ -45,7 +45,7 @@ config VIDEO_SH_MOBILE_CSI2
45config VIDEO_SH_MOBILE_CEU 45config VIDEO_SH_MOBILE_CEU
46 tristate "SuperH Mobile CEU Interface driver" 46 tristate "SuperH Mobile CEU Interface driver"
47 depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK 47 depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK
48 depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST 48 depends on ARCH_SHMOBILE || COMPILE_TEST
49 depends on HAS_DMA 49 depends on HAS_DMA
50 select VIDEOBUF2_DMA_CONTIG 50 select VIDEOBUF2_DMA_CONTIG
51 select SOC_CAMERA_SCALE_CROP 51 select SOC_CAMERA_SCALE_CROP
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 3b8edf458964..3f9c1b8456c3 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -1845,6 +1845,8 @@ static const struct of_device_id rcar_vin_of_table[] = {
1845 { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 }, 1845 { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
1846 { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 }, 1846 { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
1847 { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 }, 1847 { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
1848 { .compatible = "renesas,rcar-gen3-vin", .data = (void *)RCAR_GEN3 },
1849 { .compatible = "renesas,rcar-gen2-vin", .data = (void *)RCAR_GEN2 },
1848 { }, 1850 { },
1849}; 1851};
1850MODULE_DEVICE_TABLE(of, rcar_vin_of_table); 1852MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
index 78e3cb9a628f..7dddf77a62cf 100644
--- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
+++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
@@ -49,7 +49,7 @@ MODULE_FIRMWARE(FIRMWARE_MEMDMA);
49#define PID_TABLE_SIZE 1024 49#define PID_TABLE_SIZE 1024
50#define POLL_MSECS 50 50#define POLL_MSECS 50
51 51
52static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei); 52static int load_c8sectpfe_fw(struct c8sectpfei *fei);
53 53
54#define TS_PKT_SIZE 188 54#define TS_PKT_SIZE 188
55#define HEADER_SIZE (4) 55#define HEADER_SIZE (4)
@@ -130,7 +130,7 @@ static void channel_swdemux_tsklet(unsigned long data)
130 writel(channel->back_buffer_busaddr, channel->irec + 130 writel(channel->back_buffer_busaddr, channel->irec +
131 DMA_PRDS_BUSRP_TP(0)); 131 DMA_PRDS_BUSRP_TP(0));
132 else 132 else
133 writel(wp, channel->irec + DMA_PRDS_BUSWP_TP(0)); 133 writel(wp, channel->irec + DMA_PRDS_BUSRP_TP(0));
134} 134}
135 135
136static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed) 136static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed)
@@ -141,6 +141,7 @@ static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed)
141 struct channel_info *channel; 141 struct channel_info *channel;
142 u32 tmp; 142 u32 tmp;
143 unsigned long *bitmap; 143 unsigned long *bitmap;
144 int ret;
144 145
145 switch (dvbdmxfeed->type) { 146 switch (dvbdmxfeed->type) {
146 case DMX_TYPE_TS: 147 case DMX_TYPE_TS:
@@ -169,8 +170,9 @@ static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed)
169 } 170 }
170 171
171 if (!atomic_read(&fei->fw_loaded)) { 172 if (!atomic_read(&fei->fw_loaded)) {
172 dev_err(fei->dev, "%s: c8sectpfe fw not loaded\n", __func__); 173 ret = load_c8sectpfe_fw(fei);
173 return -EINVAL; 174 if (ret)
175 return ret;
174 } 176 }
175 177
176 mutex_lock(&fei->lock); 178 mutex_lock(&fei->lock);
@@ -265,8 +267,9 @@ static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
265 unsigned long *bitmap; 267 unsigned long *bitmap;
266 268
267 if (!atomic_read(&fei->fw_loaded)) { 269 if (!atomic_read(&fei->fw_loaded)) {
268 dev_err(fei->dev, "%s: c8sectpfe fw not loaded\n", __func__); 270 ret = load_c8sectpfe_fw(fei);
269 return -EINVAL; 271 if (ret)
272 return ret;
270 } 273 }
271 274
272 mutex_lock(&fei->lock); 275 mutex_lock(&fei->lock);
@@ -585,7 +588,7 @@ static int configure_memdma_and_inputblock(struct c8sectpfei *fei,
585 writel(tsin->pid_buffer_busaddr, 588 writel(tsin->pid_buffer_busaddr,
586 fei->io + PIDF_BASE(tsin->tsin_id)); 589 fei->io + PIDF_BASE(tsin->tsin_id));
587 590
588 dev_info(fei->dev, "chan=%d PIDF_BASE=0x%x pid_bus_addr=%pad\n", 591 dev_dbg(fei->dev, "chan=%d PIDF_BASE=0x%x pid_bus_addr=%pad\n",
589 tsin->tsin_id, readl(fei->io + PIDF_BASE(tsin->tsin_id)), 592 tsin->tsin_id, readl(fei->io + PIDF_BASE(tsin->tsin_id)),
590 &tsin->pid_buffer_busaddr); 593 &tsin->pid_buffer_busaddr);
591 594
@@ -880,13 +883,6 @@ static int c8sectpfe_probe(struct platform_device *pdev)
880 goto err_clk_disable; 883 goto err_clk_disable;
881 } 884 }
882 885
883 /* ensure all other init has been done before requesting firmware */
884 ret = load_c8sectpfe_fw_step1(fei);
885 if (ret) {
886 dev_err(dev, "Couldn't load slim core firmware\n");
887 goto err_clk_disable;
888 }
889
890 c8sectpfe_debugfs_init(fei); 886 c8sectpfe_debugfs_init(fei);
891 887
892 return 0; 888 return 0;
@@ -1091,15 +1087,14 @@ static void load_dmem_segment(struct c8sectpfei *fei, Elf32_Phdr *phdr,
1091 phdr->p_memsz - phdr->p_filesz); 1087 phdr->p_memsz - phdr->p_filesz);
1092} 1088}
1093 1089
1094static int load_slim_core_fw(const struct firmware *fw, void *context) 1090static int load_slim_core_fw(const struct firmware *fw, struct c8sectpfei *fei)
1095{ 1091{
1096 struct c8sectpfei *fei = context;
1097 Elf32_Ehdr *ehdr; 1092 Elf32_Ehdr *ehdr;
1098 Elf32_Phdr *phdr; 1093 Elf32_Phdr *phdr;
1099 u8 __iomem *dst; 1094 u8 __iomem *dst;
1100 int err = 0, i; 1095 int err = 0, i;
1101 1096
1102 if (!fw || !context) 1097 if (!fw || !fei)
1103 return -EINVAL; 1098 return -EINVAL;
1104 1099
1105 ehdr = (Elf32_Ehdr *)fw->data; 1100 ehdr = (Elf32_Ehdr *)fw->data;
@@ -1151,29 +1146,35 @@ static int load_slim_core_fw(const struct firmware *fw, void *context)
1151 return err; 1146 return err;
1152} 1147}
1153 1148
1154static void load_c8sectpfe_fw_cb(const struct firmware *fw, void *context) 1149static int load_c8sectpfe_fw(struct c8sectpfei *fei)
1155{ 1150{
1156 struct c8sectpfei *fei = context; 1151 const struct firmware *fw;
1157 int err; 1152 int err;
1158 1153
1154 dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA);
1155
1156 err = request_firmware(&fw, FIRMWARE_MEMDMA, fei->dev);
1157 if (err)
1158 return err;
1159
1159 err = c8sectpfe_elf_sanity_check(fei, fw); 1160 err = c8sectpfe_elf_sanity_check(fei, fw);
1160 if (err) { 1161 if (err) {
1161 dev_err(fei->dev, "c8sectpfe_elf_sanity_check failed err=(%d)\n" 1162 dev_err(fei->dev, "c8sectpfe_elf_sanity_check failed err=(%d)\n"
1162 , err); 1163 , err);
1163 goto err; 1164 return err;
1164 } 1165 }
1165 1166
1166 err = load_slim_core_fw(fw, context); 1167 err = load_slim_core_fw(fw, fei);
1167 if (err) { 1168 if (err) {
1168 dev_err(fei->dev, "load_slim_core_fw failed err=(%d)\n", err); 1169 dev_err(fei->dev, "load_slim_core_fw failed err=(%d)\n", err);
1169 goto err; 1170 return err;
1170 } 1171 }
1171 1172
1172 /* now the firmware is loaded configure the input blocks */ 1173 /* now the firmware is loaded configure the input blocks */
1173 err = configure_channels(fei); 1174 err = configure_channels(fei);
1174 if (err) { 1175 if (err) {
1175 dev_err(fei->dev, "configure_channels failed err=(%d)\n", err); 1176 dev_err(fei->dev, "configure_channels failed err=(%d)\n", err);
1176 goto err; 1177 return err;
1177 } 1178 }
1178 1179
1179 /* 1180 /*
@@ -1186,28 +1187,6 @@ static void load_c8sectpfe_fw_cb(const struct firmware *fw, void *context)
1186 writel(0x1, fei->io + DMA_CPU_RUN); 1187 writel(0x1, fei->io + DMA_CPU_RUN);
1187 1188
1188 atomic_set(&fei->fw_loaded, 1); 1189 atomic_set(&fei->fw_loaded, 1);
1189err:
1190 complete_all(&fei->fw_ack);
1191}
1192
1193static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei)
1194{
1195 int err;
1196
1197 dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA);
1198
1199 init_completion(&fei->fw_ack);
1200 atomic_set(&fei->fw_loaded, 0);
1201
1202 err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
1203 FIRMWARE_MEMDMA, fei->dev, GFP_KERNEL, fei,
1204 load_c8sectpfe_fw_cb);
1205
1206 if (err) {
1207 dev_err(fei->dev, "request_firmware_nowait err: %d.\n", err);
1208 complete_all(&fei->fw_ack);
1209 return err;
1210 }
1211 1190
1212 return 0; 1191 return 0;
1213} 1192}
diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig
index 0885e93ad436..f535f576913d 100644
--- a/drivers/media/platform/vivid/Kconfig
+++ b/drivers/media/platform/vivid/Kconfig
@@ -7,6 +7,7 @@ config VIDEO_VIVID
7 select FB_CFB_COPYAREA 7 select FB_CFB_COPYAREA
8 select FB_CFB_IMAGEBLIT 8 select FB_CFB_IMAGEBLIT
9 select VIDEOBUF2_VMALLOC 9 select VIDEOBUF2_VMALLOC
10 select VIDEO_V4L2_TPG
10 default n 11 default n
11 ---help--- 12 ---help---
12 Enables a virtual video driver. This driver emulates a webcam, 13 Enables a virtual video driver. This driver emulates a webcam,
diff --git a/drivers/media/platform/vivid/Makefile b/drivers/media/platform/vivid/Makefile
index 756fc12851df..633c8a1b2c27 100644
--- a/drivers/media/platform/vivid/Makefile
+++ b/drivers/media/platform/vivid/Makefile
@@ -2,5 +2,5 @@ vivid-objs := vivid-core.o vivid-ctrls.o vivid-vid-common.o vivid-vbi-gen.o \
2 vivid-vid-cap.o vivid-vid-out.o vivid-kthread-cap.o vivid-kthread-out.o \ 2 vivid-vid-cap.o vivid-vid-out.o vivid-kthread-cap.o vivid-kthread-out.o \
3 vivid-radio-rx.o vivid-radio-tx.o vivid-radio-common.o \ 3 vivid-radio-rx.o vivid-radio-tx.o vivid-radio-common.o \
4 vivid-rds-gen.o vivid-sdr-cap.o vivid-vbi-cap.o vivid-vbi-out.o \ 4 vivid-rds-gen.o vivid-sdr-cap.o vivid-vbi-cap.o vivid-vbi-out.o \
5 vivid-osd.o vivid-tpg.o vivid-tpg-colors.o 5 vivid-osd.o
6obj-$(CONFIG_VIDEO_VIVID) += vivid.o 6obj-$(CONFIG_VIDEO_VIVID) += vivid.o
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index ec125becb7af..c14da84af09b 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -200,27 +200,12 @@ static int vidioc_querycap(struct file *file, void *priv,
200 struct v4l2_capability *cap) 200 struct v4l2_capability *cap)
201{ 201{
202 struct vivid_dev *dev = video_drvdata(file); 202 struct vivid_dev *dev = video_drvdata(file);
203 struct video_device *vdev = video_devdata(file);
204 203
205 strcpy(cap->driver, "vivid"); 204 strcpy(cap->driver, "vivid");
206 strcpy(cap->card, "vivid"); 205 strcpy(cap->card, "vivid");
207 snprintf(cap->bus_info, sizeof(cap->bus_info), 206 snprintf(cap->bus_info, sizeof(cap->bus_info),
208 "platform:%s", dev->v4l2_dev.name); 207 "platform:%s", dev->v4l2_dev.name);
209 208
210 if (vdev->vfl_type == VFL_TYPE_GRABBER && vdev->vfl_dir == VFL_DIR_RX)
211 cap->device_caps = dev->vid_cap_caps;
212 if (vdev->vfl_type == VFL_TYPE_GRABBER && vdev->vfl_dir == VFL_DIR_TX)
213 cap->device_caps = dev->vid_out_caps;
214 else if (vdev->vfl_type == VFL_TYPE_VBI && vdev->vfl_dir == VFL_DIR_RX)
215 cap->device_caps = dev->vbi_cap_caps;
216 else if (vdev->vfl_type == VFL_TYPE_VBI && vdev->vfl_dir == VFL_DIR_TX)
217 cap->device_caps = dev->vbi_out_caps;
218 else if (vdev->vfl_type == VFL_TYPE_SDR)
219 cap->device_caps = dev->sdr_cap_caps;
220 else if (vdev->vfl_type == VFL_TYPE_RADIO && vdev->vfl_dir == VFL_DIR_RX)
221 cap->device_caps = dev->radio_rx_caps;
222 else if (vdev->vfl_type == VFL_TYPE_RADIO && vdev->vfl_dir == VFL_DIR_TX)
223 cap->device_caps = dev->radio_tx_caps;
224 cap->capabilities = dev->vid_cap_caps | dev->vid_out_caps | 209 cap->capabilities = dev->vid_cap_caps | dev->vid_out_caps |
225 dev->vbi_cap_caps | dev->vbi_out_caps | 210 dev->vbi_cap_caps | dev->vbi_out_caps |
226 dev->radio_rx_caps | dev->radio_tx_caps | 211 dev->radio_rx_caps | dev->radio_tx_caps |
@@ -1135,6 +1120,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
1135 strlcpy(vfd->name, "vivid-vid-cap", sizeof(vfd->name)); 1120 strlcpy(vfd->name, "vivid-vid-cap", sizeof(vfd->name));
1136 vfd->fops = &vivid_fops; 1121 vfd->fops = &vivid_fops;
1137 vfd->ioctl_ops = &vivid_ioctl_ops; 1122 vfd->ioctl_ops = &vivid_ioctl_ops;
1123 vfd->device_caps = dev->vid_cap_caps;
1138 vfd->release = video_device_release_empty; 1124 vfd->release = video_device_release_empty;
1139 vfd->v4l2_dev = &dev->v4l2_dev; 1125 vfd->v4l2_dev = &dev->v4l2_dev;
1140 vfd->queue = &dev->vb_vid_cap_q; 1126 vfd->queue = &dev->vb_vid_cap_q;
@@ -1160,6 +1146,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
1160 vfd->vfl_dir = VFL_DIR_TX; 1146 vfd->vfl_dir = VFL_DIR_TX;
1161 vfd->fops = &vivid_fops; 1147 vfd->fops = &vivid_fops;
1162 vfd->ioctl_ops = &vivid_ioctl_ops; 1148 vfd->ioctl_ops = &vivid_ioctl_ops;
1149 vfd->device_caps = dev->vid_out_caps;
1163 vfd->release = video_device_release_empty; 1150 vfd->release = video_device_release_empty;
1164 vfd->v4l2_dev = &dev->v4l2_dev; 1151 vfd->v4l2_dev = &dev->v4l2_dev;
1165 vfd->queue = &dev->vb_vid_out_q; 1152 vfd->queue = &dev->vb_vid_out_q;
@@ -1184,6 +1171,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
1184 strlcpy(vfd->name, "vivid-vbi-cap", sizeof(vfd->name)); 1171 strlcpy(vfd->name, "vivid-vbi-cap", sizeof(vfd->name));
1185 vfd->fops = &vivid_fops; 1172 vfd->fops = &vivid_fops;
1186 vfd->ioctl_ops = &vivid_ioctl_ops; 1173 vfd->ioctl_ops = &vivid_ioctl_ops;
1174 vfd->device_caps = dev->vbi_cap_caps;
1187 vfd->release = video_device_release_empty; 1175 vfd->release = video_device_release_empty;
1188 vfd->v4l2_dev = &dev->v4l2_dev; 1176 vfd->v4l2_dev = &dev->v4l2_dev;
1189 vfd->queue = &dev->vb_vbi_cap_q; 1177 vfd->queue = &dev->vb_vbi_cap_q;
@@ -1207,6 +1195,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
1207 vfd->vfl_dir = VFL_DIR_TX; 1195 vfd->vfl_dir = VFL_DIR_TX;
1208 vfd->fops = &vivid_fops; 1196 vfd->fops = &vivid_fops;
1209 vfd->ioctl_ops = &vivid_ioctl_ops; 1197 vfd->ioctl_ops = &vivid_ioctl_ops;
1198 vfd->device_caps = dev->vbi_out_caps;
1210 vfd->release = video_device_release_empty; 1199 vfd->release = video_device_release_empty;
1211 vfd->v4l2_dev = &dev->v4l2_dev; 1200 vfd->v4l2_dev = &dev->v4l2_dev;
1212 vfd->queue = &dev->vb_vbi_out_q; 1201 vfd->queue = &dev->vb_vbi_out_q;
@@ -1229,6 +1218,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
1229 strlcpy(vfd->name, "vivid-sdr-cap", sizeof(vfd->name)); 1218 strlcpy(vfd->name, "vivid-sdr-cap", sizeof(vfd->name));
1230 vfd->fops = &vivid_fops; 1219 vfd->fops = &vivid_fops;
1231 vfd->ioctl_ops = &vivid_ioctl_ops; 1220 vfd->ioctl_ops = &vivid_ioctl_ops;
1221 vfd->device_caps = dev->sdr_cap_caps;
1232 vfd->release = video_device_release_empty; 1222 vfd->release = video_device_release_empty;
1233 vfd->v4l2_dev = &dev->v4l2_dev; 1223 vfd->v4l2_dev = &dev->v4l2_dev;
1234 vfd->queue = &dev->vb_sdr_cap_q; 1224 vfd->queue = &dev->vb_sdr_cap_q;
@@ -1247,6 +1237,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
1247 strlcpy(vfd->name, "vivid-rad-rx", sizeof(vfd->name)); 1237 strlcpy(vfd->name, "vivid-rad-rx", sizeof(vfd->name));
1248 vfd->fops = &vivid_radio_fops; 1238 vfd->fops = &vivid_radio_fops;
1249 vfd->ioctl_ops = &vivid_ioctl_ops; 1239 vfd->ioctl_ops = &vivid_ioctl_ops;
1240 vfd->device_caps = dev->radio_rx_caps;
1250 vfd->release = video_device_release_empty; 1241 vfd->release = video_device_release_empty;
1251 vfd->v4l2_dev = &dev->v4l2_dev; 1242 vfd->v4l2_dev = &dev->v4l2_dev;
1252 vfd->lock = &dev->mutex; 1243 vfd->lock = &dev->mutex;
@@ -1265,6 +1256,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
1265 vfd->vfl_dir = VFL_DIR_TX; 1256 vfd->vfl_dir = VFL_DIR_TX;
1266 vfd->fops = &vivid_radio_fops; 1257 vfd->fops = &vivid_radio_fops;
1267 vfd->ioctl_ops = &vivid_ioctl_ops; 1258 vfd->ioctl_ops = &vivid_ioctl_ops;
1259 vfd->device_caps = dev->radio_tx_caps;
1268 vfd->release = video_device_release_empty; 1260 vfd->release = video_device_release_empty;
1269 vfd->v4l2_dev = &dev->v4l2_dev; 1261 vfd->v4l2_dev = &dev->v4l2_dev;
1270 vfd->lock = &dev->mutex; 1262 vfd->lock = &dev->mutex;
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 751c1ba391e9..776783bec227 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -25,7 +25,7 @@
25#include <media/v4l2-device.h> 25#include <media/v4l2-device.h>
26#include <media/v4l2-dev.h> 26#include <media/v4l2-dev.h>
27#include <media/v4l2-ctrls.h> 27#include <media/v4l2-ctrls.h>
28#include "vivid-tpg.h" 28#include <media/v4l2-tpg.h>
29#include "vivid-rds-gen.h" 29#include "vivid-rds-gen.h"
30#include "vivid-vbi-gen.h" 30#include "vivid-vbi-gen.h"
31 31
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 9034281944a4..3b8c10108dfa 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -36,6 +36,7 @@
36#include <media/v4l2-ioctl.h> 36#include <media/v4l2-ioctl.h>
37#include <media/v4l2-fh.h> 37#include <media/v4l2-fh.h>
38#include <media/v4l2-event.h> 38#include <media/v4l2-event.h>
39#include <media/v4l2-rect.h>
39 40
40#include "vivid-core.h" 41#include "vivid-core.h"
41#include "vivid-vid-common.h" 42#include "vivid-vid-common.h"
@@ -184,15 +185,15 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev)
184 dev->compose_out.width, dev->compose_out.height 185 dev->compose_out.width, dev->compose_out.height
185 }; 186 };
186 187
187 dev->loop_vid_copy = rect_intersect(&dev->crop_cap, &dev->compose_out); 188 v4l2_rect_intersect(&dev->loop_vid_copy, &dev->crop_cap, &dev->compose_out);
188 189
189 dev->loop_vid_out = dev->loop_vid_copy; 190 dev->loop_vid_out = dev->loop_vid_copy;
190 rect_scale(&dev->loop_vid_out, &dev->compose_out, &dev->crop_out); 191 v4l2_rect_scale(&dev->loop_vid_out, &dev->compose_out, &dev->crop_out);
191 dev->loop_vid_out.left += dev->crop_out.left; 192 dev->loop_vid_out.left += dev->crop_out.left;
192 dev->loop_vid_out.top += dev->crop_out.top; 193 dev->loop_vid_out.top += dev->crop_out.top;
193 194
194 dev->loop_vid_cap = dev->loop_vid_copy; 195 dev->loop_vid_cap = dev->loop_vid_copy;
195 rect_scale(&dev->loop_vid_cap, &dev->crop_cap, &dev->compose_cap); 196 v4l2_rect_scale(&dev->loop_vid_cap, &dev->crop_cap, &dev->compose_cap);
196 197
197 dprintk(dev, 1, 198 dprintk(dev, 1,
198 "loop_vid_copy: %dx%d@%dx%d loop_vid_out: %dx%d@%dx%d loop_vid_cap: %dx%d@%dx%d\n", 199 "loop_vid_copy: %dx%d@%dx%d loop_vid_out: %dx%d@%dx%d loop_vid_cap: %dx%d@%dx%d\n",
@@ -203,13 +204,13 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev)
203 dev->loop_vid_cap.width, dev->loop_vid_cap.height, 204 dev->loop_vid_cap.width, dev->loop_vid_cap.height,
204 dev->loop_vid_cap.left, dev->loop_vid_cap.top); 205 dev->loop_vid_cap.left, dev->loop_vid_cap.top);
205 206
206 r_overlay = rect_intersect(&r_fb, &r_overlay); 207 v4l2_rect_intersect(&r_overlay, &r_fb, &r_overlay);
207 208
208 /* shift r_overlay to the same origin as compose_out */ 209 /* shift r_overlay to the same origin as compose_out */
209 r_overlay.left += dev->compose_out.left - dev->overlay_out_left; 210 r_overlay.left += dev->compose_out.left - dev->overlay_out_left;
210 r_overlay.top += dev->compose_out.top - dev->overlay_out_top; 211 r_overlay.top += dev->compose_out.top - dev->overlay_out_top;
211 212
212 dev->loop_vid_overlay = rect_intersect(&r_overlay, &dev->loop_vid_copy); 213 v4l2_rect_intersect(&dev->loop_vid_overlay, &r_overlay, &dev->loop_vid_copy);
213 dev->loop_fb_copy = dev->loop_vid_overlay; 214 dev->loop_fb_copy = dev->loop_vid_overlay;
214 215
215 /* shift dev->loop_fb_copy back again to the fb origin */ 216 /* shift dev->loop_fb_copy back again to the fb origin */
@@ -217,7 +218,7 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev)
217 dev->loop_fb_copy.top -= dev->compose_out.top - dev->overlay_out_top; 218 dev->loop_fb_copy.top -= dev->compose_out.top - dev->overlay_out_top;
218 219
219 dev->loop_vid_overlay_cap = dev->loop_vid_overlay; 220 dev->loop_vid_overlay_cap = dev->loop_vid_overlay;
220 rect_scale(&dev->loop_vid_overlay_cap, &dev->crop_cap, &dev->compose_cap); 221 v4l2_rect_scale(&dev->loop_vid_overlay_cap, &dev->crop_cap, &dev->compose_cap);
221 222
222 dprintk(dev, 1, 223 dprintk(dev, 1,
223 "loop_fb_copy: %dx%d@%dx%d loop_vid_overlay: %dx%d@%dx%d loop_vid_overlay_cap: %dx%d@%dx%d\n", 224 "loop_fb_copy: %dx%d@%dx%d loop_vid_overlay: %dx%d@%dx%d loop_vid_overlay_cap: %dx%d@%dx%d\n",
diff --git a/drivers/media/platform/vivid/vivid-rds-gen.c b/drivers/media/platform/vivid/vivid-rds-gen.c
index c382343fdb66..53c7777dc001 100644
--- a/drivers/media/platform/vivid/vivid-rds-gen.c
+++ b/drivers/media/platform/vivid/vivid-rds-gen.c
@@ -55,6 +55,7 @@ void vivid_rds_generate(struct vivid_rds_gen *rds)
55{ 55{
56 struct v4l2_rds_data *data = rds->data; 56 struct v4l2_rds_data *data = rds->data;
57 unsigned grp; 57 unsigned grp;
58 unsigned idx;
58 struct tm tm; 59 struct tm tm;
59 unsigned date; 60 unsigned date;
60 unsigned time; 61 unsigned time;
@@ -73,24 +74,26 @@ void vivid_rds_generate(struct vivid_rds_gen *rds)
73 case 0 ... 3: 74 case 0 ... 3:
74 case 22 ... 25: 75 case 22 ... 25:
75 case 44 ... 47: /* Group 0B */ 76 case 44 ... 47: /* Group 0B */
77 idx = (grp % 22) % 4;
76 data[1].lsb |= (rds->ta << 4) | (rds->ms << 3); 78 data[1].lsb |= (rds->ta << 4) | (rds->ms << 3);
77 data[1].lsb |= vivid_get_di(rds, grp % 22); 79 data[1].lsb |= vivid_get_di(rds, idx);
78 data[1].msb |= 1 << 3; 80 data[1].msb |= 1 << 3;
79 data[2].lsb = rds->picode & 0xff; 81 data[2].lsb = rds->picode & 0xff;
80 data[2].msb = rds->picode >> 8; 82 data[2].msb = rds->picode >> 8;
81 data[2].block = V4L2_RDS_BLOCK_C_ALT | (V4L2_RDS_BLOCK_C_ALT << 3); 83 data[2].block = V4L2_RDS_BLOCK_C_ALT | (V4L2_RDS_BLOCK_C_ALT << 3);
82 data[3].lsb = rds->psname[2 * (grp % 22) + 1]; 84 data[3].lsb = rds->psname[2 * idx + 1];
83 data[3].msb = rds->psname[2 * (grp % 22)]; 85 data[3].msb = rds->psname[2 * idx];
84 break; 86 break;
85 case 4 ... 19: 87 case 4 ... 19:
86 case 26 ... 41: /* Group 2A */ 88 case 26 ... 41: /* Group 2A */
87 data[1].lsb |= (grp - 4) % 22; 89 idx = ((grp - 4) % 22) % 16;
90 data[1].lsb |= idx;
88 data[1].msb |= 4 << 3; 91 data[1].msb |= 4 << 3;
89 data[2].msb = rds->radiotext[4 * ((grp - 4) % 22)]; 92 data[2].msb = rds->radiotext[4 * idx];
90 data[2].lsb = rds->radiotext[4 * ((grp - 4) % 22) + 1]; 93 data[2].lsb = rds->radiotext[4 * idx + 1];
91 data[2].block = V4L2_RDS_BLOCK_C | (V4L2_RDS_BLOCK_C << 3); 94 data[2].block = V4L2_RDS_BLOCK_C | (V4L2_RDS_BLOCK_C << 3);
92 data[3].msb = rds->radiotext[4 * ((grp - 4) % 22) + 2]; 95 data[3].msb = rds->radiotext[4 * idx + 2];
93 data[3].lsb = rds->radiotext[4 * ((grp - 4) % 22) + 3]; 96 data[3].lsb = rds->radiotext[4 * idx + 3];
94 break; 97 break;
95 case 56: 98 case 56:
96 /* 99 /*
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index b84f081c1b92..4f730f355a17 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -26,6 +26,7 @@
26#include <media/v4l2-common.h> 26#include <media/v4l2-common.h>
27#include <media/v4l2-event.h> 27#include <media/v4l2-event.h>
28#include <media/v4l2-dv-timings.h> 28#include <media/v4l2-dv-timings.h>
29#include <media/v4l2-rect.h>
29 30
30#include "vivid-core.h" 31#include "vivid-core.h"
31#include "vivid-vid-common.h" 32#include "vivid-vid-common.h"
@@ -590,16 +591,16 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
590 } else { 591 } else {
591 struct v4l2_rect r = { 0, 0, mp->width, mp->height * factor }; 592 struct v4l2_rect r = { 0, 0, mp->width, mp->height * factor };
592 593
593 rect_set_min_size(&r, &vivid_min_rect); 594 v4l2_rect_set_min_size(&r, &vivid_min_rect);
594 rect_set_max_size(&r, &vivid_max_rect); 595 v4l2_rect_set_max_size(&r, &vivid_max_rect);
595 if (dev->has_scaler_cap && !dev->has_compose_cap) { 596 if (dev->has_scaler_cap && !dev->has_compose_cap) {
596 struct v4l2_rect max_r = { 0, 0, MAX_ZOOM * w, MAX_ZOOM * h }; 597 struct v4l2_rect max_r = { 0, 0, MAX_ZOOM * w, MAX_ZOOM * h };
597 598
598 rect_set_max_size(&r, &max_r); 599 v4l2_rect_set_max_size(&r, &max_r);
599 } else if (!dev->has_scaler_cap && dev->has_crop_cap && !dev->has_compose_cap) { 600 } else if (!dev->has_scaler_cap && dev->has_crop_cap && !dev->has_compose_cap) {
600 rect_set_max_size(&r, &dev->src_rect); 601 v4l2_rect_set_max_size(&r, &dev->src_rect);
601 } else if (!dev->has_scaler_cap && !dev->has_crop_cap) { 602 } else if (!dev->has_scaler_cap && !dev->has_crop_cap) {
602 rect_set_min_size(&r, &dev->src_rect); 603 v4l2_rect_set_min_size(&r, &dev->src_rect);
603 } 604 }
604 mp->width = r.width; 605 mp->width = r.width;
605 mp->height = r.height / factor; 606 mp->height = r.height / factor;
@@ -668,7 +669,7 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
668 669
669 if (dev->has_scaler_cap) { 670 if (dev->has_scaler_cap) {
670 if (dev->has_compose_cap) 671 if (dev->has_compose_cap)
671 rect_map_inside(compose, &r); 672 v4l2_rect_map_inside(compose, &r);
672 else 673 else
673 *compose = r; 674 *compose = r;
674 if (dev->has_crop_cap && !dev->has_compose_cap) { 675 if (dev->has_crop_cap && !dev->has_compose_cap) {
@@ -683,9 +684,9 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
683 factor * r.height * MAX_ZOOM 684 factor * r.height * MAX_ZOOM
684 }; 685 };
685 686
686 rect_set_min_size(crop, &min_r); 687 v4l2_rect_set_min_size(crop, &min_r);
687 rect_set_max_size(crop, &max_r); 688 v4l2_rect_set_max_size(crop, &max_r);
688 rect_map_inside(crop, &dev->crop_bounds_cap); 689 v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
689 } else if (dev->has_crop_cap) { 690 } else if (dev->has_crop_cap) {
690 struct v4l2_rect min_r = { 691 struct v4l2_rect min_r = {
691 0, 0, 692 0, 0,
@@ -698,27 +699,27 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
698 factor * compose->height * MAX_ZOOM 699 factor * compose->height * MAX_ZOOM
699 }; 700 };
700 701
701 rect_set_min_size(crop, &min_r); 702 v4l2_rect_set_min_size(crop, &min_r);
702 rect_set_max_size(crop, &max_r); 703 v4l2_rect_set_max_size(crop, &max_r);
703 rect_map_inside(crop, &dev->crop_bounds_cap); 704 v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
704 } 705 }
705 } else if (dev->has_crop_cap && !dev->has_compose_cap) { 706 } else if (dev->has_crop_cap && !dev->has_compose_cap) {
706 r.height *= factor; 707 r.height *= factor;
707 rect_set_size_to(crop, &r); 708 v4l2_rect_set_size_to(crop, &r);
708 rect_map_inside(crop, &dev->crop_bounds_cap); 709 v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
709 r = *crop; 710 r = *crop;
710 r.height /= factor; 711 r.height /= factor;
711 rect_set_size_to(compose, &r); 712 v4l2_rect_set_size_to(compose, &r);
712 } else if (!dev->has_crop_cap) { 713 } else if (!dev->has_crop_cap) {
713 rect_map_inside(compose, &r); 714 v4l2_rect_map_inside(compose, &r);
714 } else { 715 } else {
715 r.height *= factor; 716 r.height *= factor;
716 rect_set_max_size(crop, &r); 717 v4l2_rect_set_max_size(crop, &r);
717 rect_map_inside(crop, &dev->crop_bounds_cap); 718 v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
718 compose->top *= factor; 719 compose->top *= factor;
719 compose->height *= factor; 720 compose->height *= factor;
720 rect_set_size_to(compose, crop); 721 v4l2_rect_set_size_to(compose, crop);
721 rect_map_inside(compose, &r); 722 v4l2_rect_map_inside(compose, &r);
722 compose->top /= factor; 723 compose->top /= factor;
723 compose->height /= factor; 724 compose->height /= factor;
724 } 725 }
@@ -735,9 +736,9 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
735 } else { 736 } else {
736 struct v4l2_rect r = { 0, 0, mp->width, mp->height }; 737 struct v4l2_rect r = { 0, 0, mp->width, mp->height };
737 738
738 rect_set_size_to(compose, &r); 739 v4l2_rect_set_size_to(compose, &r);
739 r.height *= factor; 740 r.height *= factor;
740 rect_set_size_to(crop, &r); 741 v4l2_rect_set_size_to(crop, &r);
741 } 742 }
742 743
743 dev->fmt_cap_rect.width = mp->width; 744 dev->fmt_cap_rect.width = mp->width;
@@ -886,9 +887,9 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
886 ret = vivid_vid_adjust_sel(s->flags, &s->r); 887 ret = vivid_vid_adjust_sel(s->flags, &s->r);
887 if (ret) 888 if (ret)
888 return ret; 889 return ret;
889 rect_set_min_size(&s->r, &vivid_min_rect); 890 v4l2_rect_set_min_size(&s->r, &vivid_min_rect);
890 rect_set_max_size(&s->r, &dev->src_rect); 891 v4l2_rect_set_max_size(&s->r, &dev->src_rect);
891 rect_map_inside(&s->r, &dev->crop_bounds_cap); 892 v4l2_rect_map_inside(&s->r, &dev->crop_bounds_cap);
892 s->r.top /= factor; 893 s->r.top /= factor;
893 s->r.height /= factor; 894 s->r.height /= factor;
894 if (dev->has_scaler_cap) { 895 if (dev->has_scaler_cap) {
@@ -904,36 +905,36 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
904 s->r.height / MAX_ZOOM 905 s->r.height / MAX_ZOOM
905 }; 906 };
906 907
907 rect_set_min_size(&fmt, &min_rect); 908 v4l2_rect_set_min_size(&fmt, &min_rect);
908 if (!dev->has_compose_cap) 909 if (!dev->has_compose_cap)
909 rect_set_max_size(&fmt, &max_rect); 910 v4l2_rect_set_max_size(&fmt, &max_rect);
910 if (!rect_same_size(&dev->fmt_cap_rect, &fmt) && 911 if (!v4l2_rect_same_size(&dev->fmt_cap_rect, &fmt) &&
911 vb2_is_busy(&dev->vb_vid_cap_q)) 912 vb2_is_busy(&dev->vb_vid_cap_q))
912 return -EBUSY; 913 return -EBUSY;
913 if (dev->has_compose_cap) { 914 if (dev->has_compose_cap) {
914 rect_set_min_size(compose, &min_rect); 915 v4l2_rect_set_min_size(compose, &min_rect);
915 rect_set_max_size(compose, &max_rect); 916 v4l2_rect_set_max_size(compose, &max_rect);
916 } 917 }
917 dev->fmt_cap_rect = fmt; 918 dev->fmt_cap_rect = fmt;
918 tpg_s_buf_height(&dev->tpg, fmt.height); 919 tpg_s_buf_height(&dev->tpg, fmt.height);
919 } else if (dev->has_compose_cap) { 920 } else if (dev->has_compose_cap) {
920 struct v4l2_rect fmt = dev->fmt_cap_rect; 921 struct v4l2_rect fmt = dev->fmt_cap_rect;
921 922
922 rect_set_min_size(&fmt, &s->r); 923 v4l2_rect_set_min_size(&fmt, &s->r);
923 if (!rect_same_size(&dev->fmt_cap_rect, &fmt) && 924 if (!v4l2_rect_same_size(&dev->fmt_cap_rect, &fmt) &&
924 vb2_is_busy(&dev->vb_vid_cap_q)) 925 vb2_is_busy(&dev->vb_vid_cap_q))
925 return -EBUSY; 926 return -EBUSY;
926 dev->fmt_cap_rect = fmt; 927 dev->fmt_cap_rect = fmt;
927 tpg_s_buf_height(&dev->tpg, fmt.height); 928 tpg_s_buf_height(&dev->tpg, fmt.height);
928 rect_set_size_to(compose, &s->r); 929 v4l2_rect_set_size_to(compose, &s->r);
929 rect_map_inside(compose, &dev->fmt_cap_rect); 930 v4l2_rect_map_inside(compose, &dev->fmt_cap_rect);
930 } else { 931 } else {
931 if (!rect_same_size(&s->r, &dev->fmt_cap_rect) && 932 if (!v4l2_rect_same_size(&s->r, &dev->fmt_cap_rect) &&
932 vb2_is_busy(&dev->vb_vid_cap_q)) 933 vb2_is_busy(&dev->vb_vid_cap_q))
933 return -EBUSY; 934 return -EBUSY;
934 rect_set_size_to(&dev->fmt_cap_rect, &s->r); 935 v4l2_rect_set_size_to(&dev->fmt_cap_rect, &s->r);
935 rect_set_size_to(compose, &s->r); 936 v4l2_rect_set_size_to(compose, &s->r);
936 rect_map_inside(compose, &dev->fmt_cap_rect); 937 v4l2_rect_map_inside(compose, &dev->fmt_cap_rect);
937 tpg_s_buf_height(&dev->tpg, dev->fmt_cap_rect.height); 938 tpg_s_buf_height(&dev->tpg, dev->fmt_cap_rect.height);
938 } 939 }
939 s->r.top *= factor; 940 s->r.top *= factor;
@@ -946,8 +947,8 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
946 ret = vivid_vid_adjust_sel(s->flags, &s->r); 947 ret = vivid_vid_adjust_sel(s->flags, &s->r);
947 if (ret) 948 if (ret)
948 return ret; 949 return ret;
949 rect_set_min_size(&s->r, &vivid_min_rect); 950 v4l2_rect_set_min_size(&s->r, &vivid_min_rect);
950 rect_set_max_size(&s->r, &dev->fmt_cap_rect); 951 v4l2_rect_set_max_size(&s->r, &dev->fmt_cap_rect);
951 if (dev->has_scaler_cap) { 952 if (dev->has_scaler_cap) {
952 struct v4l2_rect max_rect = { 953 struct v4l2_rect max_rect = {
953 0, 0, 954 0, 0,
@@ -955,7 +956,7 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
955 (dev->src_rect.height / factor) * MAX_ZOOM 956 (dev->src_rect.height / factor) * MAX_ZOOM
956 }; 957 };
957 958
958 rect_set_max_size(&s->r, &max_rect); 959 v4l2_rect_set_max_size(&s->r, &max_rect);
959 if (dev->has_crop_cap) { 960 if (dev->has_crop_cap) {
960 struct v4l2_rect min_rect = { 961 struct v4l2_rect min_rect = {
961 0, 0, 962 0, 0,
@@ -968,23 +969,23 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
968 (s->r.height * factor) * MAX_ZOOM 969 (s->r.height * factor) * MAX_ZOOM
969 }; 970 };
970 971
971 rect_set_min_size(crop, &min_rect); 972 v4l2_rect_set_min_size(crop, &min_rect);
972 rect_set_max_size(crop, &max_rect); 973 v4l2_rect_set_max_size(crop, &max_rect);
973 rect_map_inside(crop, &dev->crop_bounds_cap); 974 v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
974 } 975 }
975 } else if (dev->has_crop_cap) { 976 } else if (dev->has_crop_cap) {
976 s->r.top *= factor; 977 s->r.top *= factor;
977 s->r.height *= factor; 978 s->r.height *= factor;
978 rect_set_max_size(&s->r, &dev->src_rect); 979 v4l2_rect_set_max_size(&s->r, &dev->src_rect);
979 rect_set_size_to(crop, &s->r); 980 v4l2_rect_set_size_to(crop, &s->r);
980 rect_map_inside(crop, &dev->crop_bounds_cap); 981 v4l2_rect_map_inside(crop, &dev->crop_bounds_cap);
981 s->r.top /= factor; 982 s->r.top /= factor;
982 s->r.height /= factor; 983 s->r.height /= factor;
983 } else { 984 } else {
984 rect_set_size_to(&s->r, &dev->src_rect); 985 v4l2_rect_set_size_to(&s->r, &dev->src_rect);
985 s->r.height /= factor; 986 s->r.height /= factor;
986 } 987 }
987 rect_map_inside(&s->r, &dev->fmt_cap_rect); 988 v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect);
988 if (dev->bitmap_cap && (compose->width != s->r.width || 989 if (dev->bitmap_cap && (compose->width != s->r.width ||
989 compose->height != s->r.height)) { 990 compose->height != s->r.height)) {
990 kfree(dev->bitmap_cap); 991 kfree(dev->bitmap_cap);
@@ -1124,7 +1125,7 @@ int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
1124 for (j = i + 1; j < win->clipcount; j++) { 1125 for (j = i + 1; j < win->clipcount; j++) {
1125 struct v4l2_rect *r2 = &dev->try_clips_cap[j].c; 1126 struct v4l2_rect *r2 = &dev->try_clips_cap[j].c;
1126 1127
1127 if (rect_overlap(r1, r2)) 1128 if (v4l2_rect_overlap(r1, r2))
1128 return -EINVAL; 1129 return -EINVAL;
1129 } 1130 }
1130 } 1131 }
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index b0d4e3a0acf0..39ea2284789c 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -653,103 +653,6 @@ int fmt_sp2mp_func(struct file *file, void *priv,
653 return ret; 653 return ret;
654} 654}
655 655
656/* v4l2_rect helper function: copy the width/height values */
657void rect_set_size_to(struct v4l2_rect *r, const struct v4l2_rect *size)
658{
659 r->width = size->width;
660 r->height = size->height;
661}
662
663/* v4l2_rect helper function: width and height of r should be >= min_size */
664void rect_set_min_size(struct v4l2_rect *r, const struct v4l2_rect *min_size)
665{
666 if (r->width < min_size->width)
667 r->width = min_size->width;
668 if (r->height < min_size->height)
669 r->height = min_size->height;
670}
671
672/* v4l2_rect helper function: width and height of r should be <= max_size */
673void rect_set_max_size(struct v4l2_rect *r, const struct v4l2_rect *max_size)
674{
675 if (r->width > max_size->width)
676 r->width = max_size->width;
677 if (r->height > max_size->height)
678 r->height = max_size->height;
679}
680
681/* v4l2_rect helper function: r should be inside boundary */
682void rect_map_inside(struct v4l2_rect *r, const struct v4l2_rect *boundary)
683{
684 rect_set_max_size(r, boundary);
685 if (r->left < boundary->left)
686 r->left = boundary->left;
687 if (r->top < boundary->top)
688 r->top = boundary->top;
689 if (r->left + r->width > boundary->width)
690 r->left = boundary->width - r->width;
691 if (r->top + r->height > boundary->height)
692 r->top = boundary->height - r->height;
693}
694
695/* v4l2_rect helper function: return true if r1 has the same size as r2 */
696bool rect_same_size(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
697{
698 return r1->width == r2->width && r1->height == r2->height;
699}
700
701/* v4l2_rect helper function: calculate the intersection of two rects */
702struct v4l2_rect rect_intersect(const struct v4l2_rect *a, const struct v4l2_rect *b)
703{
704 struct v4l2_rect r;
705 int right, bottom;
706
707 r.top = max(a->top, b->top);
708 r.left = max(a->left, b->left);
709 bottom = min(a->top + a->height, b->top + b->height);
710 right = min(a->left + a->width, b->left + b->width);
711 r.height = max(0, bottom - r.top);
712 r.width = max(0, right - r.left);
713 return r;
714}
715
716/*
717 * v4l2_rect helper function: scale rect r by to->width / from->width and
718 * to->height / from->height.
719 */
720void rect_scale(struct v4l2_rect *r, const struct v4l2_rect *from,
721 const struct v4l2_rect *to)
722{
723 if (from->width == 0 || from->height == 0) {
724 r->left = r->top = r->width = r->height = 0;
725 return;
726 }
727 r->left = (((r->left - from->left) * to->width) / from->width) & ~1;
728 r->width = ((r->width * to->width) / from->width) & ~1;
729 r->top = ((r->top - from->top) * to->height) / from->height;
730 r->height = (r->height * to->height) / from->height;
731}
732
733bool rect_overlap(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
734{
735 /*
736 * IF the left side of r1 is to the right of the right side of r2 OR
737 * the left side of r2 is to the right of the right side of r1 THEN
738 * they do not overlap.
739 */
740 if (r1->left >= r2->left + r2->width ||
741 r2->left >= r1->left + r1->width)
742 return false;
743 /*
744 * IF the top side of r1 is below the bottom of r2 OR
745 * the top side of r2 is below the bottom of r1 THEN
746 * they do not overlap.
747 */
748 if (r1->top >= r2->top + r2->height ||
749 r2->top >= r1->top + r1->height)
750 return false;
751 return true;
752}
753int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r) 656int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
754{ 657{
755 unsigned w = r->width; 658 unsigned w = r->width;
diff --git a/drivers/media/platform/vivid/vivid-vid-common.h b/drivers/media/platform/vivid/vivid-vid-common.h
index 3ec4fa85c9b9..4b6175eab8a2 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.h
+++ b/drivers/media/platform/vivid/vivid-vid-common.h
@@ -37,15 +37,6 @@ const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
37bool vivid_vid_can_loop(struct vivid_dev *dev); 37bool vivid_vid_can_loop(struct vivid_dev *dev);
38void vivid_send_source_change(struct vivid_dev *dev, unsigned type); 38void vivid_send_source_change(struct vivid_dev *dev, unsigned type);
39 39
40bool rect_overlap(const struct v4l2_rect *r1, const struct v4l2_rect *r2);
41void rect_set_size_to(struct v4l2_rect *r, const struct v4l2_rect *size);
42void rect_set_min_size(struct v4l2_rect *r, const struct v4l2_rect *min_size);
43void rect_set_max_size(struct v4l2_rect *r, const struct v4l2_rect *max_size);
44void rect_map_inside(struct v4l2_rect *r, const struct v4l2_rect *boundary);
45bool rect_same_size(const struct v4l2_rect *r1, const struct v4l2_rect *r2);
46struct v4l2_rect rect_intersect(const struct v4l2_rect *a, const struct v4l2_rect *b);
47void rect_scale(struct v4l2_rect *r, const struct v4l2_rect *from,
48 const struct v4l2_rect *to);
49int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r); 40int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r);
50 41
51int vivid_enum_fmt_vid(struct file *file, void *priv, struct v4l2_fmtdesc *f); 42int vivid_enum_fmt_vid(struct file *file, void *priv, struct v4l2_fmtdesc *f);
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index 64e4d66482c1..f92f4496d527 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -25,6 +25,7 @@
25#include <media/v4l2-common.h> 25#include <media/v4l2-common.h>
26#include <media/v4l2-event.h> 26#include <media/v4l2-event.h>
27#include <media/v4l2-dv-timings.h> 27#include <media/v4l2-dv-timings.h>
28#include <media/v4l2-rect.h>
28 29
29#include "vivid-core.h" 30#include "vivid-core.h"
30#include "vivid-vid-common.h" 31#include "vivid-vid-common.h"
@@ -376,16 +377,16 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
376 } else { 377 } else {
377 struct v4l2_rect r = { 0, 0, mp->width, mp->height * factor }; 378 struct v4l2_rect r = { 0, 0, mp->width, mp->height * factor };
378 379
379 rect_set_min_size(&r, &vivid_min_rect); 380 v4l2_rect_set_min_size(&r, &vivid_min_rect);
380 rect_set_max_size(&r, &vivid_max_rect); 381 v4l2_rect_set_max_size(&r, &vivid_max_rect);
381 if (dev->has_scaler_out && !dev->has_crop_out) { 382 if (dev->has_scaler_out && !dev->has_crop_out) {
382 struct v4l2_rect max_r = { 0, 0, MAX_ZOOM * w, MAX_ZOOM * h }; 383 struct v4l2_rect max_r = { 0, 0, MAX_ZOOM * w, MAX_ZOOM * h };
383 384
384 rect_set_max_size(&r, &max_r); 385 v4l2_rect_set_max_size(&r, &max_r);
385 } else if (!dev->has_scaler_out && dev->has_compose_out && !dev->has_crop_out) { 386 } else if (!dev->has_scaler_out && dev->has_compose_out && !dev->has_crop_out) {
386 rect_set_max_size(&r, &dev->sink_rect); 387 v4l2_rect_set_max_size(&r, &dev->sink_rect);
387 } else if (!dev->has_scaler_out && !dev->has_compose_out) { 388 } else if (!dev->has_scaler_out && !dev->has_compose_out) {
388 rect_set_min_size(&r, &dev->sink_rect); 389 v4l2_rect_set_min_size(&r, &dev->sink_rect);
389 } 390 }
390 mp->width = r.width; 391 mp->width = r.width;
391 mp->height = r.height / factor; 392 mp->height = r.height / factor;
@@ -473,7 +474,7 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv,
473 474
474 if (dev->has_scaler_out) { 475 if (dev->has_scaler_out) {
475 if (dev->has_crop_out) 476 if (dev->has_crop_out)
476 rect_map_inside(crop, &r); 477 v4l2_rect_map_inside(crop, &r);
477 else 478 else
478 *crop = r; 479 *crop = r;
479 if (dev->has_compose_out && !dev->has_crop_out) { 480 if (dev->has_compose_out && !dev->has_crop_out) {
@@ -488,9 +489,9 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv,
488 factor * r.height * MAX_ZOOM 489 factor * r.height * MAX_ZOOM
489 }; 490 };
490 491
491 rect_set_min_size(compose, &min_r); 492 v4l2_rect_set_min_size(compose, &min_r);
492 rect_set_max_size(compose, &max_r); 493 v4l2_rect_set_max_size(compose, &max_r);
493 rect_map_inside(compose, &dev->compose_bounds_out); 494 v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
494 } else if (dev->has_compose_out) { 495 } else if (dev->has_compose_out) {
495 struct v4l2_rect min_r = { 496 struct v4l2_rect min_r = {
496 0, 0, 497 0, 0,
@@ -503,36 +504,36 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv,
503 factor * crop->height * MAX_ZOOM 504 factor * crop->height * MAX_ZOOM
504 }; 505 };
505 506
506 rect_set_min_size(compose, &min_r); 507 v4l2_rect_set_min_size(compose, &min_r);
507 rect_set_max_size(compose, &max_r); 508 v4l2_rect_set_max_size(compose, &max_r);
508 rect_map_inside(compose, &dev->compose_bounds_out); 509 v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
509 } 510 }
510 } else if (dev->has_compose_out && !dev->has_crop_out) { 511 } else if (dev->has_compose_out && !dev->has_crop_out) {
511 rect_set_size_to(crop, &r); 512 v4l2_rect_set_size_to(crop, &r);
512 r.height *= factor; 513 r.height *= factor;
513 rect_set_size_to(compose, &r); 514 v4l2_rect_set_size_to(compose, &r);
514 rect_map_inside(compose, &dev->compose_bounds_out); 515 v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
515 } else if (!dev->has_compose_out) { 516 } else if (!dev->has_compose_out) {
516 rect_map_inside(crop, &r); 517 v4l2_rect_map_inside(crop, &r);
517 r.height /= factor; 518 r.height /= factor;
518 rect_set_size_to(compose, &r); 519 v4l2_rect_set_size_to(compose, &r);
519 } else { 520 } else {
520 r.height *= factor; 521 r.height *= factor;
521 rect_set_max_size(compose, &r); 522 v4l2_rect_set_max_size(compose, &r);
522 rect_map_inside(compose, &dev->compose_bounds_out); 523 v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
523 crop->top *= factor; 524 crop->top *= factor;
524 crop->height *= factor; 525 crop->height *= factor;
525 rect_set_size_to(crop, compose); 526 v4l2_rect_set_size_to(crop, compose);
526 rect_map_inside(crop, &r); 527 v4l2_rect_map_inside(crop, &r);
527 crop->top /= factor; 528 crop->top /= factor;
528 crop->height /= factor; 529 crop->height /= factor;
529 } 530 }
530 } else { 531 } else {
531 struct v4l2_rect r = { 0, 0, mp->width, mp->height }; 532 struct v4l2_rect r = { 0, 0, mp->width, mp->height };
532 533
533 rect_set_size_to(crop, &r); 534 v4l2_rect_set_size_to(crop, &r);
534 r.height /= factor; 535 r.height /= factor;
535 rect_set_size_to(compose, &r); 536 v4l2_rect_set_size_to(compose, &r);
536 } 537 }
537 538
538 dev->fmt_out_rect.width = mp->width; 539 dev->fmt_out_rect.width = mp->width;
@@ -683,8 +684,8 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection
683 ret = vivid_vid_adjust_sel(s->flags, &s->r); 684 ret = vivid_vid_adjust_sel(s->flags, &s->r);
684 if (ret) 685 if (ret)
685 return ret; 686 return ret;
686 rect_set_min_size(&s->r, &vivid_min_rect); 687 v4l2_rect_set_min_size(&s->r, &vivid_min_rect);
687 rect_set_max_size(&s->r, &dev->fmt_out_rect); 688 v4l2_rect_set_max_size(&s->r, &dev->fmt_out_rect);
688 if (dev->has_scaler_out) { 689 if (dev->has_scaler_out) {
689 struct v4l2_rect max_rect = { 690 struct v4l2_rect max_rect = {
690 0, 0, 691 0, 0,
@@ -692,7 +693,7 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection
692 (dev->sink_rect.height / factor) * MAX_ZOOM 693 (dev->sink_rect.height / factor) * MAX_ZOOM
693 }; 694 };
694 695
695 rect_set_max_size(&s->r, &max_rect); 696 v4l2_rect_set_max_size(&s->r, &max_rect);
696 if (dev->has_compose_out) { 697 if (dev->has_compose_out) {
697 struct v4l2_rect min_rect = { 698 struct v4l2_rect min_rect = {
698 0, 0, 699 0, 0,
@@ -705,23 +706,23 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection
705 (s->r.height * factor) * MAX_ZOOM 706 (s->r.height * factor) * MAX_ZOOM
706 }; 707 };
707 708
708 rect_set_min_size(compose, &min_rect); 709 v4l2_rect_set_min_size(compose, &min_rect);
709 rect_set_max_size(compose, &max_rect); 710 v4l2_rect_set_max_size(compose, &max_rect);
710 rect_map_inside(compose, &dev->compose_bounds_out); 711 v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
711 } 712 }
712 } else if (dev->has_compose_out) { 713 } else if (dev->has_compose_out) {
713 s->r.top *= factor; 714 s->r.top *= factor;
714 s->r.height *= factor; 715 s->r.height *= factor;
715 rect_set_max_size(&s->r, &dev->sink_rect); 716 v4l2_rect_set_max_size(&s->r, &dev->sink_rect);
716 rect_set_size_to(compose, &s->r); 717 v4l2_rect_set_size_to(compose, &s->r);
717 rect_map_inside(compose, &dev->compose_bounds_out); 718 v4l2_rect_map_inside(compose, &dev->compose_bounds_out);
718 s->r.top /= factor; 719 s->r.top /= factor;
719 s->r.height /= factor; 720 s->r.height /= factor;
720 } else { 721 } else {
721 rect_set_size_to(&s->r, &dev->sink_rect); 722 v4l2_rect_set_size_to(&s->r, &dev->sink_rect);
722 s->r.height /= factor; 723 s->r.height /= factor;
723 } 724 }
724 rect_map_inside(&s->r, &dev->fmt_out_rect); 725 v4l2_rect_map_inside(&s->r, &dev->fmt_out_rect);
725 *crop = s->r; 726 *crop = s->r;
726 break; 727 break;
727 case V4L2_SEL_TGT_COMPOSE: 728 case V4L2_SEL_TGT_COMPOSE:
@@ -730,9 +731,9 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection
730 ret = vivid_vid_adjust_sel(s->flags, &s->r); 731 ret = vivid_vid_adjust_sel(s->flags, &s->r);
731 if (ret) 732 if (ret)
732 return ret; 733 return ret;
733 rect_set_min_size(&s->r, &vivid_min_rect); 734 v4l2_rect_set_min_size(&s->r, &vivid_min_rect);
734 rect_set_max_size(&s->r, &dev->sink_rect); 735 v4l2_rect_set_max_size(&s->r, &dev->sink_rect);
735 rect_map_inside(&s->r, &dev->compose_bounds_out); 736 v4l2_rect_map_inside(&s->r, &dev->compose_bounds_out);
736 s->r.top /= factor; 737 s->r.top /= factor;
737 s->r.height /= factor; 738 s->r.height /= factor;
738 if (dev->has_scaler_out) { 739 if (dev->has_scaler_out) {
@@ -748,35 +749,35 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection
748 s->r.height / MAX_ZOOM 749 s->r.height / MAX_ZOOM
749 }; 750 };
750 751
751 rect_set_min_size(&fmt, &min_rect); 752 v4l2_rect_set_min_size(&fmt, &min_rect);
752 if (!dev->has_crop_out) 753 if (!dev->has_crop_out)
753 rect_set_max_size(&fmt, &max_rect); 754 v4l2_rect_set_max_size(&fmt, &max_rect);
754 if (!rect_same_size(&dev->fmt_out_rect, &fmt) && 755 if (!v4l2_rect_same_size(&dev->fmt_out_rect, &fmt) &&
755 vb2_is_busy(&dev->vb_vid_out_q)) 756 vb2_is_busy(&dev->vb_vid_out_q))
756 return -EBUSY; 757 return -EBUSY;
757 if (dev->has_crop_out) { 758 if (dev->has_crop_out) {
758 rect_set_min_size(crop, &min_rect); 759 v4l2_rect_set_min_size(crop, &min_rect);
759 rect_set_max_size(crop, &max_rect); 760 v4l2_rect_set_max_size(crop, &max_rect);
760 } 761 }
761 dev->fmt_out_rect = fmt; 762 dev->fmt_out_rect = fmt;
762 } else if (dev->has_crop_out) { 763 } else if (dev->has_crop_out) {
763 struct v4l2_rect fmt = dev->fmt_out_rect; 764 struct v4l2_rect fmt = dev->fmt_out_rect;
764 765
765 rect_set_min_size(&fmt, &s->r); 766 v4l2_rect_set_min_size(&fmt, &s->r);
766 if (!rect_same_size(&dev->fmt_out_rect, &fmt) && 767 if (!v4l2_rect_same_size(&dev->fmt_out_rect, &fmt) &&
767 vb2_is_busy(&dev->vb_vid_out_q)) 768 vb2_is_busy(&dev->vb_vid_out_q))
768 return -EBUSY; 769 return -EBUSY;
769 dev->fmt_out_rect = fmt; 770 dev->fmt_out_rect = fmt;
770 rect_set_size_to(crop, &s->r); 771 v4l2_rect_set_size_to(crop, &s->r);
771 rect_map_inside(crop, &dev->fmt_out_rect); 772 v4l2_rect_map_inside(crop, &dev->fmt_out_rect);
772 } else { 773 } else {
773 if (!rect_same_size(&s->r, &dev->fmt_out_rect) && 774 if (!v4l2_rect_same_size(&s->r, &dev->fmt_out_rect) &&
774 vb2_is_busy(&dev->vb_vid_out_q)) 775 vb2_is_busy(&dev->vb_vid_out_q))
775 return -EBUSY; 776 return -EBUSY;
776 rect_set_size_to(&dev->fmt_out_rect, &s->r); 777 v4l2_rect_set_size_to(&dev->fmt_out_rect, &s->r);
777 rect_set_size_to(crop, &s->r); 778 v4l2_rect_set_size_to(crop, &s->r);
778 crop->height /= factor; 779 crop->height /= factor;
779 rect_map_inside(crop, &dev->fmt_out_rect); 780 v4l2_rect_map_inside(crop, &dev->fmt_out_rect);
780 } 781 }
781 s->r.top *= factor; 782 s->r.top *= factor;
782 s->r.height *= factor; 783 s->r.height *= factor;
@@ -901,7 +902,7 @@ int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv,
901 for (j = i + 1; j < win->clipcount; j++) { 902 for (j = i + 1; j < win->clipcount; j++) {
902 struct v4l2_rect *r2 = &dev->try_clips_out[j].c; 903 struct v4l2_rect *r2 = &dev->try_clips_out[j].c;
903 904
904 if (rect_overlap(r1, r2)) 905 if (v4l2_rect_overlap(r1, r2))
905 return -EINVAL; 906 return -EINVAL;
906 } 907 }
907 } 908 }
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 910d6b8e8b50..46738b6c5f72 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -26,7 +26,6 @@
26struct clk; 26struct clk;
27struct device; 27struct device;
28 28
29struct vsp1_dl;
30struct vsp1_drm; 29struct vsp1_drm;
31struct vsp1_entity; 30struct vsp1_entity;
32struct vsp1_platform_data; 31struct vsp1_platform_data;
@@ -49,6 +48,7 @@ struct vsp1_uds;
49 48
50struct vsp1_device_info { 49struct vsp1_device_info {
51 u32 version; 50 u32 version;
51 unsigned int gen;
52 unsigned int features; 52 unsigned int features;
53 unsigned int rpf_count; 53 unsigned int rpf_count;
54 unsigned int uds_count; 54 unsigned int uds_count;
@@ -85,8 +85,6 @@ struct vsp1_device {
85 struct media_entity_operations media_ops; 85 struct media_entity_operations media_ops;
86 86
87 struct vsp1_drm *drm; 87 struct vsp1_drm *drm;
88
89 bool use_dl;
90}; 88};
91 89
92int vsp1_device_get(struct vsp1_device *vsp1); 90int vsp1_device_get(struct vsp1_device *vsp1);
@@ -104,14 +102,4 @@ static inline void vsp1_write(struct vsp1_device *vsp1, u32 reg, u32 data)
104 iowrite32(data, vsp1->mmio + reg); 102 iowrite32(data, vsp1->mmio + reg);
105} 103}
106 104
107#include "vsp1_dl.h"
108
109static inline void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data)
110{
111 if (e->vsp1->use_dl)
112 vsp1_dl_add(e, reg, data);
113 else
114 vsp1_write(e->vsp1, reg, data);
115}
116
117#endif /* __VSP1_H__ */ 105#endif /* __VSP1_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index cb0dbc15ddad..b1068c018011 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -18,6 +18,8 @@
18 18
19#include "vsp1.h" 19#include "vsp1.h"
20#include "vsp1_bru.h" 20#include "vsp1_bru.h"
21#include "vsp1_dl.h"
22#include "vsp1_pipe.h"
21#include "vsp1_rwpf.h" 23#include "vsp1_rwpf.h"
22#include "vsp1_video.h" 24#include "vsp1_video.h"
23 25
@@ -28,9 +30,10 @@
28 * Device Access 30 * Device Access
29 */ 31 */
30 32
31static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data) 33static inline void vsp1_bru_write(struct vsp1_bru *bru, struct vsp1_dl_list *dl,
34 u32 reg, u32 data)
32{ 35{
33 vsp1_mod_write(&bru->entity, reg, data); 36 vsp1_dl_list_write(dl, reg, data);
34} 37}
35 38
36/* ----------------------------------------------------------------------------- 39/* -----------------------------------------------------------------------------
@@ -42,13 +45,9 @@ static int bru_s_ctrl(struct v4l2_ctrl *ctrl)
42 struct vsp1_bru *bru = 45 struct vsp1_bru *bru =
43 container_of(ctrl->handler, struct vsp1_bru, ctrls); 46 container_of(ctrl->handler, struct vsp1_bru, ctrls);
44 47
45 if (!vsp1_entity_is_streaming(&bru->entity))
46 return 0;
47
48 switch (ctrl->id) { 48 switch (ctrl->id) {
49 case V4L2_CID_BG_COLOR: 49 case V4L2_CID_BG_COLOR:
50 vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, ctrl->val | 50 bru->bgcolor = ctrl->val;
51 (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT));
52 break; 51 break;
53 } 52 }
54 53
@@ -60,116 +59,7 @@ static const struct v4l2_ctrl_ops bru_ctrl_ops = {
60}; 59};
61 60
62/* ----------------------------------------------------------------------------- 61/* -----------------------------------------------------------------------------
63 * V4L2 Subdevice Core Operations 62 * V4L2 Subdevice Operations
64 */
65
66static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
67{
68 struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity);
69 struct vsp1_bru *bru = to_bru(subdev);
70 struct v4l2_mbus_framefmt *format;
71 unsigned int flags;
72 unsigned int i;
73 int ret;
74
75 ret = vsp1_entity_set_streaming(&bru->entity, enable);
76 if (ret < 0)
77 return ret;
78
79 if (!enable)
80 return 0;
81
82 format = &bru->entity.formats[bru->entity.source_pad];
83
84 /* The hardware is extremely flexible but we have no userspace API to
85 * expose all the parameters, nor is it clear whether we would have use
86 * cases for all the supported modes. Let's just harcode the parameters
87 * to sane default values for now.
88 */
89
90 /* Disable dithering and enable color data normalization unless the
91 * format at the pipeline output is premultiplied.
92 */
93 flags = pipe->output ? pipe->output->format.flags : 0;
94 vsp1_bru_write(bru, VI6_BRU_INCTRL,
95 flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
96 0 : VI6_BRU_INCTRL_NRM);
97
98 /* Set the background position to cover the whole output image. */
99 vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE,
100 (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
101 (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
102 vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0);
103
104 /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP
105 * unit with a NOP operation to make BRU input 1 available as the
106 * Blend/ROP unit B SRC input.
107 */
108 vsp1_bru_write(bru, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) |
109 VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
110 VI6_BRU_ROP_AROP(VI6_ROP_NOP));
111
112 for (i = 0; i < bru->entity.source_pad; ++i) {
113 bool premultiplied = false;
114 u32 ctrl = 0;
115
116 /* Configure all Blend/ROP units corresponding to an enabled BRU
117 * input for alpha blending. Blend/ROP units corresponding to
118 * disabled BRU inputs are used in ROP NOP mode to ignore the
119 * SRC input.
120 */
121 if (bru->inputs[i].rpf) {
122 ctrl |= VI6_BRU_CTRL_RBC;
123
124 premultiplied = bru->inputs[i].rpf->format.flags
125 & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
126 } else {
127 ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
128 | VI6_BRU_CTRL_AROP(VI6_ROP_NOP);
129 }
130
131 /* Select the virtual RPF as the Blend/ROP unit A DST input to
132 * serve as a background color.
133 */
134 if (i == 0)
135 ctrl |= VI6_BRU_CTRL_DSTSEL_VRPF;
136
137 /* Route BRU inputs 0 to 3 as SRC inputs to Blend/ROP units A to
138 * D in that order. The Blend/ROP unit B SRC is hardwired to the
139 * ROP unit output, the corresponding register bits must be set
140 * to 0.
141 */
142 if (i != 1)
143 ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i);
144
145 vsp1_bru_write(bru, VI6_BRU_CTRL(i), ctrl);
146
147 /* Harcode the blending formula to
148 *
149 * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa
150 * DSTa = DSTa * (1 - SRCa) + SRCa
151 *
152 * when the SRC input isn't premultiplied, and to
153 *
154 * DSTc = DSTc * (1 - SRCa) + SRCc
155 * DSTa = DSTa * (1 - SRCa) + SRCa
156 *
157 * otherwise.
158 */
159 vsp1_bru_write(bru, VI6_BRU_BLD(i),
160 VI6_BRU_BLD_CCMDX_255_SRC_A |
161 (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY :
162 VI6_BRU_BLD_CCMDY_SRC_A) |
163 VI6_BRU_BLD_ACMDX_255_SRC_A |
164 VI6_BRU_BLD_ACMDY_COEFY |
165 (0xff << VI6_BRU_BLD_COEFY_SHIFT));
166 }
167
168 return 0;
169}
170
171/* -----------------------------------------------------------------------------
172 * V4L2 Subdevice Pad Operations
173 */ 63 */
174 64
175/* 65/*
@@ -186,24 +76,9 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
186 MEDIA_BUS_FMT_ARGB8888_1X32, 76 MEDIA_BUS_FMT_ARGB8888_1X32,
187 MEDIA_BUS_FMT_AYUV8_1X32, 77 MEDIA_BUS_FMT_AYUV8_1X32,
188 }; 78 };
189 struct vsp1_bru *bru = to_bru(subdev);
190 struct v4l2_mbus_framefmt *format;
191
192 if (code->pad == BRU_PAD_SINK(0)) {
193 if (code->index >= ARRAY_SIZE(codes))
194 return -EINVAL;
195
196 code->code = codes[code->index];
197 } else {
198 if (code->index)
199 return -EINVAL;
200
201 format = vsp1_entity_get_pad_format(&bru->entity, cfg,
202 BRU_PAD_SINK(0), code->which);
203 code->code = format->code;
204 }
205 79
206 return 0; 80 return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
81 ARRAY_SIZE(codes));
207} 82}
208 83
209static int bru_enum_frame_size(struct v4l2_subdev *subdev, 84static int bru_enum_frame_size(struct v4l2_subdev *subdev,
@@ -227,32 +102,14 @@ static int bru_enum_frame_size(struct v4l2_subdev *subdev,
227 102
228static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru, 103static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
229 struct v4l2_subdev_pad_config *cfg, 104 struct v4l2_subdev_pad_config *cfg,
230 unsigned int pad, u32 which) 105 unsigned int pad)
231{
232 switch (which) {
233 case V4L2_SUBDEV_FORMAT_TRY:
234 return v4l2_subdev_get_try_crop(&bru->entity.subdev, cfg, pad);
235 case V4L2_SUBDEV_FORMAT_ACTIVE:
236 return &bru->inputs[pad].compose;
237 default:
238 return NULL;
239 }
240}
241
242static int bru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
243 struct v4l2_subdev_format *fmt)
244{ 106{
245 struct vsp1_bru *bru = to_bru(subdev); 107 return v4l2_subdev_get_try_compose(&bru->entity.subdev, cfg, pad);
246
247 fmt->format = *vsp1_entity_get_pad_format(&bru->entity, cfg, fmt->pad,
248 fmt->which);
249
250 return 0;
251} 108}
252 109
253static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_pad_config *cfg, 110static void bru_try_format(struct vsp1_bru *bru,
254 unsigned int pad, struct v4l2_mbus_framefmt *fmt, 111 struct v4l2_subdev_pad_config *config,
255 enum v4l2_subdev_format_whence which) 112 unsigned int pad, struct v4l2_mbus_framefmt *fmt)
256{ 113{
257 struct v4l2_mbus_framefmt *format; 114 struct v4l2_mbus_framefmt *format;
258 115
@@ -266,8 +123,8 @@ static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_pad_config *
266 123
267 default: 124 default:
268 /* The BRU can't perform format conversion. */ 125 /* The BRU can't perform format conversion. */
269 format = vsp1_entity_get_pad_format(&bru->entity, cfg, 126 format = vsp1_entity_get_pad_format(&bru->entity, config,
270 BRU_PAD_SINK(0), which); 127 BRU_PAD_SINK(0));
271 fmt->code = format->code; 128 fmt->code = format->code;
272 break; 129 break;
273 } 130 }
@@ -278,23 +135,28 @@ static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_pad_config *
278 fmt->colorspace = V4L2_COLORSPACE_SRGB; 135 fmt->colorspace = V4L2_COLORSPACE_SRGB;
279} 136}
280 137
281static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 138static int bru_set_format(struct v4l2_subdev *subdev,
139 struct v4l2_subdev_pad_config *cfg,
282 struct v4l2_subdev_format *fmt) 140 struct v4l2_subdev_format *fmt)
283{ 141{
284 struct vsp1_bru *bru = to_bru(subdev); 142 struct vsp1_bru *bru = to_bru(subdev);
143 struct v4l2_subdev_pad_config *config;
285 struct v4l2_mbus_framefmt *format; 144 struct v4l2_mbus_framefmt *format;
286 145
287 bru_try_format(bru, cfg, fmt->pad, &fmt->format, fmt->which); 146 config = vsp1_entity_get_pad_config(&bru->entity, cfg, fmt->which);
147 if (!config)
148 return -EINVAL;
149
150 bru_try_format(bru, config, fmt->pad, &fmt->format);
288 151
289 format = vsp1_entity_get_pad_format(&bru->entity, cfg, fmt->pad, 152 format = vsp1_entity_get_pad_format(&bru->entity, config, fmt->pad);
290 fmt->which);
291 *format = fmt->format; 153 *format = fmt->format;
292 154
293 /* Reset the compose rectangle */ 155 /* Reset the compose rectangle */
294 if (fmt->pad != bru->entity.source_pad) { 156 if (fmt->pad != bru->entity.source_pad) {
295 struct v4l2_rect *compose; 157 struct v4l2_rect *compose;
296 158
297 compose = bru_get_compose(bru, cfg, fmt->pad, fmt->which); 159 compose = bru_get_compose(bru, config, fmt->pad);
298 compose->left = 0; 160 compose->left = 0;
299 compose->top = 0; 161 compose->top = 0;
300 compose->width = format->width; 162 compose->width = format->width;
@@ -306,8 +168,8 @@ static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con
306 unsigned int i; 168 unsigned int i;
307 169
308 for (i = 0; i <= bru->entity.source_pad; ++i) { 170 for (i = 0; i <= bru->entity.source_pad; ++i) {
309 format = vsp1_entity_get_pad_format(&bru->entity, cfg, 171 format = vsp1_entity_get_pad_format(&bru->entity,
310 i, fmt->which); 172 config, i);
311 format->code = fmt->format.code; 173 format->code = fmt->format.code;
312 } 174 }
313 } 175 }
@@ -320,6 +182,7 @@ static int bru_get_selection(struct v4l2_subdev *subdev,
320 struct v4l2_subdev_selection *sel) 182 struct v4l2_subdev_selection *sel)
321{ 183{
322 struct vsp1_bru *bru = to_bru(subdev); 184 struct vsp1_bru *bru = to_bru(subdev);
185 struct v4l2_subdev_pad_config *config;
323 186
324 if (sel->pad == bru->entity.source_pad) 187 if (sel->pad == bru->entity.source_pad)
325 return -EINVAL; 188 return -EINVAL;
@@ -333,7 +196,12 @@ static int bru_get_selection(struct v4l2_subdev *subdev,
333 return 0; 196 return 0;
334 197
335 case V4L2_SEL_TGT_COMPOSE: 198 case V4L2_SEL_TGT_COMPOSE:
336 sel->r = *bru_get_compose(bru, cfg, sel->pad, sel->which); 199 config = vsp1_entity_get_pad_config(&bru->entity, cfg,
200 sel->which);
201 if (!config)
202 return -EINVAL;
203
204 sel->r = *bru_get_compose(bru, config, sel->pad);
337 return 0; 205 return 0;
338 206
339 default: 207 default:
@@ -346,6 +214,7 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
346 struct v4l2_subdev_selection *sel) 214 struct v4l2_subdev_selection *sel)
347{ 215{
348 struct vsp1_bru *bru = to_bru(subdev); 216 struct vsp1_bru *bru = to_bru(subdev);
217 struct v4l2_subdev_pad_config *config;
349 struct v4l2_mbus_framefmt *format; 218 struct v4l2_mbus_framefmt *format;
350 struct v4l2_rect *compose; 219 struct v4l2_rect *compose;
351 220
@@ -355,57 +224,161 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
355 if (sel->target != V4L2_SEL_TGT_COMPOSE) 224 if (sel->target != V4L2_SEL_TGT_COMPOSE)
356 return -EINVAL; 225 return -EINVAL;
357 226
227 config = vsp1_entity_get_pad_config(&bru->entity, cfg, sel->which);
228 if (!config)
229 return -EINVAL;
230
358 /* The compose rectangle top left corner must be inside the output 231 /* The compose rectangle top left corner must be inside the output
359 * frame. 232 * frame.
360 */ 233 */
361 format = vsp1_entity_get_pad_format(&bru->entity, cfg, 234 format = vsp1_entity_get_pad_format(&bru->entity, config,
362 bru->entity.source_pad, sel->which); 235 bru->entity.source_pad);
363 sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1); 236 sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1);
364 sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1); 237 sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1);
365 238
366 /* Scaling isn't supported, the compose rectangle size must be identical 239 /* Scaling isn't supported, the compose rectangle size must be identical
367 * to the sink format size. 240 * to the sink format size.
368 */ 241 */
369 format = vsp1_entity_get_pad_format(&bru->entity, cfg, sel->pad, 242 format = vsp1_entity_get_pad_format(&bru->entity, config, sel->pad);
370 sel->which);
371 sel->r.width = format->width; 243 sel->r.width = format->width;
372 sel->r.height = format->height; 244 sel->r.height = format->height;
373 245
374 compose = bru_get_compose(bru, cfg, sel->pad, sel->which); 246 compose = bru_get_compose(bru, config, sel->pad);
375 *compose = sel->r; 247 *compose = sel->r;
376 248
377 return 0; 249 return 0;
378} 250}
379 251
380/* -----------------------------------------------------------------------------
381 * V4L2 Subdevice Operations
382 */
383
384static struct v4l2_subdev_video_ops bru_video_ops = {
385 .s_stream = bru_s_stream,
386};
387
388static struct v4l2_subdev_pad_ops bru_pad_ops = { 252static struct v4l2_subdev_pad_ops bru_pad_ops = {
253 .init_cfg = vsp1_entity_init_cfg,
389 .enum_mbus_code = bru_enum_mbus_code, 254 .enum_mbus_code = bru_enum_mbus_code,
390 .enum_frame_size = bru_enum_frame_size, 255 .enum_frame_size = bru_enum_frame_size,
391 .get_fmt = bru_get_format, 256 .get_fmt = vsp1_subdev_get_pad_format,
392 .set_fmt = bru_set_format, 257 .set_fmt = bru_set_format,
393 .get_selection = bru_get_selection, 258 .get_selection = bru_get_selection,
394 .set_selection = bru_set_selection, 259 .set_selection = bru_set_selection,
395}; 260};
396 261
397static struct v4l2_subdev_ops bru_ops = { 262static struct v4l2_subdev_ops bru_ops = {
398 .video = &bru_video_ops,
399 .pad = &bru_pad_ops, 263 .pad = &bru_pad_ops,
400}; 264};
401 265
402/* ----------------------------------------------------------------------------- 266/* -----------------------------------------------------------------------------
267 * VSP1 Entity Operations
268 */
269
270static void bru_configure(struct vsp1_entity *entity,
271 struct vsp1_pipeline *pipe,
272 struct vsp1_dl_list *dl)
273{
274 struct vsp1_bru *bru = to_bru(&entity->subdev);
275 struct v4l2_mbus_framefmt *format;
276 unsigned int flags;
277 unsigned int i;
278
279 format = vsp1_entity_get_pad_format(&bru->entity, bru->entity.config,
280 bru->entity.source_pad);
281
282 /* The hardware is extremely flexible but we have no userspace API to
283 * expose all the parameters, nor is it clear whether we would have use
284 * cases for all the supported modes. Let's just harcode the parameters
285 * to sane default values for now.
286 */
287
288 /* Disable dithering and enable color data normalization unless the
289 * format at the pipeline output is premultiplied.
290 */
291 flags = pipe->output ? pipe->output->format.flags : 0;
292 vsp1_bru_write(bru, dl, VI6_BRU_INCTRL,
293 flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
294 0 : VI6_BRU_INCTRL_NRM);
295
296 /* Set the background position to cover the whole output image and
297 * configure its color.
298 */
299 vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_SIZE,
300 (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
301 (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
302 vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_LOC, 0);
303
304 vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_COL, bru->bgcolor |
305 (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT));
306
307 /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP
308 * unit with a NOP operation to make BRU input 1 available as the
309 * Blend/ROP unit B SRC input.
310 */
311 vsp1_bru_write(bru, dl, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) |
312 VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
313 VI6_BRU_ROP_AROP(VI6_ROP_NOP));
314
315 for (i = 0; i < bru->entity.source_pad; ++i) {
316 bool premultiplied = false;
317 u32 ctrl = 0;
318
319 /* Configure all Blend/ROP units corresponding to an enabled BRU
320 * input for alpha blending. Blend/ROP units corresponding to
321 * disabled BRU inputs are used in ROP NOP mode to ignore the
322 * SRC input.
323 */
324 if (bru->inputs[i].rpf) {
325 ctrl |= VI6_BRU_CTRL_RBC;
326
327 premultiplied = bru->inputs[i].rpf->format.flags
328 & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
329 } else {
330 ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
331 | VI6_BRU_CTRL_AROP(VI6_ROP_NOP);
332 }
333
334 /* Select the virtual RPF as the Blend/ROP unit A DST input to
335 * serve as a background color.
336 */
337 if (i == 0)
338 ctrl |= VI6_BRU_CTRL_DSTSEL_VRPF;
339
340 /* Route BRU inputs 0 to 3 as SRC inputs to Blend/ROP units A to
341 * D in that order. The Blend/ROP unit B SRC is hardwired to the
342 * ROP unit output, the corresponding register bits must be set
343 * to 0.
344 */
345 if (i != 1)
346 ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i);
347
348 vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl);
349
350 /* Harcode the blending formula to
351 *
352 * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa
353 * DSTa = DSTa * (1 - SRCa) + SRCa
354 *
355 * when the SRC input isn't premultiplied, and to
356 *
357 * DSTc = DSTc * (1 - SRCa) + SRCc
358 * DSTa = DSTa * (1 - SRCa) + SRCa
359 *
360 * otherwise.
361 */
362 vsp1_bru_write(bru, dl, VI6_BRU_BLD(i),
363 VI6_BRU_BLD_CCMDX_255_SRC_A |
364 (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY :
365 VI6_BRU_BLD_CCMDY_SRC_A) |
366 VI6_BRU_BLD_ACMDX_255_SRC_A |
367 VI6_BRU_BLD_ACMDY_COEFY |
368 (0xff << VI6_BRU_BLD_COEFY_SHIFT));
369 }
370}
371
372static const struct vsp1_entity_operations bru_entity_ops = {
373 .configure = bru_configure,
374};
375
376/* -----------------------------------------------------------------------------
403 * Initialization and Cleanup 377 * Initialization and Cleanup
404 */ 378 */
405 379
406struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) 380struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
407{ 381{
408 struct v4l2_subdev *subdev;
409 struct vsp1_bru *bru; 382 struct vsp1_bru *bru;
410 int ret; 383 int ret;
411 384
@@ -413,31 +386,21 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
413 if (bru == NULL) 386 if (bru == NULL)
414 return ERR_PTR(-ENOMEM); 387 return ERR_PTR(-ENOMEM);
415 388
389 bru->entity.ops = &bru_entity_ops;
416 bru->entity.type = VSP1_ENTITY_BRU; 390 bru->entity.type = VSP1_ENTITY_BRU;
417 391
418 ret = vsp1_entity_init(vsp1, &bru->entity, 392 ret = vsp1_entity_init(vsp1, &bru->entity, "bru",
419 vsp1->info->num_bru_inputs + 1); 393 vsp1->info->num_bru_inputs + 1, &bru_ops);
420 if (ret < 0) 394 if (ret < 0)
421 return ERR_PTR(ret); 395 return ERR_PTR(ret);
422 396
423 /* Initialize the V4L2 subdev. */
424 subdev = &bru->entity.subdev;
425 v4l2_subdev_init(subdev, &bru_ops);
426
427 subdev->entity.ops = &vsp1->media_ops;
428 subdev->internal_ops = &vsp1_subdev_internal_ops;
429 snprintf(subdev->name, sizeof(subdev->name), "%s bru",
430 dev_name(vsp1->dev));
431 v4l2_set_subdevdata(subdev, bru);
432 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
433
434 vsp1_entity_init_formats(subdev, NULL);
435
436 /* Initialize the control handler. */ 397 /* Initialize the control handler. */
437 v4l2_ctrl_handler_init(&bru->ctrls, 1); 398 v4l2_ctrl_handler_init(&bru->ctrls, 1);
438 v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR, 399 v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR,
439 0, 0xffffff, 1, 0); 400 0, 0xffffff, 1, 0);
440 401
402 bru->bgcolor = 0;
403
441 bru->entity.subdev.ctrl_handler = &bru->ctrls; 404 bru->entity.subdev.ctrl_handler = &bru->ctrls;
442 405
443 if (bru->ctrls.error) { 406 if (bru->ctrls.error) {
diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h
index dbac9686ea69..828a3fcadea8 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.h
+++ b/drivers/media/platform/vsp1/vsp1_bru.h
@@ -31,8 +31,9 @@ struct vsp1_bru {
31 31
32 struct { 32 struct {
33 struct vsp1_rwpf *rpf; 33 struct vsp1_rwpf *rpf;
34 struct v4l2_rect compose;
35 } inputs[VSP1_MAX_RPF]; 34 } inputs[VSP1_MAX_RPF];
35
36 u32 bgcolor;
36}; 37};
37 38
38static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev) 39static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c
index 1a9a58588f84..e238d9b9376b 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -18,139 +18,406 @@
18 18
19#include "vsp1.h" 19#include "vsp1.h"
20#include "vsp1_dl.h" 20#include "vsp1_dl.h"
21#include "vsp1_pipe.h"
22 21
23/* 22#define VSP1_DL_NUM_ENTRIES 256
24 * Global resources
25 *
26 * - Display-related interrupts (can be used for vblank evasion ?)
27 * - Display-list enable
28 * - Header-less for WPF0
29 * - DL swap
30 */
31
32#define VSP1_DL_BODY_SIZE (2 * 4 * 256)
33#define VSP1_DL_NUM_LISTS 3 23#define VSP1_DL_NUM_LISTS 3
34 24
25#define VSP1_DLH_INT_ENABLE (1 << 1)
26#define VSP1_DLH_AUTO_START (1 << 0)
27
28struct vsp1_dl_header_list {
29 u32 num_bytes;
30 u32 addr;
31} __attribute__((__packed__));
32
33struct vsp1_dl_header {
34 u32 num_lists;
35 struct vsp1_dl_header_list lists[8];
36 u32 next_header;
37 u32 flags;
38} __attribute__((__packed__));
39
35struct vsp1_dl_entry { 40struct vsp1_dl_entry {
36 u32 addr; 41 u32 addr;
37 u32 data; 42 u32 data;
38} __attribute__((__packed__)); 43} __attribute__((__packed__));
39 44
40struct vsp1_dl_list { 45/**
46 * struct vsp1_dl_body - Display list body
47 * @list: entry in the display list list of bodies
48 * @vsp1: the VSP1 device
49 * @entries: array of entries
50 * @dma: DMA address of the entries
51 * @size: size of the DMA memory in bytes
52 * @num_entries: number of stored entries
53 */
54struct vsp1_dl_body {
55 struct list_head list;
56 struct vsp1_device *vsp1;
57
58 struct vsp1_dl_entry *entries;
59 dma_addr_t dma;
41 size_t size; 60 size_t size;
42 int reg_count;
43 61
44 bool in_use; 62 unsigned int num_entries;
63};
45 64
46 struct vsp1_dl_entry *body; 65/**
66 * struct vsp1_dl_list - Display list
67 * @list: entry in the display list manager lists
68 * @dlm: the display list manager
69 * @header: display list header, NULL for headerless lists
70 * @dma: DMA address for the header
71 * @body0: first display list body
72 * @fragments: list of extra display list bodies
73 */
74struct vsp1_dl_list {
75 struct list_head list;
76 struct vsp1_dl_manager *dlm;
77
78 struct vsp1_dl_header *header;
47 dma_addr_t dma; 79 dma_addr_t dma;
80
81 struct vsp1_dl_body body0;
82 struct list_head fragments;
83};
84
85enum vsp1_dl_mode {
86 VSP1_DL_MODE_HEADER,
87 VSP1_DL_MODE_HEADERLESS,
48}; 88};
49 89
50/** 90/**
51 * struct vsp1_dl - Display List manager 91 * struct vsp1_dl_manager - Display List manager
92 * @index: index of the related WPF
93 * @mode: display list operation mode (header or headerless)
52 * @vsp1: the VSP1 device 94 * @vsp1: the VSP1 device
53 * @lock: protects the active, queued and pending lists 95 * @lock: protects the active, queued and pending lists
54 * @lists.all: array of all allocate display lists 96 * @free: array of all free display lists
55 * @lists.active: list currently being processed (loaded) by hardware 97 * @active: list currently being processed (loaded) by hardware
56 * @lists.queued: list queued to the hardware (written to the DL registers) 98 * @queued: list queued to the hardware (written to the DL registers)
57 * @lists.pending: list waiting to be queued to the hardware 99 * @pending: list waiting to be queued to the hardware
58 * @lists.write: list being written to by software
59 */ 100 */
60struct vsp1_dl { 101struct vsp1_dl_manager {
102 unsigned int index;
103 enum vsp1_dl_mode mode;
61 struct vsp1_device *vsp1; 104 struct vsp1_device *vsp1;
62 105
63 spinlock_t lock; 106 spinlock_t lock;
107 struct list_head free;
108 struct vsp1_dl_list *active;
109 struct vsp1_dl_list *queued;
110 struct vsp1_dl_list *pending;
111};
64 112
65 size_t size; 113/* -----------------------------------------------------------------------------
66 dma_addr_t dma; 114 * Display List Body Management
67 void *mem; 115 */
116
117/*
118 * Initialize a display list body object and allocate DMA memory for the body
119 * data. The display list body object is expected to have been initialized to
120 * 0 when allocated.
121 */
122static int vsp1_dl_body_init(struct vsp1_device *vsp1,
123 struct vsp1_dl_body *dlb, unsigned int num_entries,
124 size_t extra_size)
125{
126 size_t size = num_entries * sizeof(*dlb->entries) + extra_size;
68 127
69 struct { 128 dlb->vsp1 = vsp1;
70 struct vsp1_dl_list all[VSP1_DL_NUM_LISTS]; 129 dlb->size = size;
71 130
72 struct vsp1_dl_list *active; 131 dlb->entries = dma_alloc_wc(vsp1->dev, dlb->size, &dlb->dma,
73 struct vsp1_dl_list *queued; 132 GFP_KERNEL);
74 struct vsp1_dl_list *pending; 133 if (!dlb->entries)
75 struct vsp1_dl_list *write; 134 return -ENOMEM;
76 } lists; 135
77}; 136 return 0;
137}
138
139/*
140 * Cleanup a display list body and free allocated DMA memory allocated.
141 */
142static void vsp1_dl_body_cleanup(struct vsp1_dl_body *dlb)
143{
144 dma_free_wc(dlb->vsp1->dev, dlb->size, dlb->entries, dlb->dma);
145}
146
147/**
148 * vsp1_dl_fragment_alloc - Allocate a display list fragment
149 * @vsp1: The VSP1 device
150 * @num_entries: The maximum number of entries that the fragment can contain
151 *
152 * Allocate a display list fragment with enough memory to contain the requested
153 * number of entries.
154 *
155 * Return a pointer to a fragment on success or NULL if memory can't be
156 * allocated.
157 */
158struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1,
159 unsigned int num_entries)
160{
161 struct vsp1_dl_body *dlb;
162 int ret;
163
164 dlb = kzalloc(sizeof(*dlb), GFP_KERNEL);
165 if (!dlb)
166 return NULL;
167
168 ret = vsp1_dl_body_init(vsp1, dlb, num_entries, 0);
169 if (ret < 0) {
170 kfree(dlb);
171 return NULL;
172 }
173
174 return dlb;
175}
176
177/**
178 * vsp1_dl_fragment_free - Free a display list fragment
179 * @dlb: The fragment
180 *
181 * Free the given display list fragment and the associated DMA memory.
182 *
183 * Fragments must only be freed explicitly if they are not added to a display
184 * list, as the display list will take ownership of them and free them
185 * otherwise. Manual free typically happens at cleanup time for fragments that
186 * have been allocated but not used.
187 *
188 * Passing a NULL pointer to this function is safe, in that case no operation
189 * will be performed.
190 */
191void vsp1_dl_fragment_free(struct vsp1_dl_body *dlb)
192{
193 if (!dlb)
194 return;
195
196 vsp1_dl_body_cleanup(dlb);
197 kfree(dlb);
198}
199
200/**
201 * vsp1_dl_fragment_write - Write a register to a display list fragment
202 * @dlb: The fragment
203 * @reg: The register address
204 * @data: The register value
205 *
206 * Write the given register and value to the display list fragment. The maximum
207 * number of entries that can be written in a fragment is specified when the
208 * fragment is allocated by vsp1_dl_fragment_alloc().
209 */
210void vsp1_dl_fragment_write(struct vsp1_dl_body *dlb, u32 reg, u32 data)
211{
212 dlb->entries[dlb->num_entries].addr = reg;
213 dlb->entries[dlb->num_entries].data = data;
214 dlb->num_entries++;
215}
78 216
79/* ----------------------------------------------------------------------------- 217/* -----------------------------------------------------------------------------
80 * Display List Transaction Management 218 * Display List Transaction Management
81 */ 219 */
82 220
83static void vsp1_dl_free_list(struct vsp1_dl_list *list) 221static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm)
84{ 222{
85 if (!list) 223 struct vsp1_dl_list *dl;
86 return; 224 size_t header_size;
225 int ret;
226
227 dl = kzalloc(sizeof(*dl), GFP_KERNEL);
228 if (!dl)
229 return NULL;
87 230
88 list->in_use = false; 231 INIT_LIST_HEAD(&dl->fragments);
232 dl->dlm = dlm;
233
234 /* Initialize the display list body and allocate DMA memory for the body
235 * and the optional header. Both are allocated together to avoid memory
236 * fragmentation, with the header located right after the body in
237 * memory.
238 */
239 header_size = dlm->mode == VSP1_DL_MODE_HEADER
240 ? ALIGN(sizeof(struct vsp1_dl_header), 8)
241 : 0;
242
243 ret = vsp1_dl_body_init(dlm->vsp1, &dl->body0, VSP1_DL_NUM_ENTRIES,
244 header_size);
245 if (ret < 0) {
246 kfree(dl);
247 return NULL;
248 }
249
250 if (dlm->mode == VSP1_DL_MODE_HEADER) {
251 size_t header_offset = VSP1_DL_NUM_ENTRIES
252 * sizeof(*dl->body0.entries);
253
254 dl->header = ((void *)dl->body0.entries) + header_offset;
255 dl->dma = dl->body0.dma + header_offset;
256
257 memset(dl->header, 0, sizeof(*dl->header));
258 dl->header->lists[0].addr = dl->body0.dma;
259 dl->header->flags = VSP1_DLH_INT_ENABLE;
260 }
261
262 return dl;
89} 263}
90 264
91void vsp1_dl_reset(struct vsp1_dl *dl) 265static void vsp1_dl_list_free_fragments(struct vsp1_dl_list *dl)
92{ 266{
93 unsigned int i; 267 struct vsp1_dl_body *dlb, *next;
94 268
95 dl->lists.active = NULL; 269 list_for_each_entry_safe(dlb, next, &dl->fragments, list) {
96 dl->lists.queued = NULL; 270 list_del(&dlb->list);
97 dl->lists.pending = NULL; 271 vsp1_dl_body_cleanup(dlb);
98 dl->lists.write = NULL; 272 kfree(dlb);
273 }
274}
99 275
100 for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) 276static void vsp1_dl_list_free(struct vsp1_dl_list *dl)
101 dl->lists.all[i].in_use = false; 277{
278 vsp1_dl_body_cleanup(&dl->body0);
279 vsp1_dl_list_free_fragments(dl);
280 kfree(dl);
102} 281}
103 282
104void vsp1_dl_begin(struct vsp1_dl *dl) 283/**
284 * vsp1_dl_list_get - Get a free display list
285 * @dlm: The display list manager
286 *
287 * Get a display list from the pool of free lists and return it.
288 *
289 * This function must be called without the display list manager lock held.
290 */
291struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm)
105{ 292{
106 struct vsp1_dl_list *list = NULL; 293 struct vsp1_dl_list *dl = NULL;
107 unsigned long flags; 294 unsigned long flags;
108 unsigned int i;
109 295
110 spin_lock_irqsave(&dl->lock, flags); 296 spin_lock_irqsave(&dlm->lock, flags);
111 297
112 for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) { 298 if (!list_empty(&dlm->free)) {
113 if (!dl->lists.all[i].in_use) { 299 dl = list_first_entry(&dlm->free, struct vsp1_dl_list, list);
114 list = &dl->lists.all[i]; 300 list_del(&dl->list);
115 break;
116 }
117 } 301 }
118 302
119 if (!list) { 303 spin_unlock_irqrestore(&dlm->lock, flags);
120 list = dl->lists.pending; 304
121 dl->lists.pending = NULL; 305 return dl;
122 } 306}
307
308/* This function must be called with the display list manager lock held.*/
309static void __vsp1_dl_list_put(struct vsp1_dl_list *dl)
310{
311 if (!dl)
312 return;
313
314 vsp1_dl_list_free_fragments(dl);
315 dl->body0.num_entries = 0;
316
317 list_add_tail(&dl->list, &dl->dlm->free);
318}
319
320/**
321 * vsp1_dl_list_put - Release a display list
322 * @dl: The display list
323 *
324 * Release the display list and return it to the pool of free lists.
325 *
326 * Passing a NULL pointer to this function is safe, in that case no operation
327 * will be performed.
328 */
329void vsp1_dl_list_put(struct vsp1_dl_list *dl)
330{
331 unsigned long flags;
123 332
124 spin_unlock_irqrestore(&dl->lock, flags); 333 if (!dl)
334 return;
125 335
126 dl->lists.write = list; 336 spin_lock_irqsave(&dl->dlm->lock, flags);
337 __vsp1_dl_list_put(dl);
338 spin_unlock_irqrestore(&dl->dlm->lock, flags);
339}
127 340
128 list->in_use = true; 341/**
129 list->reg_count = 0; 342 * vsp1_dl_list_write - Write a register to the display list
343 * @dl: The display list
344 * @reg: The register address
345 * @data: The register value
346 *
347 * Write the given register and value to the display list. Up to 256 registers
348 * can be written per display list.
349 */
350void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data)
351{
352 vsp1_dl_fragment_write(&dl->body0, reg, data);
130} 353}
131 354
132void vsp1_dl_add(struct vsp1_entity *e, u32 reg, u32 data) 355/**
356 * vsp1_dl_list_add_fragment - Add a fragment to the display list
357 * @dl: The display list
358 * @dlb: The fragment
359 *
360 * Add a display list body as a fragment to a display list. Registers contained
361 * in fragments are processed after registers contained in the main display
362 * list, in the order in which fragments are added.
363 *
364 * Adding a fragment to a display list passes ownership of the fragment to the
365 * list. The caller must not touch the fragment after this call, and must not
366 * free it explicitly with vsp1_dl_fragment_free().
367 *
368 * Fragments are only usable for display lists in header mode. Attempt to
369 * add a fragment to a header-less display list will return an error.
370 */
371int vsp1_dl_list_add_fragment(struct vsp1_dl_list *dl,
372 struct vsp1_dl_body *dlb)
133{ 373{
134 struct vsp1_pipeline *pipe = to_vsp1_pipeline(&e->subdev.entity); 374 /* Multi-body lists are only available in header mode. */
135 struct vsp1_dl *dl = pipe->dl; 375 if (dl->dlm->mode != VSP1_DL_MODE_HEADER)
136 struct vsp1_dl_list *list = dl->lists.write; 376 return -EINVAL;
137 377
138 list->body[list->reg_count].addr = reg; 378 list_add_tail(&dlb->list, &dl->fragments);
139 list->body[list->reg_count].data = data; 379 return 0;
140 list->reg_count++;
141} 380}
142 381
143void vsp1_dl_commit(struct vsp1_dl *dl) 382void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
144{ 383{
145 struct vsp1_device *vsp1 = dl->vsp1; 384 struct vsp1_dl_manager *dlm = dl->dlm;
146 struct vsp1_dl_list *list; 385 struct vsp1_device *vsp1 = dlm->vsp1;
147 unsigned long flags; 386 unsigned long flags;
148 bool update; 387 bool update;
149 388
150 list = dl->lists.write; 389 spin_lock_irqsave(&dlm->lock, flags);
151 dl->lists.write = NULL; 390
391 if (dl->dlm->mode == VSP1_DL_MODE_HEADER) {
392 struct vsp1_dl_header_list *hdr = dl->header->lists;
393 struct vsp1_dl_body *dlb;
394 unsigned int num_lists = 0;
395
396 /* Fill the header with the display list bodies addresses and
397 * sizes. The address of the first body has already been filled
398 * when the display list was allocated.
399 *
400 * In header mode the caller guarantees that the hardware is
401 * idle at this point.
402 */
403 hdr->num_bytes = dl->body0.num_entries
404 * sizeof(*dl->header->lists);
405
406 list_for_each_entry(dlb, &dl->fragments, list) {
407 num_lists++;
408 hdr++;
409
410 hdr->addr = dlb->dma;
411 hdr->num_bytes = dlb->num_entries
412 * sizeof(*dl->header->lists);
413 }
414
415 dl->header->num_lists = num_lists;
416 vsp1_write(vsp1, VI6_DL_HDR_ADDR(dlm->index), dl->dma);
152 417
153 spin_lock_irqsave(&dl->lock, flags); 418 dlm->active = dl;
419 goto done;
420 }
154 421
155 /* Once the UPD bit has been set the hardware can start processing the 422 /* Once the UPD bit has been set the hardware can start processing the
156 * display list at any time and we can't touch the address and size 423 * display list at any time and we can't touch the address and size
@@ -159,8 +426,8 @@ void vsp1_dl_commit(struct vsp1_dl *dl)
159 */ 426 */
160 update = !!(vsp1_read(vsp1, VI6_DL_BODY_SIZE) & VI6_DL_BODY_SIZE_UPD); 427 update = !!(vsp1_read(vsp1, VI6_DL_BODY_SIZE) & VI6_DL_BODY_SIZE_UPD);
161 if (update) { 428 if (update) {
162 vsp1_dl_free_list(dl->lists.pending); 429 __vsp1_dl_list_put(dlm->pending);
163 dl->lists.pending = list; 430 dlm->pending = dl;
164 goto done; 431 goto done;
165 } 432 }
166 433
@@ -168,42 +435,51 @@ void vsp1_dl_commit(struct vsp1_dl *dl)
168 * The UPD bit will be cleared by the device when the display list is 435 * The UPD bit will be cleared by the device when the display list is
169 * processed. 436 * processed.
170 */ 437 */
171 vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), list->dma); 438 vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), dl->body0.dma);
172 vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | 439 vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD |
173 (list->reg_count * 8)); 440 (dl->body0.num_entries * sizeof(*dl->header->lists)));
174 441
175 vsp1_dl_free_list(dl->lists.queued); 442 __vsp1_dl_list_put(dlm->queued);
176 dl->lists.queued = list; 443 dlm->queued = dl;
177 444
178done: 445done:
179 spin_unlock_irqrestore(&dl->lock, flags); 446 spin_unlock_irqrestore(&dlm->lock, flags);
180} 447}
181 448
182/* ----------------------------------------------------------------------------- 449/* -----------------------------------------------------------------------------
183 * Interrupt Handling 450 * Display List Manager
184 */ 451 */
185 452
186void vsp1_dl_irq_display_start(struct vsp1_dl *dl) 453/* Interrupt Handling */
454void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm)
187{ 455{
188 spin_lock(&dl->lock); 456 spin_lock(&dlm->lock);
189 457
190 /* The display start interrupt signals the end of the display list 458 /* The display start interrupt signals the end of the display list
191 * processing by the device. The active display list, if any, won't be 459 * processing by the device. The active display list, if any, won't be
192 * accessed anymore and can be reused. 460 * accessed anymore and can be reused.
193 */ 461 */
194 if (dl->lists.active) { 462 __vsp1_dl_list_put(dlm->active);
195 vsp1_dl_free_list(dl->lists.active); 463 dlm->active = NULL;
196 dl->lists.active = NULL;
197 }
198 464
199 spin_unlock(&dl->lock); 465 spin_unlock(&dlm->lock);
200} 466}
201 467
202void vsp1_dl_irq_frame_end(struct vsp1_dl *dl) 468void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
203{ 469{
204 struct vsp1_device *vsp1 = dl->vsp1; 470 struct vsp1_device *vsp1 = dlm->vsp1;
471
472 spin_lock(&dlm->lock);
473
474 __vsp1_dl_list_put(dlm->active);
475 dlm->active = NULL;
205 476
206 spin_lock(&dl->lock); 477 /* Header mode is used for mem-to-mem pipelines only. We don't need to
478 * perform any operation as there can't be any new display list queued
479 * in that case.
480 */
481 if (dlm->mode == VSP1_DL_MODE_HEADER)
482 goto done;
207 483
208 /* The UPD bit set indicates that the commit operation raced with the 484 /* The UPD bit set indicates that the commit operation raced with the
209 * interrupt and occurred after the frame end event and UPD clear but 485 * interrupt and occurred after the frame end event and UPD clear but
@@ -216,42 +492,39 @@ void vsp1_dl_irq_frame_end(struct vsp1_dl *dl)
216 /* The device starts processing the queued display list right after the 492 /* The device starts processing the queued display list right after the
217 * frame end interrupt. The display list thus becomes active. 493 * frame end interrupt. The display list thus becomes active.
218 */ 494 */
219 if (dl->lists.queued) { 495 if (dlm->queued) {
220 WARN_ON(dl->lists.active); 496 dlm->active = dlm->queued;
221 dl->lists.active = dl->lists.queued; 497 dlm->queued = NULL;
222 dl->lists.queued = NULL;
223 } 498 }
224 499
225 /* Now that the UPD bit has been cleared we can queue the next display 500 /* Now that the UPD bit has been cleared we can queue the next display
226 * list to the hardware if one has been prepared. 501 * list to the hardware if one has been prepared.
227 */ 502 */
228 if (dl->lists.pending) { 503 if (dlm->pending) {
229 struct vsp1_dl_list *list = dl->lists.pending; 504 struct vsp1_dl_list *dl = dlm->pending;
230 505
231 vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), list->dma); 506 vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), dl->body0.dma);
232 vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | 507 vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD |
233 (list->reg_count * 8)); 508 (dl->body0.num_entries *
509 sizeof(*dl->header->lists)));
234 510
235 dl->lists.queued = list; 511 dlm->queued = dl;
236 dl->lists.pending = NULL; 512 dlm->pending = NULL;
237 } 513 }
238 514
239done: 515done:
240 spin_unlock(&dl->lock); 516 spin_unlock(&dlm->lock);
241} 517}
242 518
243/* ----------------------------------------------------------------------------- 519/* Hardware Setup */
244 * Hardware Setup 520void vsp1_dlm_setup(struct vsp1_device *vsp1)
245 */
246
247void vsp1_dl_setup(struct vsp1_device *vsp1)
248{ 521{
249 u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT) 522 u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT)
250 | VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0 523 | VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0
251 | VI6_DL_CTRL_DLE; 524 | VI6_DL_CTRL_DLE;
252 525
253 /* The DRM pipeline operates with header-less display lists in 526 /* The DRM pipeline operates with display lists in Continuous Frame
254 * Continuous Frame Mode. 527 * Mode, all other pipelines use manual start.
255 */ 528 */
256 if (vsp1->drm) 529 if (vsp1->drm)
257 ctrl |= VI6_DL_CTRL_CFM0 | VI6_DL_CTRL_NH0; 530 ctrl |= VI6_DL_CTRL_CFM0 | VI6_DL_CTRL_NH0;
@@ -260,46 +533,64 @@ void vsp1_dl_setup(struct vsp1_device *vsp1)
260 vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS); 533 vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS);
261} 534}
262 535
263/* ----------------------------------------------------------------------------- 536void vsp1_dlm_reset(struct vsp1_dl_manager *dlm)
264 * Initialization and Cleanup 537{
265 */ 538 unsigned long flags;
539
540 spin_lock_irqsave(&dlm->lock, flags);
266 541
267struct vsp1_dl *vsp1_dl_create(struct vsp1_device *vsp1) 542 __vsp1_dl_list_put(dlm->active);
543 __vsp1_dl_list_put(dlm->queued);
544 __vsp1_dl_list_put(dlm->pending);
545
546 spin_unlock_irqrestore(&dlm->lock, flags);
547
548 dlm->active = NULL;
549 dlm->queued = NULL;
550 dlm->pending = NULL;
551}
552
553struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
554 unsigned int index,
555 unsigned int prealloc)
268{ 556{
269 struct vsp1_dl *dl; 557 struct vsp1_dl_manager *dlm;
270 unsigned int i; 558 unsigned int i;
271 559
272 dl = kzalloc(sizeof(*dl), GFP_KERNEL); 560 dlm = devm_kzalloc(vsp1->dev, sizeof(*dlm), GFP_KERNEL);
273 if (!dl) 561 if (!dlm)
274 return NULL; 562 return NULL;
275 563
276 spin_lock_init(&dl->lock); 564 dlm->index = index;
565 dlm->mode = index == 0 && !vsp1->info->uapi
566 ? VSP1_DL_MODE_HEADERLESS : VSP1_DL_MODE_HEADER;
567 dlm->vsp1 = vsp1;
277 568
278 dl->vsp1 = vsp1; 569 spin_lock_init(&dlm->lock);
279 dl->size = VSP1_DL_BODY_SIZE * ARRAY_SIZE(dl->lists.all); 570 INIT_LIST_HEAD(&dlm->free);
280 571
281 dl->mem = dma_alloc_wc(vsp1->dev, dl->size, &dl->dma, 572 for (i = 0; i < prealloc; ++i) {
282 GFP_KERNEL); 573 struct vsp1_dl_list *dl;
283 if (!dl->mem) {
284 kfree(dl);
285 return NULL;
286 }
287 574
288 for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) { 575 dl = vsp1_dl_list_alloc(dlm);
289 struct vsp1_dl_list *list = &dl->lists.all[i]; 576 if (!dl)
577 return NULL;
290 578
291 list->size = VSP1_DL_BODY_SIZE; 579 list_add_tail(&dl->list, &dlm->free);
292 list->reg_count = 0;
293 list->in_use = false;
294 list->dma = dl->dma + VSP1_DL_BODY_SIZE * i;
295 list->body = dl->mem + VSP1_DL_BODY_SIZE * i;
296 } 580 }
297 581
298 return dl; 582 return dlm;
299} 583}
300 584
301void vsp1_dl_destroy(struct vsp1_dl *dl) 585void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm)
302{ 586{
303 dma_free_wc(dl->vsp1->dev, dl->size, dl->mem, dl->dma); 587 struct vsp1_dl_list *dl, *next;
304 kfree(dl); 588
589 if (!dlm)
590 return;
591
592 list_for_each_entry_safe(dl, next, &dlm->free, list) {
593 list_del(&dl->list);
594 vsp1_dl_list_free(dl);
595 }
305} 596}
diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h
index 448c4250e54c..de387cd4d745 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.h
+++ b/drivers/media/platform/vsp1/vsp1_dl.h
@@ -13,30 +13,33 @@
13#ifndef __VSP1_DL_H__ 13#ifndef __VSP1_DL_H__
14#define __VSP1_DL_H__ 14#define __VSP1_DL_H__
15 15
16#include "vsp1_entity.h" 16#include <linux/types.h>
17 17
18struct vsp1_device; 18struct vsp1_device;
19struct vsp1_dl; 19struct vsp1_dl_fragment;
20 20struct vsp1_dl_list;
21struct vsp1_dl *vsp1_dl_create(struct vsp1_device *vsp1); 21struct vsp1_dl_manager;
22void vsp1_dl_destroy(struct vsp1_dl *dl); 22
23 23void vsp1_dlm_setup(struct vsp1_device *vsp1);
24void vsp1_dl_setup(struct vsp1_device *vsp1); 24
25 25struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
26void vsp1_dl_reset(struct vsp1_dl *dl); 26 unsigned int index,
27void vsp1_dl_begin(struct vsp1_dl *dl); 27 unsigned int prealloc);
28void vsp1_dl_add(struct vsp1_entity *e, u32 reg, u32 data); 28void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
29void vsp1_dl_commit(struct vsp1_dl *dl); 29void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
30 30void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm);
31void vsp1_dl_irq_display_start(struct vsp1_dl *dl); 31void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
32void vsp1_dl_irq_frame_end(struct vsp1_dl *dl); 32
33 33struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm);
34static inline void vsp1_dl_mod_write(struct vsp1_entity *e, u32 reg, u32 data) 34void vsp1_dl_list_put(struct vsp1_dl_list *dl);
35{ 35void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data);
36 if (e->vsp1->use_dl) 36void vsp1_dl_list_commit(struct vsp1_dl_list *dl);
37 vsp1_dl_add(e, reg, data); 37
38 else 38struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1,
39 vsp1_write(e->vsp1, reg, data); 39 unsigned int num_entries);
40} 40void vsp1_dl_fragment_free(struct vsp1_dl_body *dlb);
41void vsp1_dl_fragment_write(struct vsp1_dl_body *dlb, u32 reg, u32 data);
42int vsp1_dl_list_add_fragment(struct vsp1_dl_list *dl,
43 struct vsp1_dl_body *dlb);
41 44
42#endif /* __VSP1_DL_H__ */ 45#endif /* __VSP1_DL_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 021fe5778cd1..fc4bbc401e67 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -13,10 +13,10 @@
13 13
14#include <linux/device.h> 14#include <linux/device.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/vsp1.h>
17 16
18#include <media/media-entity.h> 17#include <media/media-entity.h>
19#include <media/v4l2-subdev.h> 18#include <media/v4l2-subdev.h>
19#include <media/vsp1.h>
20 20
21#include "vsp1.h" 21#include "vsp1.h"
22#include "vsp1_bru.h" 22#include "vsp1_bru.h"
@@ -26,18 +26,14 @@
26#include "vsp1_pipe.h" 26#include "vsp1_pipe.h"
27#include "vsp1_rwpf.h" 27#include "vsp1_rwpf.h"
28 28
29
29/* ----------------------------------------------------------------------------- 30/* -----------------------------------------------------------------------------
30 * Runtime Handling 31 * Interrupt Handling
31 */ 32 */
32 33
33static void vsp1_drm_pipeline_frame_end(struct vsp1_pipeline *pipe) 34void vsp1_drm_display_start(struct vsp1_device *vsp1)
34{ 35{
35 unsigned long flags; 36 vsp1_dlm_irq_display_start(vsp1->drm->pipe.output->dlm);
36
37 spin_lock_irqsave(&pipe->irqlock, flags);
38 if (pipe->num_inputs)
39 vsp1_pipeline_run(pipe);
40 spin_unlock_irqrestore(&pipe->irqlock, flags);
41} 37}
42 38
43/* ----------------------------------------------------------------------------- 39/* -----------------------------------------------------------------------------
@@ -97,12 +93,14 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
97 media_entity_pipeline_stop(&pipe->output->entity.subdev.entity); 93 media_entity_pipeline_stop(&pipe->output->entity.subdev.entity);
98 94
99 for (i = 0; i < bru->entity.source_pad; ++i) { 95 for (i = 0; i < bru->entity.source_pad; ++i) {
96 vsp1->drm->inputs[i].enabled = false;
100 bru->inputs[i].rpf = NULL; 97 bru->inputs[i].rpf = NULL;
101 pipe->inputs[i] = NULL; 98 pipe->inputs[i] = NULL;
102 } 99 }
103 100
104 pipe->num_inputs = 0; 101 pipe->num_inputs = 0;
105 102
103 vsp1_dlm_reset(pipe->output->dlm);
106 vsp1_device_put(vsp1); 104 vsp1_device_put(vsp1);
107 105
108 dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__); 106 dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__);
@@ -110,8 +108,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
110 return 0; 108 return 0;
111 } 109 }
112 110
113 vsp1_dl_reset(vsp1->drm->dl);
114
115 /* Configure the format at the BRU sinks and propagate it through the 111 /* Configure the format at the BRU sinks and propagate it through the
116 * pipeline. 112 * pipeline.
117 */ 113 */
@@ -222,16 +218,11 @@ void vsp1_du_atomic_begin(struct device *dev)
222{ 218{
223 struct vsp1_device *vsp1 = dev_get_drvdata(dev); 219 struct vsp1_device *vsp1 = dev_get_drvdata(dev);
224 struct vsp1_pipeline *pipe = &vsp1->drm->pipe; 220 struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
225 unsigned long flags;
226
227 spin_lock_irqsave(&pipe->irqlock, flags);
228 221
229 vsp1->drm->num_inputs = pipe->num_inputs; 222 vsp1->drm->num_inputs = pipe->num_inputs;
230 223
231 spin_unlock_irqrestore(&pipe->irqlock, flags);
232
233 /* Prepare the display list. */ 224 /* Prepare the display list. */
234 vsp1_dl_begin(vsp1->drm->dl); 225 pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
235} 226}
236EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin); 227EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
237 228
@@ -244,10 +235,13 @@ EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
244 * @mem: DMA addresses of the memory buffers (one per plane) 235 * @mem: DMA addresses of the memory buffers (one per plane)
245 * @src: the source crop rectangle for the RPF 236 * @src: the source crop rectangle for the RPF
246 * @dst: the destination compose rectangle for the BRU input 237 * @dst: the destination compose rectangle for the BRU input
238 * @alpha: global alpha value for the input
239 * @zpos: the Z-order position of the input
247 * 240 *
248 * Configure the VSP to perform composition of the image referenced by @mem 241 * Configure the VSP to perform composition of the image referenced by @mem
249 * through RPF @rpf_index, using the @src crop rectangle and the @dst 242 * through RPF @rpf_index, using the @src crop rectangle and the @dst
250 * composition rectangle. The Z-order is fixed with RPF 0 at the bottom. 243 * composition rectangle. The Z-order is configurable with higher @zpos values
244 * displayed on top.
251 * 245 *
252 * Image format as stored in memory is expressed as a V4L2 @pixelformat value. 246 * Image format as stored in memory is expressed as a V4L2 @pixelformat value.
253 * As a special case, setting the pixel format to 0 will disable the RPF. The 247 * As a special case, setting the pixel format to 0 will disable the RPF. The
@@ -265,25 +259,17 @@ EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
265 * 259 *
266 * This function isn't reentrant, the caller needs to serialize calls. 260 * This function isn't reentrant, the caller needs to serialize calls.
267 * 261 *
268 * TODO: Implement Z-order control by decoupling the RPF index from the BRU
269 * input index.
270 *
271 * Return 0 on success or a negative error code on failure. 262 * Return 0 on success or a negative error code on failure.
272 */ 263 */
273int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, 264int vsp1_du_atomic_update_ext(struct device *dev, unsigned int rpf_index,
274 u32 pixelformat, unsigned int pitch, 265 u32 pixelformat, unsigned int pitch,
275 dma_addr_t mem[2], const struct v4l2_rect *src, 266 dma_addr_t mem[2], const struct v4l2_rect *src,
276 const struct v4l2_rect *dst) 267 const struct v4l2_rect *dst, unsigned int alpha,
268 unsigned int zpos)
277{ 269{
278 struct vsp1_device *vsp1 = dev_get_drvdata(dev); 270 struct vsp1_device *vsp1 = dev_get_drvdata(dev);
279 struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
280 const struct vsp1_format_info *fmtinfo; 271 const struct vsp1_format_info *fmtinfo;
281 struct v4l2_subdev_selection sel;
282 struct v4l2_subdev_format format;
283 struct vsp1_rwpf_memory memory;
284 struct vsp1_rwpf *rpf; 272 struct vsp1_rwpf *rpf;
285 unsigned long flags;
286 int ret;
287 273
288 if (rpf_index >= vsp1->info->rpf_count) 274 if (rpf_index >= vsp1->info->rpf_count)
289 return -EINVAL; 275 return -EINVAL;
@@ -294,31 +280,20 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
294 dev_dbg(vsp1->dev, "%s: RPF%u: disable requested\n", __func__, 280 dev_dbg(vsp1->dev, "%s: RPF%u: disable requested\n", __func__,
295 rpf_index); 281 rpf_index);
296 282
297 spin_lock_irqsave(&pipe->irqlock, flags); 283 vsp1->drm->inputs[rpf_index].enabled = false;
298
299 if (pipe->inputs[rpf_index]) {
300 /* Remove the RPF from the pipeline if it was previously
301 * enabled.
302 */
303 vsp1->bru->inputs[rpf_index].rpf = NULL;
304 pipe->inputs[rpf_index] = NULL;
305
306 pipe->num_inputs--;
307 }
308
309 spin_unlock_irqrestore(&pipe->irqlock, flags);
310
311 return 0; 284 return 0;
312 } 285 }
313 286
314 dev_dbg(vsp1->dev, 287 dev_dbg(vsp1->dev,
315 "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad }\n", 288 "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad } zpos %u\n",
316 __func__, rpf_index, 289 __func__, rpf_index,
317 src->left, src->top, src->width, src->height, 290 src->left, src->top, src->width, src->height,
318 dst->left, dst->top, dst->width, dst->height, 291 dst->left, dst->top, dst->width, dst->height,
319 pixelformat, pitch, &mem[0], &mem[1]); 292 pixelformat, pitch, &mem[0], &mem[1], zpos);
320 293
321 /* Set the stride at the RPF input. */ 294 /* Store the format, stride, memory buffer address, crop and compose
295 * rectangles and Z-order position and for the input.
296 */
322 fmtinfo = vsp1_get_format_info(pixelformat); 297 fmtinfo = vsp1_get_format_info(pixelformat);
323 if (!fmtinfo) { 298 if (!fmtinfo) {
324 dev_dbg(vsp1->dev, "Unsupport pixel format %08x for RPF\n", 299 dev_dbg(vsp1->dev, "Unsupport pixel format %08x for RPF\n",
@@ -330,16 +305,40 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
330 rpf->format.num_planes = fmtinfo->planes; 305 rpf->format.num_planes = fmtinfo->planes;
331 rpf->format.plane_fmt[0].bytesperline = pitch; 306 rpf->format.plane_fmt[0].bytesperline = pitch;
332 rpf->format.plane_fmt[1].bytesperline = pitch; 307 rpf->format.plane_fmt[1].bytesperline = pitch;
308 rpf->alpha = alpha;
309
310 rpf->mem.addr[0] = mem[0];
311 rpf->mem.addr[1] = mem[1];
312 rpf->mem.addr[2] = 0;
313
314 vsp1->drm->inputs[rpf_index].crop = *src;
315 vsp1->drm->inputs[rpf_index].compose = *dst;
316 vsp1->drm->inputs[rpf_index].zpos = zpos;
317 vsp1->drm->inputs[rpf_index].enabled = true;
318
319 return 0;
320}
321EXPORT_SYMBOL_GPL(vsp1_du_atomic_update_ext);
322
323static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
324 struct vsp1_rwpf *rpf, unsigned int bru_input)
325{
326 struct v4l2_subdev_selection sel;
327 struct v4l2_subdev_format format;
328 const struct v4l2_rect *crop;
329 int ret;
333 330
334 /* Configure the format on the RPF sink pad and propagate it up to the 331 /* Configure the format on the RPF sink pad and propagate it up to the
335 * BRU sink pad. 332 * BRU sink pad.
336 */ 333 */
334 crop = &vsp1->drm->inputs[rpf->entity.index].crop;
335
337 memset(&format, 0, sizeof(format)); 336 memset(&format, 0, sizeof(format));
338 format.which = V4L2_SUBDEV_FORMAT_ACTIVE; 337 format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
339 format.pad = RWPF_PAD_SINK; 338 format.pad = RWPF_PAD_SINK;
340 format.format.width = src->width + src->left; 339 format.format.width = crop->width + crop->left;
341 format.format.height = src->height + src->top; 340 format.format.height = crop->height + crop->top;
342 format.format.code = fmtinfo->mbus; 341 format.format.code = rpf->fmtinfo->mbus;
343 format.format.field = V4L2_FIELD_NONE; 342 format.format.field = V4L2_FIELD_NONE;
344 343
345 ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, 344 ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL,
@@ -356,7 +355,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
356 sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; 355 sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
357 sel.pad = RWPF_PAD_SINK; 356 sel.pad = RWPF_PAD_SINK;
358 sel.target = V4L2_SEL_TGT_CROP; 357 sel.target = V4L2_SEL_TGT_CROP;
359 sel.r = *src; 358 sel.r = *crop;
360 359
361 ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL, 360 ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL,
362 &sel); 361 &sel);
@@ -391,7 +390,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
391 return ret; 390 return ret;
392 391
393 /* BRU sink, propagate the format from the RPF source. */ 392 /* BRU sink, propagate the format from the RPF source. */
394 format.pad = rpf->entity.index; 393 format.pad = bru_input;
395 394
396 ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_fmt, NULL, 395 ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_fmt, NULL,
397 &format); 396 &format);
@@ -402,9 +401,9 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
402 __func__, format.format.width, format.format.height, 401 __func__, format.format.width, format.format.height,
403 format.format.code, format.pad); 402 format.format.code, format.pad);
404 403
405 sel.pad = rpf->entity.index; 404 sel.pad = bru_input;
406 sel.target = V4L2_SEL_TGT_COMPOSE; 405 sel.target = V4L2_SEL_TGT_COMPOSE;
407 sel.r = *dst; 406 sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
408 407
409 ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_selection, 408 ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_selection,
410 NULL, &sel); 409 NULL, &sel);
@@ -416,33 +415,13 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
416 __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, 415 __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
417 sel.pad); 416 sel.pad);
418 417
419 /* Store the compose rectangle coordinates in the RPF. */
420 rpf->location.left = dst->left;
421 rpf->location.top = dst->top;
422
423 /* Set the memory buffer address. */
424 memory.num_planes = fmtinfo->planes;
425 memory.addr[0] = mem[0];
426 memory.addr[1] = mem[1];
427
428 rpf->ops->set_memory(rpf, &memory);
429
430 spin_lock_irqsave(&pipe->irqlock, flags);
431
432 /* If the RPF was previously stopped set the BRU input to the RPF and
433 * store the RPF in the pipeline inputs array.
434 */
435 if (!pipe->inputs[rpf->entity.index]) {
436 vsp1->bru->inputs[rpf_index].rpf = rpf;
437 pipe->inputs[rpf->entity.index] = rpf;
438 pipe->num_inputs++;
439 }
440
441 spin_unlock_irqrestore(&pipe->irqlock, flags);
442
443 return 0; 418 return 0;
444} 419}
445EXPORT_SYMBOL_GPL(vsp1_du_atomic_update); 420
421static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
422{
423 return vsp1->drm->inputs[rpf->entity.index].zpos;
424}
446 425
447/** 426/**
448 * vsp1_du_atomic_flush - Commit an atomic update 427 * vsp1_du_atomic_flush - Commit an atomic update
@@ -452,51 +431,96 @@ void vsp1_du_atomic_flush(struct device *dev)
452{ 431{
453 struct vsp1_device *vsp1 = dev_get_drvdata(dev); 432 struct vsp1_device *vsp1 = dev_get_drvdata(dev);
454 struct vsp1_pipeline *pipe = &vsp1->drm->pipe; 433 struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
434 struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
455 struct vsp1_entity *entity; 435 struct vsp1_entity *entity;
456 unsigned long flags; 436 unsigned long flags;
457 bool stop = false; 437 unsigned int i;
458 int ret; 438 int ret;
459 439
440 /* Count the number of enabled inputs and sort them by Z-order. */
441 pipe->num_inputs = 0;
442
443 for (i = 0; i < vsp1->info->rpf_count; ++i) {
444 struct vsp1_rwpf *rpf = vsp1->rpf[i];
445 unsigned int j;
446
447 if (!vsp1->drm->inputs[i].enabled) {
448 pipe->inputs[i] = NULL;
449 continue;
450 }
451
452 pipe->inputs[i] = rpf;
453
454 /* Insert the RPF in the sorted RPFs array. */
455 for (j = pipe->num_inputs++; j > 0; --j) {
456 if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
457 break;
458 inputs[j] = inputs[j-1];
459 }
460
461 inputs[j] = rpf;
462 }
463
464 /* Setup the RPF input pipeline for every enabled input. */
465 for (i = 0; i < vsp1->info->num_bru_inputs; ++i) {
466 struct vsp1_rwpf *rpf = inputs[i];
467
468 if (!rpf) {
469 vsp1->bru->inputs[i].rpf = NULL;
470 continue;
471 }
472
473 vsp1->bru->inputs[i].rpf = rpf;
474 rpf->bru_input = i;
475 rpf->entity.sink_pad = i;
476
477 dev_dbg(vsp1->dev, "%s: connecting RPF.%u to BRU:%u\n",
478 __func__, rpf->entity.index, i);
479
480 ret = vsp1_du_setup_rpf_pipe(vsp1, rpf, i);
481 if (ret < 0)
482 dev_err(vsp1->dev,
483 "%s: failed to setup RPF.%u\n",
484 __func__, rpf->entity.index);
485 }
486
487 /* Configure all entities in the pipeline. */
460 list_for_each_entry(entity, &pipe->entities, list_pipe) { 488 list_for_each_entry(entity, &pipe->entities, list_pipe) {
461 /* Disconnect unused RPFs from the pipeline. */ 489 /* Disconnect unused RPFs from the pipeline. */
462 if (entity->type == VSP1_ENTITY_RPF) { 490 if (entity->type == VSP1_ENTITY_RPF) {
463 struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); 491 struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
464 492
465 if (!pipe->inputs[rpf->entity.index]) { 493 if (!pipe->inputs[rpf->entity.index]) {
466 vsp1_mod_write(entity, entity->route->reg, 494 vsp1_dl_list_write(pipe->dl, entity->route->reg,
467 VI6_DPR_NODE_UNUSED); 495 VI6_DPR_NODE_UNUSED);
468 continue; 496 continue;
469 } 497 }
470 } 498 }
471 499
472 vsp1_entity_route_setup(entity); 500 vsp1_entity_route_setup(entity, pipe->dl);
473 501
474 ret = v4l2_subdev_call(&entity->subdev, video, 502 if (entity->ops->configure)
475 s_stream, 1); 503 entity->ops->configure(entity, pipe, pipe->dl);
476 if (ret < 0) {
477 dev_err(vsp1->dev,
478 "DRM pipeline start failure on entity %s\n",
479 entity->subdev.name);
480 return;
481 }
482 }
483 504
484 vsp1_dl_commit(vsp1->drm->dl); 505 /* The memory buffer address must be applied after configuring
506 * the RPF to make sure the crop offset are computed.
507 */
508 if (entity->type == VSP1_ENTITY_RPF)
509 vsp1_rwpf_set_memory(to_rwpf(&entity->subdev),
510 pipe->dl);
511 }
485 512
486 spin_lock_irqsave(&pipe->irqlock, flags); 513 vsp1_dl_list_commit(pipe->dl);
514 pipe->dl = NULL;
487 515
488 /* Start or stop the pipeline if needed. */ 516 /* Start or stop the pipeline if needed. */
489 if (!vsp1->drm->num_inputs && pipe->num_inputs) { 517 if (!vsp1->drm->num_inputs && pipe->num_inputs) {
490 vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0); 518 vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0);
491 vsp1_write(vsp1, VI6_DISP_IRQ_ENB, VI6_DISP_IRQ_ENB_DSTE); 519 vsp1_write(vsp1, VI6_DISP_IRQ_ENB, VI6_DISP_IRQ_ENB_DSTE);
520 spin_lock_irqsave(&pipe->irqlock, flags);
492 vsp1_pipeline_run(pipe); 521 vsp1_pipeline_run(pipe);
522 spin_unlock_irqrestore(&pipe->irqlock, flags);
493 } else if (vsp1->drm->num_inputs && !pipe->num_inputs) { 523 } else if (vsp1->drm->num_inputs && !pipe->num_inputs) {
494 stop = true;
495 }
496
497 spin_unlock_irqrestore(&pipe->irqlock, flags);
498
499 if (stop) {
500 vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0); 524 vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
501 vsp1_pipeline_stop(pipe); 525 vsp1_pipeline_stop(pipe);
502 } 526 }
@@ -562,14 +586,9 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
562 if (!vsp1->drm) 586 if (!vsp1->drm)
563 return -ENOMEM; 587 return -ENOMEM;
564 588
565 vsp1->drm->dl = vsp1_dl_create(vsp1);
566 if (!vsp1->drm->dl)
567 return -ENOMEM;
568
569 pipe = &vsp1->drm->pipe; 589 pipe = &vsp1->drm->pipe;
570 590
571 vsp1_pipeline_init(pipe); 591 vsp1_pipeline_init(pipe);
572 pipe->frame_end = vsp1_drm_pipeline_frame_end;
573 592
574 /* The DRM pipeline is static, add entities manually. */ 593 /* The DRM pipeline is static, add entities manually. */
575 for (i = 0; i < vsp1->info->rpf_count; ++i) { 594 for (i = 0; i < vsp1->info->rpf_count; ++i) {
@@ -586,12 +605,9 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
586 pipe->lif = &vsp1->lif->entity; 605 pipe->lif = &vsp1->lif->entity;
587 pipe->output = vsp1->wpf[0]; 606 pipe->output = vsp1->wpf[0];
588 607
589 pipe->dl = vsp1->drm->dl;
590
591 return 0; 608 return 0;
592} 609}
593 610
594void vsp1_drm_cleanup(struct vsp1_device *vsp1) 611void vsp1_drm_cleanup(struct vsp1_device *vsp1)
595{ 612{
596 vsp1_dl_destroy(vsp1->drm->dl);
597} 613}
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index f68056838319..9e28ab9254ba 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -13,37 +13,32 @@
13#ifndef __VSP1_DRM_H__ 13#ifndef __VSP1_DRM_H__
14#define __VSP1_DRM_H__ 14#define __VSP1_DRM_H__
15 15
16#include "vsp1_pipe.h" 16#include <linux/videodev2.h>
17 17
18struct vsp1_dl; 18#include "vsp1_pipe.h"
19 19
20/** 20/**
21 * vsp1_drm - State for the API exposed to the DRM driver 21 * vsp1_drm - State for the API exposed to the DRM driver
22 * @dl: display list for DRM pipeline operation
23 * @pipe: the VSP1 pipeline used for display 22 * @pipe: the VSP1 pipeline used for display
24 * @num_inputs: number of active pipeline inputs at the beginning of an update 23 * @num_inputs: number of active pipeline inputs at the beginning of an update
25 * @update: the pipeline configuration has been updated 24 * @planes: source crop rectangle, destination compose rectangle and z-order
25 * position for every input
26 */ 26 */
27struct vsp1_drm { 27struct vsp1_drm {
28 struct vsp1_dl *dl;
29 struct vsp1_pipeline pipe; 28 struct vsp1_pipeline pipe;
30 unsigned int num_inputs; 29 unsigned int num_inputs;
31 bool update; 30 struct {
31 bool enabled;
32 struct v4l2_rect crop;
33 struct v4l2_rect compose;
34 unsigned int zpos;
35 } inputs[VSP1_MAX_RPF];
32}; 36};
33 37
34int vsp1_drm_init(struct vsp1_device *vsp1); 38int vsp1_drm_init(struct vsp1_device *vsp1);
35void vsp1_drm_cleanup(struct vsp1_device *vsp1); 39void vsp1_drm_cleanup(struct vsp1_device *vsp1);
36int vsp1_drm_create_links(struct vsp1_device *vsp1); 40int vsp1_drm_create_links(struct vsp1_device *vsp1);
37 41
38int vsp1_du_init(struct device *dev); 42void vsp1_drm_display_start(struct vsp1_device *vsp1);
39int vsp1_du_setup_lif(struct device *dev, unsigned int width,
40 unsigned int height);
41void vsp1_du_atomic_begin(struct device *dev);
42int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
43 u32 pixelformat, unsigned int pitch,
44 dma_addr_t mem[2], const struct v4l2_rect *src,
45 const struct v4l2_rect *dst);
46void vsp1_du_atomic_flush(struct device *dev);
47
48 43
49#endif /* __VSP1_DRM_H__ */ 44#endif /* __VSP1_DRM_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 25750a0e4631..e2d779fac0eb 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -30,6 +30,7 @@
30#include "vsp1_hsit.h" 30#include "vsp1_hsit.h"
31#include "vsp1_lif.h" 31#include "vsp1_lif.h"
32#include "vsp1_lut.h" 32#include "vsp1_lut.h"
33#include "vsp1_pipe.h"
33#include "vsp1_rwpf.h" 34#include "vsp1_rwpf.h"
34#include "vsp1_sru.h" 35#include "vsp1_sru.h"
35#include "vsp1_uds.h" 36#include "vsp1_uds.h"
@@ -49,17 +50,15 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
49 50
50 for (i = 0; i < vsp1->info->wpf_count; ++i) { 51 for (i = 0; i < vsp1->info->wpf_count; ++i) {
51 struct vsp1_rwpf *wpf = vsp1->wpf[i]; 52 struct vsp1_rwpf *wpf = vsp1->wpf[i];
52 struct vsp1_pipeline *pipe;
53 53
54 if (wpf == NULL) 54 if (wpf == NULL)
55 continue; 55 continue;
56 56
57 pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
58 status = vsp1_read(vsp1, VI6_WPF_IRQ_STA(i)); 57 status = vsp1_read(vsp1, VI6_WPF_IRQ_STA(i));
59 vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask); 58 vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask);
60 59
61 if (status & VI6_WFP_IRQ_STA_FRE) { 60 if (status & VI6_WFP_IRQ_STA_FRE) {
62 vsp1_pipeline_frame_end(pipe); 61 vsp1_pipeline_frame_end(wpf->pipe);
63 ret = IRQ_HANDLED; 62 ret = IRQ_HANDLED;
64 } 63 }
65 } 64 }
@@ -68,14 +67,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
68 vsp1_write(vsp1, VI6_DISP_IRQ_STA, ~status & VI6_DISP_IRQ_STA_DST); 67 vsp1_write(vsp1, VI6_DISP_IRQ_STA, ~status & VI6_DISP_IRQ_STA_DST);
69 68
70 if (status & VI6_DISP_IRQ_STA_DST) { 69 if (status & VI6_DISP_IRQ_STA_DST) {
71 struct vsp1_rwpf *wpf = vsp1->wpf[0]; 70 vsp1_drm_display_start(vsp1);
72 struct vsp1_pipeline *pipe;
73
74 if (wpf) {
75 pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
76 vsp1_pipeline_display_start(pipe);
77 }
78
79 ret = IRQ_HANDLED; 71 ret = IRQ_HANDLED;
80 } 72 }
81 73
@@ -387,13 +379,10 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
387 /* Register subdev nodes if the userspace API is enabled or initialize 379 /* Register subdev nodes if the userspace API is enabled or initialize
388 * the DRM pipeline otherwise. 380 * the DRM pipeline otherwise.
389 */ 381 */
390 if (vsp1->info->uapi) { 382 if (vsp1->info->uapi)
391 vsp1->use_dl = false;
392 ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); 383 ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev);
393 } else { 384 else
394 vsp1->use_dl = true;
395 ret = vsp1_drm_init(vsp1); 385 ret = vsp1_drm_init(vsp1);
396 }
397 if (ret < 0) 386 if (ret < 0)
398 goto done; 387 goto done;
399 388
@@ -465,8 +454,7 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
465 vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) | 454 vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
466 (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); 455 (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
467 456
468 if (vsp1->use_dl) 457 vsp1_dlm_setup(vsp1);
469 vsp1_dl_setup(vsp1);
470 458
471 return 0; 459 return 0;
472} 460}
@@ -570,6 +558,7 @@ static const struct dev_pm_ops vsp1_pm_ops = {
570static const struct vsp1_device_info vsp1_device_infos[] = { 558static const struct vsp1_device_info vsp1_device_infos[] = {
571 { 559 {
572 .version = VI6_IP_VERSION_MODEL_VSPS_H2, 560 .version = VI6_IP_VERSION_MODEL_VSPS_H2,
561 .gen = 2,
573 .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU, 562 .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU,
574 .rpf_count = 5, 563 .rpf_count = 5,
575 .uds_count = 3, 564 .uds_count = 3,
@@ -578,6 +567,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
578 .uapi = true, 567 .uapi = true,
579 }, { 568 }, {
580 .version = VI6_IP_VERSION_MODEL_VSPR_H2, 569 .version = VI6_IP_VERSION_MODEL_VSPR_H2,
570 .gen = 2,
581 .features = VSP1_HAS_BRU | VSP1_HAS_SRU, 571 .features = VSP1_HAS_BRU | VSP1_HAS_SRU,
582 .rpf_count = 5, 572 .rpf_count = 5,
583 .uds_count = 1, 573 .uds_count = 1,
@@ -586,6 +576,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
586 .uapi = true, 576 .uapi = true,
587 }, { 577 }, {
588 .version = VI6_IP_VERSION_MODEL_VSPD_GEN2, 578 .version = VI6_IP_VERSION_MODEL_VSPD_GEN2,
579 .gen = 2,
589 .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT, 580 .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT,
590 .rpf_count = 4, 581 .rpf_count = 4,
591 .uds_count = 1, 582 .uds_count = 1,
@@ -594,6 +585,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
594 .uapi = true, 585 .uapi = true,
595 }, { 586 }, {
596 .version = VI6_IP_VERSION_MODEL_VSPS_M2, 587 .version = VI6_IP_VERSION_MODEL_VSPS_M2,
588 .gen = 2,
597 .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU, 589 .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU,
598 .rpf_count = 5, 590 .rpf_count = 5,
599 .uds_count = 3, 591 .uds_count = 3,
@@ -602,6 +594,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
602 .uapi = true, 594 .uapi = true,
603 }, { 595 }, {
604 .version = VI6_IP_VERSION_MODEL_VSPI_GEN3, 596 .version = VI6_IP_VERSION_MODEL_VSPI_GEN3,
597 .gen = 3,
605 .features = VSP1_HAS_LUT | VSP1_HAS_SRU, 598 .features = VSP1_HAS_LUT | VSP1_HAS_SRU,
606 .rpf_count = 1, 599 .rpf_count = 1,
607 .uds_count = 1, 600 .uds_count = 1,
@@ -609,6 +602,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
609 .uapi = true, 602 .uapi = true,
610 }, { 603 }, {
611 .version = VI6_IP_VERSION_MODEL_VSPBD_GEN3, 604 .version = VI6_IP_VERSION_MODEL_VSPBD_GEN3,
605 .gen = 3,
612 .features = VSP1_HAS_BRU, 606 .features = VSP1_HAS_BRU,
613 .rpf_count = 5, 607 .rpf_count = 5,
614 .wpf_count = 1, 608 .wpf_count = 1,
@@ -616,6 +610,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
616 .uapi = true, 610 .uapi = true,
617 }, { 611 }, {
618 .version = VI6_IP_VERSION_MODEL_VSPBC_GEN3, 612 .version = VI6_IP_VERSION_MODEL_VSPBC_GEN3,
613 .gen = 3,
619 .features = VSP1_HAS_BRU | VSP1_HAS_LUT, 614 .features = VSP1_HAS_BRU | VSP1_HAS_LUT,
620 .rpf_count = 5, 615 .rpf_count = 5,
621 .wpf_count = 1, 616 .wpf_count = 1,
@@ -623,7 +618,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
623 .uapi = true, 618 .uapi = true,
624 }, { 619 }, {
625 .version = VI6_IP_VERSION_MODEL_VSPD_GEN3, 620 .version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
626 .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT, 621 .gen = 3,
622 .features = VSP1_HAS_BRU | VSP1_HAS_LIF,
627 .rpf_count = 5, 623 .rpf_count = 5,
628 .wpf_count = 2, 624 .wpf_count = 2,
629 .num_bru_inputs = 5, 625 .num_bru_inputs = 5,
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 20a78fbd3691..3d070bcc6053 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -19,46 +19,11 @@
19#include <media/v4l2-subdev.h> 19#include <media/v4l2-subdev.h>
20 20
21#include "vsp1.h" 21#include "vsp1.h"
22#include "vsp1_dl.h"
22#include "vsp1_entity.h" 23#include "vsp1_entity.h"
23 24
24bool vsp1_entity_is_streaming(struct vsp1_entity *entity) 25void vsp1_entity_route_setup(struct vsp1_entity *source,
25{ 26 struct vsp1_dl_list *dl)
26 unsigned long flags;
27 bool streaming;
28
29 spin_lock_irqsave(&entity->lock, flags);
30 streaming = entity->streaming;
31 spin_unlock_irqrestore(&entity->lock, flags);
32
33 return streaming;
34}
35
36int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming)
37{
38 unsigned long flags;
39 int ret;
40
41 spin_lock_irqsave(&entity->lock, flags);
42 entity->streaming = streaming;
43 spin_unlock_irqrestore(&entity->lock, flags);
44
45 if (!streaming)
46 return 0;
47
48 if (!entity->vsp1->info->uapi || !entity->subdev.ctrl_handler)
49 return 0;
50
51 ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler);
52 if (ret < 0) {
53 spin_lock_irqsave(&entity->lock, flags);
54 entity->streaming = false;
55 spin_unlock_irqrestore(&entity->lock, flags);
56 }
57
58 return ret;
59}
60
61void vsp1_entity_route_setup(struct vsp1_entity *source)
62{ 27{
63 struct vsp1_entity *sink; 28 struct vsp1_entity *sink;
64 29
@@ -66,40 +31,74 @@ void vsp1_entity_route_setup(struct vsp1_entity *source)
66 return; 31 return;
67 32
68 sink = container_of(source->sink, struct vsp1_entity, subdev.entity); 33 sink = container_of(source->sink, struct vsp1_entity, subdev.entity);
69 vsp1_mod_write(source, source->route->reg, 34 vsp1_dl_list_write(dl, source->route->reg,
70 sink->route->inputs[source->sink_pad]); 35 sink->route->inputs[source->sink_pad]);
71} 36}
72 37
73/* ----------------------------------------------------------------------------- 38/* -----------------------------------------------------------------------------
74 * V4L2 Subdevice Operations 39 * V4L2 Subdevice Operations
75 */ 40 */
76 41
77struct v4l2_mbus_framefmt * 42/**
78vsp1_entity_get_pad_format(struct vsp1_entity *entity, 43 * vsp1_entity_get_pad_config - Get the pad configuration for an entity
44 * @entity: the entity
45 * @cfg: the TRY pad configuration
46 * @which: configuration selector (ACTIVE or TRY)
47 *
48 * Return the pad configuration requested by the which argument. The TRY
49 * configuration is passed explicitly to the function through the cfg argument
50 * and simply returned when requested. The ACTIVE configuration comes from the
51 * entity structure.
52 */
53struct v4l2_subdev_pad_config *
54vsp1_entity_get_pad_config(struct vsp1_entity *entity,
79 struct v4l2_subdev_pad_config *cfg, 55 struct v4l2_subdev_pad_config *cfg,
80 unsigned int pad, u32 which) 56 enum v4l2_subdev_format_whence which)
81{ 57{
82 switch (which) { 58 switch (which) {
83 case V4L2_SUBDEV_FORMAT_TRY:
84 return v4l2_subdev_get_try_format(&entity->subdev, cfg, pad);
85 case V4L2_SUBDEV_FORMAT_ACTIVE: 59 case V4L2_SUBDEV_FORMAT_ACTIVE:
86 return &entity->formats[pad]; 60 return entity->config;
61 case V4L2_SUBDEV_FORMAT_TRY:
87 default: 62 default:
88 return NULL; 63 return cfg;
89 } 64 }
90} 65}
91 66
67/**
68 * vsp1_entity_get_pad_format - Get a pad format from storage for an entity
69 * @entity: the entity
70 * @cfg: the configuration storage
71 * @pad: the pad number
72 *
73 * Return the format stored in the given configuration for an entity's pad. The
74 * configuration can be an ACTIVE or TRY configuration.
75 */
76struct v4l2_mbus_framefmt *
77vsp1_entity_get_pad_format(struct vsp1_entity *entity,
78 struct v4l2_subdev_pad_config *cfg,
79 unsigned int pad)
80{
81 return v4l2_subdev_get_try_format(&entity->subdev, cfg, pad);
82}
83
84struct v4l2_rect *
85vsp1_entity_get_pad_compose(struct vsp1_entity *entity,
86 struct v4l2_subdev_pad_config *cfg,
87 unsigned int pad)
88{
89 return v4l2_subdev_get_try_compose(&entity->subdev, cfg, pad);
90}
91
92/* 92/*
93 * vsp1_entity_init_formats - Initialize formats on all pads 93 * vsp1_entity_init_cfg - Initialize formats on all pads
94 * @subdev: V4L2 subdevice 94 * @subdev: V4L2 subdevice
95 * @cfg: V4L2 subdev pad configuration 95 * @cfg: V4L2 subdev pad configuration
96 * 96 *
97 * Initialize all pad formats with default values. If cfg is not NULL, try 97 * Initialize all pad formats with default values in the given pad config. This
98 * formats are initialized on the file handle. Otherwise active formats are 98 * function can be used as a handler for the subdev pad::init_cfg operation.
99 * initialized on the device.
100 */ 99 */
101void vsp1_entity_init_formats(struct v4l2_subdev *subdev, 100int vsp1_entity_init_cfg(struct v4l2_subdev *subdev,
102 struct v4l2_subdev_pad_config *cfg) 101 struct v4l2_subdev_pad_config *cfg)
103{ 102{
104 struct v4l2_subdev_format format; 103 struct v4l2_subdev_format format;
105 unsigned int pad; 104 unsigned int pad;
@@ -113,19 +112,132 @@ void vsp1_entity_init_formats(struct v4l2_subdev *subdev,
113 112
114 v4l2_subdev_call(subdev, pad, set_fmt, cfg, &format); 113 v4l2_subdev_call(subdev, pad, set_fmt, cfg, &format);
115 } 114 }
115
116 return 0;
116} 117}
117 118
118static int vsp1_entity_open(struct v4l2_subdev *subdev, 119/*
119 struct v4l2_subdev_fh *fh) 120 * vsp1_subdev_get_pad_format - Subdev pad get_fmt handler
121 * @subdev: V4L2 subdevice
122 * @cfg: V4L2 subdev pad configuration
123 * @fmt: V4L2 subdev format
124 *
125 * This function implements the subdev get_fmt pad operation. It can be used as
126 * a direct drop-in for the operation handler.
127 */
128int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev,
129 struct v4l2_subdev_pad_config *cfg,
130 struct v4l2_subdev_format *fmt)
120{ 131{
121 vsp1_entity_init_formats(subdev, fh->pad); 132 struct vsp1_entity *entity = to_vsp1_entity(subdev);
133 struct v4l2_subdev_pad_config *config;
134
135 config = vsp1_entity_get_pad_config(entity, cfg, fmt->which);
136 if (!config)
137 return -EINVAL;
138
139 fmt->format = *vsp1_entity_get_pad_format(entity, config, fmt->pad);
122 140
123 return 0; 141 return 0;
124} 142}
125 143
126const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops = { 144/*
127 .open = vsp1_entity_open, 145 * vsp1_subdev_enum_mbus_code - Subdev pad enum_mbus_code handler
128}; 146 * @subdev: V4L2 subdevice
147 * @cfg: V4L2 subdev pad configuration
148 * @code: Media bus code enumeration
149 * @codes: Array of supported media bus codes
150 * @ncodes: Number of supported media bus codes
151 *
152 * This function implements the subdev enum_mbus_code pad operation for entities
153 * that do not support format conversion. It enumerates the given supported
154 * media bus codes on the sink pad and reports a source pad format identical to
155 * the sink pad.
156 */
157int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev,
158 struct v4l2_subdev_pad_config *cfg,
159 struct v4l2_subdev_mbus_code_enum *code,
160 const unsigned int *codes, unsigned int ncodes)
161{
162 struct vsp1_entity *entity = to_vsp1_entity(subdev);
163
164 if (code->pad == 0) {
165 if (code->index >= ncodes)
166 return -EINVAL;
167
168 code->code = codes[code->index];
169 } else {
170 struct v4l2_subdev_pad_config *config;
171 struct v4l2_mbus_framefmt *format;
172
173 /* The entity can't perform format conversion, the sink format
174 * is always identical to the source format.
175 */
176 if (code->index)
177 return -EINVAL;
178
179 config = vsp1_entity_get_pad_config(entity, cfg, code->which);
180 if (!config)
181 return -EINVAL;
182
183 format = vsp1_entity_get_pad_format(entity, config, 0);
184 code->code = format->code;
185 }
186
187 return 0;
188}
189
190/*
191 * vsp1_subdev_enum_frame_size - Subdev pad enum_frame_size handler
192 * @subdev: V4L2 subdevice
193 * @cfg: V4L2 subdev pad configuration
194 * @fse: Frame size enumeration
195 * @min_width: Minimum image width
196 * @min_height: Minimum image height
197 * @max_width: Maximum image width
198 * @max_height: Maximum image height
199 *
200 * This function implements the subdev enum_frame_size pad operation for
201 * entities that do not support scaling or cropping. It reports the given
202 * minimum and maximum frame width and height on the sink pad, and a fixed
203 * source pad size identical to the sink pad.
204 */
205int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev,
206 struct v4l2_subdev_pad_config *cfg,
207 struct v4l2_subdev_frame_size_enum *fse,
208 unsigned int min_width, unsigned int min_height,
209 unsigned int max_width, unsigned int max_height)
210{
211 struct vsp1_entity *entity = to_vsp1_entity(subdev);
212 struct v4l2_subdev_pad_config *config;
213 struct v4l2_mbus_framefmt *format;
214
215 config = vsp1_entity_get_pad_config(entity, cfg, fse->which);
216 if (!config)
217 return -EINVAL;
218
219 format = vsp1_entity_get_pad_format(entity, config, fse->pad);
220
221 if (fse->index || fse->code != format->code)
222 return -EINVAL;
223
224 if (fse->pad == 0) {
225 fse->min_width = min_width;
226 fse->max_width = max_width;
227 fse->min_height = min_height;
228 fse->max_height = max_height;
229 } else {
230 /* The size on the source pad are fixed and always identical to
231 * the size on the sink pad.
232 */
233 fse->min_width = format->width;
234 fse->max_width = format->width;
235 fse->min_height = format->height;
236 fse->max_height = format->height;
237 }
238
239 return 0;
240}
129 241
130/* ----------------------------------------------------------------------------- 242/* -----------------------------------------------------------------------------
131 * Media Operations 243 * Media Operations
@@ -171,11 +283,11 @@ static const struct vsp1_route vsp1_routes[] = {
171 { VSP1_ENTITY_HST, 0, VI6_DPR_HST_ROUTE, { VI6_DPR_NODE_HST, } }, 283 { VSP1_ENTITY_HST, 0, VI6_DPR_HST_ROUTE, { VI6_DPR_NODE_HST, } },
172 { VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, } }, 284 { VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, } },
173 { VSP1_ENTITY_LUT, 0, VI6_DPR_LUT_ROUTE, { VI6_DPR_NODE_LUT, } }, 285 { VSP1_ENTITY_LUT, 0, VI6_DPR_LUT_ROUTE, { VI6_DPR_NODE_LUT, } },
174 { VSP1_ENTITY_RPF, 0, VI6_DPR_RPF_ROUTE(0), { VI6_DPR_NODE_RPF(0), } }, 286 { VSP1_ENTITY_RPF, 0, VI6_DPR_RPF_ROUTE(0), { 0, } },
175 { VSP1_ENTITY_RPF, 1, VI6_DPR_RPF_ROUTE(1), { VI6_DPR_NODE_RPF(1), } }, 287 { VSP1_ENTITY_RPF, 1, VI6_DPR_RPF_ROUTE(1), { 0, } },
176 { VSP1_ENTITY_RPF, 2, VI6_DPR_RPF_ROUTE(2), { VI6_DPR_NODE_RPF(2), } }, 288 { VSP1_ENTITY_RPF, 2, VI6_DPR_RPF_ROUTE(2), { 0, } },
177 { VSP1_ENTITY_RPF, 3, VI6_DPR_RPF_ROUTE(3), { VI6_DPR_NODE_RPF(3), } }, 289 { VSP1_ENTITY_RPF, 3, VI6_DPR_RPF_ROUTE(3), { 0, } },
178 { VSP1_ENTITY_RPF, 4, VI6_DPR_RPF_ROUTE(4), { VI6_DPR_NODE_RPF(4), } }, 290 { VSP1_ENTITY_RPF, 4, VI6_DPR_RPF_ROUTE(4), { 0, } },
179 { VSP1_ENTITY_SRU, 0, VI6_DPR_SRU_ROUTE, { VI6_DPR_NODE_SRU, } }, 291 { VSP1_ENTITY_SRU, 0, VI6_DPR_SRU_ROUTE, { VI6_DPR_NODE_SRU, } },
180 { VSP1_ENTITY_UDS, 0, VI6_DPR_UDS_ROUTE(0), { VI6_DPR_NODE_UDS(0), } }, 292 { VSP1_ENTITY_UDS, 0, VI6_DPR_UDS_ROUTE(0), { VI6_DPR_NODE_UDS(0), } },
181 { VSP1_ENTITY_UDS, 1, VI6_DPR_UDS_ROUTE(1), { VI6_DPR_NODE_UDS(1), } }, 293 { VSP1_ENTITY_UDS, 1, VI6_DPR_UDS_ROUTE(1), { VI6_DPR_NODE_UDS(1), } },
@@ -187,9 +299,12 @@ static const struct vsp1_route vsp1_routes[] = {
187}; 299};
188 300
189int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, 301int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
190 unsigned int num_pads) 302 const char *name, unsigned int num_pads,
303 const struct v4l2_subdev_ops *ops)
191{ 304{
305 struct v4l2_subdev *subdev;
192 unsigned int i; 306 unsigned int i;
307 int ret;
193 308
194 for (i = 0; i < ARRAY_SIZE(vsp1_routes); ++i) { 309 for (i = 0; i < ARRAY_SIZE(vsp1_routes); ++i) {
195 if (vsp1_routes[i].type == entity->type && 310 if (vsp1_routes[i].type == entity->type &&
@@ -202,37 +317,56 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
202 if (i == ARRAY_SIZE(vsp1_routes)) 317 if (i == ARRAY_SIZE(vsp1_routes))
203 return -EINVAL; 318 return -EINVAL;
204 319
205 spin_lock_init(&entity->lock);
206
207 entity->vsp1 = vsp1; 320 entity->vsp1 = vsp1;
208 entity->source_pad = num_pads - 1; 321 entity->source_pad = num_pads - 1;
209 322
210 /* Allocate formats and pads. */ 323 /* Allocate and initialize pads. */
211 entity->formats = devm_kzalloc(vsp1->dev,
212 num_pads * sizeof(*entity->formats),
213 GFP_KERNEL);
214 if (entity->formats == NULL)
215 return -ENOMEM;
216
217 entity->pads = devm_kzalloc(vsp1->dev, num_pads * sizeof(*entity->pads), 324 entity->pads = devm_kzalloc(vsp1->dev, num_pads * sizeof(*entity->pads),
218 GFP_KERNEL); 325 GFP_KERNEL);
219 if (entity->pads == NULL) 326 if (entity->pads == NULL)
220 return -ENOMEM; 327 return -ENOMEM;
221 328
222 /* Initialize pads. */
223 for (i = 0; i < num_pads - 1; ++i) 329 for (i = 0; i < num_pads - 1; ++i)
224 entity->pads[i].flags = MEDIA_PAD_FL_SINK; 330 entity->pads[i].flags = MEDIA_PAD_FL_SINK;
225 331
226 entity->pads[num_pads - 1].flags = MEDIA_PAD_FL_SOURCE; 332 entity->pads[num_pads - 1].flags = MEDIA_PAD_FL_SOURCE;
227 333
228 /* Initialize the media entity. */ 334 /* Initialize the media entity. */
229 return media_entity_pads_init(&entity->subdev.entity, num_pads, 335 ret = media_entity_pads_init(&entity->subdev.entity, num_pads,
230 entity->pads); 336 entity->pads);
337 if (ret < 0)
338 return ret;
339
340 /* Initialize the V4L2 subdev. */
341 subdev = &entity->subdev;
342 v4l2_subdev_init(subdev, ops);
343
344 subdev->entity.ops = &vsp1->media_ops;
345 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
346
347 snprintf(subdev->name, sizeof(subdev->name), "%s %s",
348 dev_name(vsp1->dev), name);
349
350 vsp1_entity_init_cfg(subdev, NULL);
351
352 /* Allocate the pad configuration to store formats and selection
353 * rectangles.
354 */
355 entity->config = v4l2_subdev_alloc_pad_config(&entity->subdev);
356 if (entity->config == NULL) {
357 media_entity_cleanup(&entity->subdev.entity);
358 return -ENOMEM;
359 }
360
361 return 0;
231} 362}
232 363
233void vsp1_entity_destroy(struct vsp1_entity *entity) 364void vsp1_entity_destroy(struct vsp1_entity *entity)
234{ 365{
366 if (entity->ops && entity->ops->destroy)
367 entity->ops->destroy(entity);
235 if (entity->subdev.ctrl_handler) 368 if (entity->subdev.ctrl_handler)
236 v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); 369 v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
370 v4l2_subdev_free_pad_config(entity->config);
237 media_entity_cleanup(&entity->subdev.entity); 371 media_entity_cleanup(&entity->subdev.entity);
238} 372}
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 83570dfde8ec..69eff4e17350 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -19,6 +19,8 @@
19#include <media/v4l2-subdev.h> 19#include <media/v4l2-subdev.h>
20 20
21struct vsp1_device; 21struct vsp1_device;
22struct vsp1_dl_list;
23struct vsp1_pipeline;
22 24
23enum vsp1_entity_type { 25enum vsp1_entity_type {
24 VSP1_ENTITY_BRU, 26 VSP1_ENTITY_BRU,
@@ -53,9 +55,27 @@ struct vsp1_route {
53 unsigned int inputs[VSP1_ENTITY_MAX_INPUTS]; 55 unsigned int inputs[VSP1_ENTITY_MAX_INPUTS];
54}; 56};
55 57
58/**
59 * struct vsp1_entity_operations - Entity operations
60 * @destroy: Destroy the entity.
61 * @set_memory: Setup memory buffer access. This operation applies the settings
62 * stored in the rwpf mem field to the display list. Valid for RPF
63 * and WPF only.
64 * @configure: Setup the hardware based on the entity state (pipeline, formats,
65 * selection rectangles, ...)
66 */
67struct vsp1_entity_operations {
68 void (*destroy)(struct vsp1_entity *);
69 void (*set_memory)(struct vsp1_entity *, struct vsp1_dl_list *dl);
70 void (*configure)(struct vsp1_entity *, struct vsp1_pipeline *,
71 struct vsp1_dl_list *);
72};
73
56struct vsp1_entity { 74struct vsp1_entity {
57 struct vsp1_device *vsp1; 75 struct vsp1_device *vsp1;
58 76
77 const struct vsp1_entity_operations *ops;
78
59 enum vsp1_entity_type type; 79 enum vsp1_entity_type type;
60 unsigned int index; 80 unsigned int index;
61 const struct vsp1_route *route; 81 const struct vsp1_route *route;
@@ -70,10 +90,7 @@ struct vsp1_entity {
70 unsigned int sink_pad; 90 unsigned int sink_pad;
71 91
72 struct v4l2_subdev subdev; 92 struct v4l2_subdev subdev;
73 struct v4l2_mbus_framefmt *formats; 93 struct v4l2_subdev_pad_config *config;
74
75 spinlock_t lock; /* Protects the streaming field */
76 bool streaming;
77}; 94};
78 95
79static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev) 96static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev)
@@ -82,7 +99,8 @@ static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev)
82} 99}
83 100
84int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, 101int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
85 unsigned int num_pads); 102 const char *name, unsigned int num_pads,
103 const struct v4l2_subdev_ops *ops);
86void vsp1_entity_destroy(struct vsp1_entity *entity); 104void vsp1_entity_destroy(struct vsp1_entity *entity);
87 105
88extern const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops; 106extern const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops;
@@ -91,16 +109,35 @@ int vsp1_entity_link_setup(struct media_entity *entity,
91 const struct media_pad *local, 109 const struct media_pad *local,
92 const struct media_pad *remote, u32 flags); 110 const struct media_pad *remote, u32 flags);
93 111
112struct v4l2_subdev_pad_config *
113vsp1_entity_get_pad_config(struct vsp1_entity *entity,
114 struct v4l2_subdev_pad_config *cfg,
115 enum v4l2_subdev_format_whence which);
94struct v4l2_mbus_framefmt * 116struct v4l2_mbus_framefmt *
95vsp1_entity_get_pad_format(struct vsp1_entity *entity, 117vsp1_entity_get_pad_format(struct vsp1_entity *entity,
96 struct v4l2_subdev_pad_config *cfg, 118 struct v4l2_subdev_pad_config *cfg,
97 unsigned int pad, u32 which); 119 unsigned int pad);
98void vsp1_entity_init_formats(struct v4l2_subdev *subdev, 120struct v4l2_rect *
99 struct v4l2_subdev_pad_config *cfg); 121vsp1_entity_get_pad_compose(struct vsp1_entity *entity,
100 122 struct v4l2_subdev_pad_config *cfg,
101bool vsp1_entity_is_streaming(struct vsp1_entity *entity); 123 unsigned int pad);
102int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming); 124int vsp1_entity_init_cfg(struct v4l2_subdev *subdev,
103 125 struct v4l2_subdev_pad_config *cfg);
104void vsp1_entity_route_setup(struct vsp1_entity *source); 126
127void vsp1_entity_route_setup(struct vsp1_entity *source,
128 struct vsp1_dl_list *dl);
129
130int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev,
131 struct v4l2_subdev_pad_config *cfg,
132 struct v4l2_subdev_format *fmt);
133int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev,
134 struct v4l2_subdev_pad_config *cfg,
135 struct v4l2_subdev_mbus_code_enum *code,
136 const unsigned int *codes, unsigned int ncodes);
137int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev,
138 struct v4l2_subdev_pad_config *cfg,
139 struct v4l2_subdev_frame_size_enum *fse,
140 unsigned int min_w, unsigned int min_h,
141 unsigned int max_w, unsigned int max_h);
105 142
106#endif /* __VSP1_ENTITY_H__ */ 143#endif /* __VSP1_ENTITY_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c
index c1087cff31a0..68b8567b374d 100644
--- a/drivers/media/platform/vsp1/vsp1_hsit.c
+++ b/drivers/media/platform/vsp1/vsp1_hsit.c
@@ -17,6 +17,7 @@
17#include <media/v4l2-subdev.h> 17#include <media/v4l2-subdev.h>
18 18
19#include "vsp1.h" 19#include "vsp1.h"
20#include "vsp1_dl.h"
20#include "vsp1_hsit.h" 21#include "vsp1_hsit.h"
21 22
22#define HSIT_MIN_SIZE 4U 23#define HSIT_MIN_SIZE 4U
@@ -26,32 +27,14 @@
26 * Device Access 27 * Device Access
27 */ 28 */
28 29
29static inline void vsp1_hsit_write(struct vsp1_hsit *hsit, u32 reg, u32 data) 30static inline void vsp1_hsit_write(struct vsp1_hsit *hsit,
31 struct vsp1_dl_list *dl, u32 reg, u32 data)
30{ 32{
31 vsp1_write(hsit->entity.vsp1, reg, data); 33 vsp1_dl_list_write(dl, reg, data);
32} 34}
33 35
34/* ----------------------------------------------------------------------------- 36/* -----------------------------------------------------------------------------
35 * V4L2 Subdevice Core Operations 37 * V4L2 Subdevice Operations
36 */
37
38static int hsit_s_stream(struct v4l2_subdev *subdev, int enable)
39{
40 struct vsp1_hsit *hsit = to_hsit(subdev);
41
42 if (!enable)
43 return 0;
44
45 if (hsit->inverse)
46 vsp1_hsit_write(hsit, VI6_HSI_CTRL, VI6_HSI_CTRL_EN);
47 else
48 vsp1_hsit_write(hsit, VI6_HST_CTRL, VI6_HST_CTRL_EN);
49
50 return 0;
51}
52
53/* -----------------------------------------------------------------------------
54 * V4L2 Subdevice Pad Operations
55 */ 38 */
56 39
57static int hsit_enum_mbus_code(struct v4l2_subdev *subdev, 40static int hsit_enum_mbus_code(struct v4l2_subdev *subdev,
@@ -76,43 +59,9 @@ static int hsit_enum_frame_size(struct v4l2_subdev *subdev,
76 struct v4l2_subdev_pad_config *cfg, 59 struct v4l2_subdev_pad_config *cfg,
77 struct v4l2_subdev_frame_size_enum *fse) 60 struct v4l2_subdev_frame_size_enum *fse)
78{ 61{
79 struct vsp1_hsit *hsit = to_hsit(subdev); 62 return vsp1_subdev_enum_frame_size(subdev, cfg, fse, HSIT_MIN_SIZE,
80 struct v4l2_mbus_framefmt *format; 63 HSIT_MIN_SIZE, HSIT_MAX_SIZE,
81 64 HSIT_MAX_SIZE);
82 format = vsp1_entity_get_pad_format(&hsit->entity, cfg, fse->pad,
83 fse->which);
84
85 if (fse->index || fse->code != format->code)
86 return -EINVAL;
87
88 if (fse->pad == HSIT_PAD_SINK) {
89 fse->min_width = HSIT_MIN_SIZE;
90 fse->max_width = HSIT_MAX_SIZE;
91 fse->min_height = HSIT_MIN_SIZE;
92 fse->max_height = HSIT_MAX_SIZE;
93 } else {
94 /* The size on the source pad are fixed and always identical to
95 * the size on the sink pad.
96 */
97 fse->min_width = format->width;
98 fse->max_width = format->width;
99 fse->min_height = format->height;
100 fse->max_height = format->height;
101 }
102
103 return 0;
104}
105
106static int hsit_get_format(struct v4l2_subdev *subdev,
107 struct v4l2_subdev_pad_config *cfg,
108 struct v4l2_subdev_format *fmt)
109{
110 struct vsp1_hsit *hsit = to_hsit(subdev);
111
112 fmt->format = *vsp1_entity_get_pad_format(&hsit->entity, cfg, fmt->pad,
113 fmt->which);
114
115 return 0;
116} 65}
117 66
118static int hsit_set_format(struct v4l2_subdev *subdev, 67static int hsit_set_format(struct v4l2_subdev *subdev,
@@ -120,10 +69,14 @@ static int hsit_set_format(struct v4l2_subdev *subdev,
120 struct v4l2_subdev_format *fmt) 69 struct v4l2_subdev_format *fmt)
121{ 70{
122 struct vsp1_hsit *hsit = to_hsit(subdev); 71 struct vsp1_hsit *hsit = to_hsit(subdev);
72 struct v4l2_subdev_pad_config *config;
123 struct v4l2_mbus_framefmt *format; 73 struct v4l2_mbus_framefmt *format;
124 74
125 format = vsp1_entity_get_pad_format(&hsit->entity, cfg, fmt->pad, 75 config = vsp1_entity_get_pad_config(&hsit->entity, cfg, fmt->which);
126 fmt->which); 76 if (!config)
77 return -EINVAL;
78
79 format = vsp1_entity_get_pad_format(&hsit->entity, config, fmt->pad);
127 80
128 if (fmt->pad == HSIT_PAD_SOURCE) { 81 if (fmt->pad == HSIT_PAD_SOURCE) {
129 /* The HST and HSI output format code and resolution can't be 82 /* The HST and HSI output format code and resolution can't be
@@ -145,8 +98,8 @@ static int hsit_set_format(struct v4l2_subdev *subdev,
145 fmt->format = *format; 98 fmt->format = *format;
146 99
147 /* Propagate the format to the source pad. */ 100 /* Propagate the format to the source pad. */
148 format = vsp1_entity_get_pad_format(&hsit->entity, cfg, HSIT_PAD_SOURCE, 101 format = vsp1_entity_get_pad_format(&hsit->entity, config,
149 fmt->which); 102 HSIT_PAD_SOURCE);
150 *format = fmt->format; 103 *format = fmt->format;
151 format->code = hsit->inverse ? MEDIA_BUS_FMT_ARGB8888_1X32 104 format->code = hsit->inverse ? MEDIA_BUS_FMT_ARGB8888_1X32
152 : MEDIA_BUS_FMT_AHSV8888_1X32; 105 : MEDIA_BUS_FMT_AHSV8888_1X32;
@@ -154,33 +107,44 @@ static int hsit_set_format(struct v4l2_subdev *subdev,
154 return 0; 107 return 0;
155} 108}
156 109
157/* -----------------------------------------------------------------------------
158 * V4L2 Subdevice Operations
159 */
160
161static struct v4l2_subdev_video_ops hsit_video_ops = {
162 .s_stream = hsit_s_stream,
163};
164
165static struct v4l2_subdev_pad_ops hsit_pad_ops = { 110static struct v4l2_subdev_pad_ops hsit_pad_ops = {
111 .init_cfg = vsp1_entity_init_cfg,
166 .enum_mbus_code = hsit_enum_mbus_code, 112 .enum_mbus_code = hsit_enum_mbus_code,
167 .enum_frame_size = hsit_enum_frame_size, 113 .enum_frame_size = hsit_enum_frame_size,
168 .get_fmt = hsit_get_format, 114 .get_fmt = vsp1_subdev_get_pad_format,
169 .set_fmt = hsit_set_format, 115 .set_fmt = hsit_set_format,
170}; 116};
171 117
172static struct v4l2_subdev_ops hsit_ops = { 118static struct v4l2_subdev_ops hsit_ops = {
173 .video = &hsit_video_ops,
174 .pad = &hsit_pad_ops, 119 .pad = &hsit_pad_ops,
175}; 120};
176 121
177/* ----------------------------------------------------------------------------- 122/* -----------------------------------------------------------------------------
123 * VSP1 Entity Operations
124 */
125
126static void hsit_configure(struct vsp1_entity *entity,
127 struct vsp1_pipeline *pipe,
128 struct vsp1_dl_list *dl)
129{
130 struct vsp1_hsit *hsit = to_hsit(&entity->subdev);
131
132 if (hsit->inverse)
133 vsp1_hsit_write(hsit, dl, VI6_HSI_CTRL, VI6_HSI_CTRL_EN);
134 else
135 vsp1_hsit_write(hsit, dl, VI6_HST_CTRL, VI6_HST_CTRL_EN);
136}
137
138static const struct vsp1_entity_operations hsit_entity_ops = {
139 .configure = hsit_configure,
140};
141
142/* -----------------------------------------------------------------------------
178 * Initialization and Cleanup 143 * Initialization and Cleanup
179 */ 144 */
180 145
181struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse) 146struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse)
182{ 147{
183 struct v4l2_subdev *subdev;
184 struct vsp1_hsit *hsit; 148 struct vsp1_hsit *hsit;
185 int ret; 149 int ret;
186 150
@@ -190,27 +154,17 @@ struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse)
190 154
191 hsit->inverse = inverse; 155 hsit->inverse = inverse;
192 156
157 hsit->entity.ops = &hsit_entity_ops;
158
193 if (inverse) 159 if (inverse)
194 hsit->entity.type = VSP1_ENTITY_HSI; 160 hsit->entity.type = VSP1_ENTITY_HSI;
195 else 161 else
196 hsit->entity.type = VSP1_ENTITY_HST; 162 hsit->entity.type = VSP1_ENTITY_HST;
197 163
198 ret = vsp1_entity_init(vsp1, &hsit->entity, 2); 164 ret = vsp1_entity_init(vsp1, &hsit->entity, inverse ? "hsi" : "hst", 2,
165 &hsit_ops);
199 if (ret < 0) 166 if (ret < 0)
200 return ERR_PTR(ret); 167 return ERR_PTR(ret);
201 168
202 /* Initialize the V4L2 subdev. */
203 subdev = &hsit->entity.subdev;
204 v4l2_subdev_init(subdev, &hsit_ops);
205
206 subdev->entity.ops = &vsp1->media_ops;
207 subdev->internal_ops = &vsp1_subdev_internal_ops;
208 snprintf(subdev->name, sizeof(subdev->name), "%s %s",
209 dev_name(vsp1->dev), inverse ? "hsi" : "hst");
210 v4l2_set_subdevdata(subdev, hsit);
211 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
212
213 vsp1_entity_init_formats(subdev, NULL);
214
215 return hsit; 169 return hsit;
216} 170}
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index 433853ce8dbf..0217393f22df 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -17,55 +17,24 @@
17#include <media/v4l2-subdev.h> 17#include <media/v4l2-subdev.h>
18 18
19#include "vsp1.h" 19#include "vsp1.h"
20#include "vsp1_dl.h"
20#include "vsp1_lif.h" 21#include "vsp1_lif.h"
21 22
22#define LIF_MIN_SIZE 2U 23#define LIF_MIN_SIZE 2U
23#define LIF_MAX_SIZE 2048U 24#define LIF_MAX_SIZE 8190U
24 25
25/* ----------------------------------------------------------------------------- 26/* -----------------------------------------------------------------------------
26 * Device Access 27 * Device Access
27 */ 28 */
28 29
29static inline void vsp1_lif_write(struct vsp1_lif *lif, u32 reg, u32 data) 30static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl,
31 u32 reg, u32 data)
30{ 32{
31 vsp1_mod_write(&lif->entity, reg, data); 33 vsp1_dl_list_write(dl, reg, data);
32} 34}
33 35
34/* ----------------------------------------------------------------------------- 36/* -----------------------------------------------------------------------------
35 * V4L2 Subdevice Core Operations 37 * V4L2 Subdevice Operations
36 */
37
38static int lif_s_stream(struct v4l2_subdev *subdev, int enable)
39{
40 const struct v4l2_mbus_framefmt *format;
41 struct vsp1_lif *lif = to_lif(subdev);
42 unsigned int hbth = 1300;
43 unsigned int obth = 400;
44 unsigned int lbth = 200;
45
46 if (!enable) {
47 vsp1_write(lif->entity.vsp1, VI6_LIF_CTRL, 0);
48 return 0;
49 }
50
51 format = &lif->entity.formats[LIF_PAD_SOURCE];
52
53 obth = min(obth, (format->width + 1) / 2 * format->height - 4);
54
55 vsp1_lif_write(lif, VI6_LIF_CSBTH,
56 (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) |
57 (lbth << VI6_LIF_CSBTH_LBTH_SHIFT));
58
59 vsp1_lif_write(lif, VI6_LIF_CTRL,
60 (obth << VI6_LIF_CTRL_OBTH_SHIFT) |
61 (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) |
62 VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN);
63
64 return 0;
65}
66
67/* -----------------------------------------------------------------------------
68 * V4L2 Subdevice Pad Operations
69 */ 38 */
70 39
71static int lif_enum_mbus_code(struct v4l2_subdev *subdev, 40static int lif_enum_mbus_code(struct v4l2_subdev *subdev,
@@ -76,82 +45,38 @@ static int lif_enum_mbus_code(struct v4l2_subdev *subdev,
76 MEDIA_BUS_FMT_ARGB8888_1X32, 45 MEDIA_BUS_FMT_ARGB8888_1X32,
77 MEDIA_BUS_FMT_AYUV8_1X32, 46 MEDIA_BUS_FMT_AYUV8_1X32,
78 }; 47 };
79 struct vsp1_lif *lif = to_lif(subdev);
80 48
81 if (code->pad == LIF_PAD_SINK) { 49 return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
82 if (code->index >= ARRAY_SIZE(codes)) 50 ARRAY_SIZE(codes));
83 return -EINVAL;
84
85 code->code = codes[code->index];
86 } else {
87 struct v4l2_mbus_framefmt *format;
88
89 /* The LIF can't perform format conversion, the sink format is
90 * always identical to the source format.
91 */
92 if (code->index)
93 return -EINVAL;
94
95 format = vsp1_entity_get_pad_format(&lif->entity, cfg,
96 LIF_PAD_SINK, code->which);
97 code->code = format->code;
98 }
99
100 return 0;
101} 51}
102 52
103static int lif_enum_frame_size(struct v4l2_subdev *subdev, 53static int lif_enum_frame_size(struct v4l2_subdev *subdev,
104 struct v4l2_subdev_pad_config *cfg, 54 struct v4l2_subdev_pad_config *cfg,
105 struct v4l2_subdev_frame_size_enum *fse) 55 struct v4l2_subdev_frame_size_enum *fse)
106{ 56{
107 struct vsp1_lif *lif = to_lif(subdev); 57 return vsp1_subdev_enum_frame_size(subdev, cfg, fse, LIF_MIN_SIZE,
108 struct v4l2_mbus_framefmt *format; 58 LIF_MIN_SIZE, LIF_MAX_SIZE,
109 59 LIF_MAX_SIZE);
110 format = vsp1_entity_get_pad_format(&lif->entity, cfg, LIF_PAD_SINK,
111 fse->which);
112
113 if (fse->index || fse->code != format->code)
114 return -EINVAL;
115
116 if (fse->pad == LIF_PAD_SINK) {
117 fse->min_width = LIF_MIN_SIZE;
118 fse->max_width = LIF_MAX_SIZE;
119 fse->min_height = LIF_MIN_SIZE;
120 fse->max_height = LIF_MAX_SIZE;
121 } else {
122 fse->min_width = format->width;
123 fse->max_width = format->width;
124 fse->min_height = format->height;
125 fse->max_height = format->height;
126 }
127
128 return 0;
129} 60}
130 61
131static int lif_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 62static int lif_set_format(struct v4l2_subdev *subdev,
132 struct v4l2_subdev_format *fmt) 63 struct v4l2_subdev_pad_config *cfg,
133{
134 struct vsp1_lif *lif = to_lif(subdev);
135
136 fmt->format = *vsp1_entity_get_pad_format(&lif->entity, cfg, fmt->pad,
137 fmt->which);
138
139 return 0;
140}
141
142static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
143 struct v4l2_subdev_format *fmt) 64 struct v4l2_subdev_format *fmt)
144{ 65{
145 struct vsp1_lif *lif = to_lif(subdev); 66 struct vsp1_lif *lif = to_lif(subdev);
67 struct v4l2_subdev_pad_config *config;
146 struct v4l2_mbus_framefmt *format; 68 struct v4l2_mbus_framefmt *format;
147 69
70 config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which);
71 if (!config)
72 return -EINVAL;
73
148 /* Default to YUV if the requested format is not supported. */ 74 /* Default to YUV if the requested format is not supported. */
149 if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && 75 if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
150 fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) 76 fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
151 fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; 77 fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
152 78
153 format = vsp1_entity_get_pad_format(&lif->entity, cfg, fmt->pad, 79 format = vsp1_entity_get_pad_format(&lif->entity, config, fmt->pad);
154 fmt->which);
155 80
156 if (fmt->pad == LIF_PAD_SOURCE) { 81 if (fmt->pad == LIF_PAD_SOURCE) {
157 /* The LIF source format is always identical to its sink 82 /* The LIF source format is always identical to its sink
@@ -172,40 +97,64 @@ static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con
172 fmt->format = *format; 97 fmt->format = *format;
173 98
174 /* Propagate the format to the source pad. */ 99 /* Propagate the format to the source pad. */
175 format = vsp1_entity_get_pad_format(&lif->entity, cfg, LIF_PAD_SOURCE, 100 format = vsp1_entity_get_pad_format(&lif->entity, config,
176 fmt->which); 101 LIF_PAD_SOURCE);
177 *format = fmt->format; 102 *format = fmt->format;
178 103
179 return 0; 104 return 0;
180} 105}
181 106
182/* -----------------------------------------------------------------------------
183 * V4L2 Subdevice Operations
184 */
185
186static struct v4l2_subdev_video_ops lif_video_ops = {
187 .s_stream = lif_s_stream,
188};
189
190static struct v4l2_subdev_pad_ops lif_pad_ops = { 107static struct v4l2_subdev_pad_ops lif_pad_ops = {
108 .init_cfg = vsp1_entity_init_cfg,
191 .enum_mbus_code = lif_enum_mbus_code, 109 .enum_mbus_code = lif_enum_mbus_code,
192 .enum_frame_size = lif_enum_frame_size, 110 .enum_frame_size = lif_enum_frame_size,
193 .get_fmt = lif_get_format, 111 .get_fmt = vsp1_subdev_get_pad_format,
194 .set_fmt = lif_set_format, 112 .set_fmt = lif_set_format,
195}; 113};
196 114
197static struct v4l2_subdev_ops lif_ops = { 115static struct v4l2_subdev_ops lif_ops = {
198 .video = &lif_video_ops,
199 .pad = &lif_pad_ops, 116 .pad = &lif_pad_ops,
200}; 117};
201 118
202/* ----------------------------------------------------------------------------- 119/* -----------------------------------------------------------------------------
120 * VSP1 Entity Operations
121 */
122
123static void lif_configure(struct vsp1_entity *entity,
124 struct vsp1_pipeline *pipe,
125 struct vsp1_dl_list *dl)
126{
127 const struct v4l2_mbus_framefmt *format;
128 struct vsp1_lif *lif = to_lif(&entity->subdev);
129 unsigned int hbth = 1300;
130 unsigned int obth = 400;
131 unsigned int lbth = 200;
132
133 format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config,
134 LIF_PAD_SOURCE);
135
136 obth = min(obth, (format->width + 1) / 2 * format->height - 4);
137
138 vsp1_lif_write(lif, dl, VI6_LIF_CSBTH,
139 (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) |
140 (lbth << VI6_LIF_CSBTH_LBTH_SHIFT));
141
142 vsp1_lif_write(lif, dl, VI6_LIF_CTRL,
143 (obth << VI6_LIF_CTRL_OBTH_SHIFT) |
144 (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) |
145 VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN);
146}
147
148static const struct vsp1_entity_operations lif_entity_ops = {
149 .configure = lif_configure,
150};
151
152/* -----------------------------------------------------------------------------
203 * Initialization and Cleanup 153 * Initialization and Cleanup
204 */ 154 */
205 155
206struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1) 156struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1)
207{ 157{
208 struct v4l2_subdev *subdev;
209 struct vsp1_lif *lif; 158 struct vsp1_lif *lif;
210 int ret; 159 int ret;
211 160
@@ -213,24 +162,12 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1)
213 if (lif == NULL) 162 if (lif == NULL)
214 return ERR_PTR(-ENOMEM); 163 return ERR_PTR(-ENOMEM);
215 164
165 lif->entity.ops = &lif_entity_ops;
216 lif->entity.type = VSP1_ENTITY_LIF; 166 lif->entity.type = VSP1_ENTITY_LIF;
217 167
218 ret = vsp1_entity_init(vsp1, &lif->entity, 2); 168 ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 2, &lif_ops);
219 if (ret < 0) 169 if (ret < 0)
220 return ERR_PTR(ret); 170 return ERR_PTR(ret);
221 171
222 /* Initialize the V4L2 subdev. */
223 subdev = &lif->entity.subdev;
224 v4l2_subdev_init(subdev, &lif_ops);
225
226 subdev->entity.ops = &vsp1->media_ops;
227 subdev->internal_ops = &vsp1_subdev_internal_ops;
228 snprintf(subdev->name, sizeof(subdev->name), "%s lif",
229 dev_name(vsp1->dev));
230 v4l2_set_subdevdata(subdev, lif);
231 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
232
233 vsp1_entity_init_formats(subdev, NULL);
234
235 return lif; 172 return lif;
236} 173}
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c
index 4b89095e7b5f..aa09e59f0ab8 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.c
+++ b/drivers/media/platform/vsp1/vsp1_lut.c
@@ -18,6 +18,7 @@
18#include <media/v4l2-subdev.h> 18#include <media/v4l2-subdev.h>
19 19
20#include "vsp1.h" 20#include "vsp1.h"
21#include "vsp1_dl.h"
21#include "vsp1_lut.h" 22#include "vsp1_lut.h"
22 23
23#define LUT_MIN_SIZE 4U 24#define LUT_MIN_SIZE 4U
@@ -27,19 +28,35 @@
27 * Device Access 28 * Device Access
28 */ 29 */
29 30
30static inline void vsp1_lut_write(struct vsp1_lut *lut, u32 reg, u32 data) 31static inline void vsp1_lut_write(struct vsp1_lut *lut, struct vsp1_dl_list *dl,
32 u32 reg, u32 data)
31{ 33{
32 vsp1_write(lut->entity.vsp1, reg, data); 34 vsp1_dl_list_write(dl, reg, data);
33} 35}
34 36
35/* ----------------------------------------------------------------------------- 37/* -----------------------------------------------------------------------------
36 * V4L2 Subdevice Core Operations 38 * V4L2 Subdevice Core Operations
37 */ 39 */
38 40
39static void lut_configure(struct vsp1_lut *lut, struct vsp1_lut_config *config) 41static int lut_set_table(struct vsp1_lut *lut, struct vsp1_lut_config *config)
40{ 42{
41 memcpy_toio(lut->entity.vsp1->mmio + VI6_LUT_TABLE, config->lut, 43 struct vsp1_dl_body *dlb;
42 sizeof(config->lut)); 44 unsigned int i;
45
46 dlb = vsp1_dl_fragment_alloc(lut->entity.vsp1, ARRAY_SIZE(config->lut));
47 if (!dlb)
48 return -ENOMEM;
49
50 for (i = 0; i < ARRAY_SIZE(config->lut); ++i)
51 vsp1_dl_fragment_write(dlb, VI6_LUT_TABLE + 4 * i,
52 config->lut[i]);
53
54 mutex_lock(&lut->lock);
55 swap(lut->lut, dlb);
56 mutex_unlock(&lut->lock);
57
58 vsp1_dl_fragment_free(dlb);
59 return 0;
43} 60}
44 61
45static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg) 62static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg)
@@ -48,8 +65,7 @@ static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg)
48 65
49 switch (cmd) { 66 switch (cmd) {
50 case VIDIOC_VSP1_LUT_CONFIG: 67 case VIDIOC_VSP1_LUT_CONFIG:
51 lut_configure(lut, arg); 68 return lut_set_table(lut, arg);
52 return 0;
53 69
54 default: 70 default:
55 return -ENOIOCTLCMD; 71 return -ENOIOCTLCMD;
@@ -57,22 +73,6 @@ static long lut_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg)
57} 73}
58 74
59/* ----------------------------------------------------------------------------- 75/* -----------------------------------------------------------------------------
60 * V4L2 Subdevice Video Operations
61 */
62
63static int lut_s_stream(struct v4l2_subdev *subdev, int enable)
64{
65 struct vsp1_lut *lut = to_lut(subdev);
66
67 if (!enable)
68 return 0;
69
70 vsp1_lut_write(lut, VI6_LUT_CTRL, VI6_LUT_CTRL_EN);
71
72 return 0;
73}
74
75/* -----------------------------------------------------------------------------
76 * V4L2 Subdevice Pad Operations 76 * V4L2 Subdevice Pad Operations
77 */ 77 */
78 78
@@ -85,85 +85,39 @@ static int lut_enum_mbus_code(struct v4l2_subdev *subdev,
85 MEDIA_BUS_FMT_AHSV8888_1X32, 85 MEDIA_BUS_FMT_AHSV8888_1X32,
86 MEDIA_BUS_FMT_AYUV8_1X32, 86 MEDIA_BUS_FMT_AYUV8_1X32,
87 }; 87 };
88 struct vsp1_lut *lut = to_lut(subdev);
89 struct v4l2_mbus_framefmt *format;
90
91 if (code->pad == LUT_PAD_SINK) {
92 if (code->index >= ARRAY_SIZE(codes))
93 return -EINVAL;
94
95 code->code = codes[code->index];
96 } else {
97 /* The LUT can't perform format conversion, the sink format is
98 * always identical to the source format.
99 */
100 if (code->index)
101 return -EINVAL;
102
103 format = vsp1_entity_get_pad_format(&lut->entity, cfg,
104 LUT_PAD_SINK, code->which);
105 code->code = format->code;
106 }
107 88
108 return 0; 89 return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
90 ARRAY_SIZE(codes));
109} 91}
110 92
111static int lut_enum_frame_size(struct v4l2_subdev *subdev, 93static int lut_enum_frame_size(struct v4l2_subdev *subdev,
112 struct v4l2_subdev_pad_config *cfg, 94 struct v4l2_subdev_pad_config *cfg,
113 struct v4l2_subdev_frame_size_enum *fse) 95 struct v4l2_subdev_frame_size_enum *fse)
114{ 96{
115 struct vsp1_lut *lut = to_lut(subdev); 97 return vsp1_subdev_enum_frame_size(subdev, cfg, fse, LUT_MIN_SIZE,
116 struct v4l2_mbus_framefmt *format; 98 LUT_MIN_SIZE, LUT_MAX_SIZE,
117 99 LUT_MAX_SIZE);
118 format = vsp1_entity_get_pad_format(&lut->entity, cfg,
119 fse->pad, fse->which);
120
121 if (fse->index || fse->code != format->code)
122 return -EINVAL;
123
124 if (fse->pad == LUT_PAD_SINK) {
125 fse->min_width = LUT_MIN_SIZE;
126 fse->max_width = LUT_MAX_SIZE;
127 fse->min_height = LUT_MIN_SIZE;
128 fse->max_height = LUT_MAX_SIZE;
129 } else {
130 /* The size on the source pad are fixed and always identical to
131 * the size on the sink pad.
132 */
133 fse->min_width = format->width;
134 fse->max_width = format->width;
135 fse->min_height = format->height;
136 fse->max_height = format->height;
137 }
138
139 return 0;
140}
141
142static int lut_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
143 struct v4l2_subdev_format *fmt)
144{
145 struct vsp1_lut *lut = to_lut(subdev);
146
147 fmt->format = *vsp1_entity_get_pad_format(&lut->entity, cfg, fmt->pad,
148 fmt->which);
149
150 return 0;
151} 100}
152 101
153static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 102static int lut_set_format(struct v4l2_subdev *subdev,
103 struct v4l2_subdev_pad_config *cfg,
154 struct v4l2_subdev_format *fmt) 104 struct v4l2_subdev_format *fmt)
155{ 105{
156 struct vsp1_lut *lut = to_lut(subdev); 106 struct vsp1_lut *lut = to_lut(subdev);
107 struct v4l2_subdev_pad_config *config;
157 struct v4l2_mbus_framefmt *format; 108 struct v4l2_mbus_framefmt *format;
158 109
110 config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which);
111 if (!config)
112 return -EINVAL;
113
159 /* Default to YUV if the requested format is not supported. */ 114 /* Default to YUV if the requested format is not supported. */
160 if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && 115 if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
161 fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 && 116 fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
162 fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) 117 fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
163 fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; 118 fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
164 119
165 format = vsp1_entity_get_pad_format(&lut->entity, cfg, fmt->pad, 120 format = vsp1_entity_get_pad_format(&lut->entity, config, fmt->pad);
166 fmt->which);
167 121
168 if (fmt->pad == LUT_PAD_SOURCE) { 122 if (fmt->pad == LUT_PAD_SOURCE) {
169 /* The LUT output format can't be modified. */ 123 /* The LUT output format can't be modified. */
@@ -171,6 +125,7 @@ static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con
171 return 0; 125 return 0;
172 } 126 }
173 127
128 format->code = fmt->format.code;
174 format->width = clamp_t(unsigned int, fmt->format.width, 129 format->width = clamp_t(unsigned int, fmt->format.width,
175 LUT_MIN_SIZE, LUT_MAX_SIZE); 130 LUT_MIN_SIZE, LUT_MAX_SIZE);
176 format->height = clamp_t(unsigned int, fmt->format.height, 131 format->height = clamp_t(unsigned int, fmt->format.height,
@@ -181,8 +136,8 @@ static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con
181 fmt->format = *format; 136 fmt->format = *format;
182 137
183 /* Propagate the format to the source pad. */ 138 /* Propagate the format to the source pad. */
184 format = vsp1_entity_get_pad_format(&lut->entity, cfg, LUT_PAD_SOURCE, 139 format = vsp1_entity_get_pad_format(&lut->entity, config,
185 fmt->which); 140 LUT_PAD_SOURCE);
186 *format = fmt->format; 141 *format = fmt->format;
187 142
188 return 0; 143 return 0;
@@ -196,30 +151,49 @@ static struct v4l2_subdev_core_ops lut_core_ops = {
196 .ioctl = lut_ioctl, 151 .ioctl = lut_ioctl,
197}; 152};
198 153
199static struct v4l2_subdev_video_ops lut_video_ops = {
200 .s_stream = lut_s_stream,
201};
202
203static struct v4l2_subdev_pad_ops lut_pad_ops = { 154static struct v4l2_subdev_pad_ops lut_pad_ops = {
155 .init_cfg = vsp1_entity_init_cfg,
204 .enum_mbus_code = lut_enum_mbus_code, 156 .enum_mbus_code = lut_enum_mbus_code,
205 .enum_frame_size = lut_enum_frame_size, 157 .enum_frame_size = lut_enum_frame_size,
206 .get_fmt = lut_get_format, 158 .get_fmt = vsp1_subdev_get_pad_format,
207 .set_fmt = lut_set_format, 159 .set_fmt = lut_set_format,
208}; 160};
209 161
210static struct v4l2_subdev_ops lut_ops = { 162static struct v4l2_subdev_ops lut_ops = {
211 .core = &lut_core_ops, 163 .core = &lut_core_ops,
212 .video = &lut_video_ops,
213 .pad = &lut_pad_ops, 164 .pad = &lut_pad_ops,
214}; 165};
215 166
216/* ----------------------------------------------------------------------------- 167/* -----------------------------------------------------------------------------
168 * VSP1 Entity Operations
169 */
170
171static void lut_configure(struct vsp1_entity *entity,
172 struct vsp1_pipeline *pipe,
173 struct vsp1_dl_list *dl)
174{
175 struct vsp1_lut *lut = to_lut(&entity->subdev);
176
177 vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN);
178
179 mutex_lock(&lut->lock);
180 if (lut->lut) {
181 vsp1_dl_list_add_fragment(dl, lut->lut);
182 lut->lut = NULL;
183 }
184 mutex_unlock(&lut->lock);
185}
186
187static const struct vsp1_entity_operations lut_entity_ops = {
188 .configure = lut_configure,
189};
190
191/* -----------------------------------------------------------------------------
217 * Initialization and Cleanup 192 * Initialization and Cleanup
218 */ 193 */
219 194
220struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1) 195struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1)
221{ 196{
222 struct v4l2_subdev *subdev;
223 struct vsp1_lut *lut; 197 struct vsp1_lut *lut;
224 int ret; 198 int ret;
225 199
@@ -227,24 +201,12 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1)
227 if (lut == NULL) 201 if (lut == NULL)
228 return ERR_PTR(-ENOMEM); 202 return ERR_PTR(-ENOMEM);
229 203
204 lut->entity.ops = &lut_entity_ops;
230 lut->entity.type = VSP1_ENTITY_LUT; 205 lut->entity.type = VSP1_ENTITY_LUT;
231 206
232 ret = vsp1_entity_init(vsp1, &lut->entity, 2); 207 ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 2, &lut_ops);
233 if (ret < 0) 208 if (ret < 0)
234 return ERR_PTR(ret); 209 return ERR_PTR(ret);
235 210
236 /* Initialize the V4L2 subdev. */
237 subdev = &lut->entity.subdev;
238 v4l2_subdev_init(subdev, &lut_ops);
239
240 subdev->entity.ops = &vsp1->media_ops;
241 subdev->internal_ops = &vsp1_subdev_internal_ops;
242 snprintf(subdev->name, sizeof(subdev->name), "%s lut",
243 dev_name(vsp1->dev));
244 v4l2_set_subdevdata(subdev, lut);
245 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
246
247 vsp1_entity_init_formats(subdev, NULL);
248
249 return lut; 211 return lut;
250} 212}
diff --git a/drivers/media/platform/vsp1/vsp1_lut.h b/drivers/media/platform/vsp1/vsp1_lut.h
index f92ffb867350..cef874f22b6a 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.h
+++ b/drivers/media/platform/vsp1/vsp1_lut.h
@@ -13,6 +13,8 @@
13#ifndef __VSP1_LUT_H__ 13#ifndef __VSP1_LUT_H__
14#define __VSP1_LUT_H__ 14#define __VSP1_LUT_H__
15 15
16#include <linux/mutex.h>
17
16#include <media/media-entity.h> 18#include <media/media-entity.h>
17#include <media/v4l2-subdev.h> 19#include <media/v4l2-subdev.h>
18 20
@@ -25,7 +27,9 @@ struct vsp1_device;
25 27
26struct vsp1_lut { 28struct vsp1_lut {
27 struct vsp1_entity entity; 29 struct vsp1_entity entity;
28 u32 lut[256]; 30
31 struct mutex lock;
32 struct vsp1_dl_body *lut;
29}; 33};
30 34
31static inline struct vsp1_lut *to_lut(struct v4l2_subdev *subdev) 35static inline struct vsp1_lut *to_lut(struct v4l2_subdev *subdev)
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 6659f06b1643..4f3b4a1d028a 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -43,7 +43,7 @@ static const struct vsp1_format_info vsp1_video_formats[] = {
43 { V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32, 43 { V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
44 VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | 44 VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
45 VI6_RPF_DSWAP_P_WDS, 45 VI6_RPF_DSWAP_P_WDS,
46 1, { 16, 0, 0 }, false, false, 1, 1, true }, 46 1, { 16, 0, 0 }, false, false, 1, 1, false },
47 { V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32, 47 { V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
48 VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | 48 VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
49 VI6_RPF_DSWAP_P_WDS, 49 VI6_RPF_DSWAP_P_WDS,
@@ -172,14 +172,18 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
172 bru->inputs[i].rpf = NULL; 172 bru->inputs[i].rpf = NULL;
173 } 173 }
174 174
175 for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) 175 for (i = 0; i < pipe->num_inputs; ++i) {
176 pipe->inputs[i]->pipe = NULL;
176 pipe->inputs[i] = NULL; 177 pipe->inputs[i] = NULL;
178 }
179
180 pipe->output->pipe = NULL;
181 pipe->output = NULL;
177 182
178 INIT_LIST_HEAD(&pipe->entities); 183 INIT_LIST_HEAD(&pipe->entities);
179 pipe->state = VSP1_PIPELINE_STOPPED; 184 pipe->state = VSP1_PIPELINE_STOPPED;
180 pipe->buffers_ready = 0; 185 pipe->buffers_ready = 0;
181 pipe->num_inputs = 0; 186 pipe->num_inputs = 0;
182 pipe->output = NULL;
183 pipe->bru = NULL; 187 pipe->bru = NULL;
184 pipe->lif = NULL; 188 pipe->lif = NULL;
185 pipe->uds = NULL; 189 pipe->uds = NULL;
@@ -190,11 +194,13 @@ void vsp1_pipeline_init(struct vsp1_pipeline *pipe)
190 mutex_init(&pipe->lock); 194 mutex_init(&pipe->lock);
191 spin_lock_init(&pipe->irqlock); 195 spin_lock_init(&pipe->irqlock);
192 init_waitqueue_head(&pipe->wq); 196 init_waitqueue_head(&pipe->wq);
197 kref_init(&pipe->kref);
193 198
194 INIT_LIST_HEAD(&pipe->entities); 199 INIT_LIST_HEAD(&pipe->entities);
195 pipe->state = VSP1_PIPELINE_STOPPED; 200 pipe->state = VSP1_PIPELINE_STOPPED;
196} 201}
197 202
203/* Must be called with the pipe irqlock held. */
198void vsp1_pipeline_run(struct vsp1_pipeline *pipe) 204void vsp1_pipeline_run(struct vsp1_pipeline *pipe)
199{ 205{
200 struct vsp1_device *vsp1 = pipe->output->entity.vsp1; 206 struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
@@ -226,7 +232,7 @@ int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
226 unsigned long flags; 232 unsigned long flags;
227 int ret; 233 int ret;
228 234
229 if (pipe->dl) { 235 if (pipe->lif) {
230 /* When using display lists in continuous frame mode the only 236 /* When using display lists in continuous frame mode the only
231 * way to stop the pipeline is to reset the hardware. 237 * way to stop the pipeline is to reset the hardware.
232 */ 238 */
@@ -253,10 +259,10 @@ int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
253 if (entity->route && entity->route->reg) 259 if (entity->route && entity->route->reg)
254 vsp1_write(entity->vsp1, entity->route->reg, 260 vsp1_write(entity->vsp1, entity->route->reg,
255 VI6_DPR_NODE_UNUSED); 261 VI6_DPR_NODE_UNUSED);
256
257 v4l2_subdev_call(&entity->subdev, video, s_stream, 0);
258 } 262 }
259 263
264 v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 0);
265
260 return ret; 266 return ret;
261} 267}
262 268
@@ -271,50 +277,15 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
271 return pipe->buffers_ready == mask; 277 return pipe->buffers_ready == mask;
272} 278}
273 279
274void vsp1_pipeline_display_start(struct vsp1_pipeline *pipe)
275{
276 if (pipe->dl)
277 vsp1_dl_irq_display_start(pipe->dl);
278}
279
280void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) 280void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
281{ 281{
282 enum vsp1_pipeline_state state;
283 unsigned long flags;
284
285 if (pipe == NULL) 282 if (pipe == NULL)
286 return; 283 return;
287 284
288 if (pipe->dl) 285 vsp1_dlm_irq_frame_end(pipe->output->dlm);
289 vsp1_dl_irq_frame_end(pipe->dl);
290 286
291 /* Signal frame end to the pipeline handler. */ 287 if (pipe->frame_end)
292 pipe->frame_end(pipe); 288 pipe->frame_end(pipe);
293
294 spin_lock_irqsave(&pipe->irqlock, flags);
295
296 state = pipe->state;
297
298 /* When using display lists in continuous frame mode the pipeline is
299 * automatically restarted by the hardware.
300 */
301 if (!pipe->dl)
302 pipe->state = VSP1_PIPELINE_STOPPED;
303
304 /* If a stop has been requested, mark the pipeline as stopped and
305 * return.
306 */
307 if (state == VSP1_PIPELINE_STOPPING) {
308 wake_up(&pipe->wq);
309 goto done;
310 }
311
312 /* Restart the pipeline if ready. */
313 if (vsp1_pipeline_ready(pipe))
314 vsp1_pipeline_run(pipe);
315
316done:
317 spin_unlock_irqrestore(&pipe->irqlock, flags);
318} 289}
319 290
320/* 291/*
@@ -324,9 +295,13 @@ done:
324 * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha 295 * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha
325 * value. The UDS then outputs a fixed alpha value which needs to be programmed 296 * value. The UDS then outputs a fixed alpha value which needs to be programmed
326 * from the input RPF alpha. 297 * from the input RPF alpha.
298 *
299 * This function can only be called from a subdev s_stream handler as it
300 * requires a valid display list context.
327 */ 301 */
328void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, 302void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
329 struct vsp1_entity *input, 303 struct vsp1_entity *input,
304 struct vsp1_dl_list *dl,
330 unsigned int alpha) 305 unsigned int alpha)
331{ 306{
332 struct vsp1_entity *entity; 307 struct vsp1_entity *entity;
@@ -349,7 +324,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
349 if (entity->type == VSP1_ENTITY_UDS) { 324 if (entity->type == VSP1_ENTITY_UDS) {
350 struct vsp1_uds *uds = to_uds(&entity->subdev); 325 struct vsp1_uds *uds = to_uds(&entity->subdev);
351 326
352 vsp1_uds_set_alpha(uds, alpha); 327 vsp1_uds_set_alpha(uds, dl, alpha);
353 break; 328 break;
354 } 329 }
355 330
@@ -375,7 +350,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
375 if (wpf == NULL) 350 if (wpf == NULL)
376 continue; 351 continue;
377 352
378 pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); 353 pipe = wpf->pipe;
379 if (pipe == NULL) 354 if (pipe == NULL)
380 continue; 355 continue;
381 356
@@ -392,7 +367,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
392 if (wpf == NULL) 367 if (wpf == NULL)
393 continue; 368 continue;
394 369
395 pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); 370 pipe = wpf->pipe;
396 if (pipe == NULL) 371 if (pipe == NULL)
397 continue; 372 continue;
398 373
@@ -416,7 +391,7 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
416 if (wpf == NULL) 391 if (wpf == NULL)
417 continue; 392 continue;
418 393
419 pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity); 394 pipe = wpf->pipe;
420 if (pipe == NULL) 395 if (pipe == NULL)
421 continue; 396 continue;
422 397
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index b2f3a8a896c9..7b56113511dd 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -13,13 +13,14 @@
13#ifndef __VSP1_PIPE_H__ 13#ifndef __VSP1_PIPE_H__
14#define __VSP1_PIPE_H__ 14#define __VSP1_PIPE_H__
15 15
16#include <linux/kref.h>
16#include <linux/list.h> 17#include <linux/list.h>
17#include <linux/spinlock.h> 18#include <linux/spinlock.h>
18#include <linux/wait.h> 19#include <linux/wait.h>
19 20
20#include <media/media-entity.h> 21#include <media/media-entity.h>
21 22
22struct vsp1_dl; 23struct vsp1_dl_list;
23struct vsp1_rwpf; 24struct vsp1_rwpf;
24 25
25/* 26/*
@@ -63,7 +64,7 @@ enum vsp1_pipeline_state {
63 * @wq: work queue to wait for state change completion 64 * @wq: work queue to wait for state change completion
64 * @frame_end: frame end interrupt handler 65 * @frame_end: frame end interrupt handler
65 * @lock: protects the pipeline use count and stream count 66 * @lock: protects the pipeline use count and stream count
66 * @use_count: number of video nodes using the pipeline 67 * @kref: pipeline reference count
67 * @stream_count: number of streaming video nodes 68 * @stream_count: number of streaming video nodes
68 * @buffers_ready: bitmask of RPFs and WPFs with at least one buffer available 69 * @buffers_ready: bitmask of RPFs and WPFs with at least one buffer available
69 * @num_inputs: number of RPFs 70 * @num_inputs: number of RPFs
@@ -86,7 +87,7 @@ struct vsp1_pipeline {
86 void (*frame_end)(struct vsp1_pipeline *pipe); 87 void (*frame_end)(struct vsp1_pipeline *pipe);
87 88
88 struct mutex lock; 89 struct mutex lock;
89 unsigned int use_count; 90 struct kref kref;
90 unsigned int stream_count; 91 unsigned int stream_count;
91 unsigned int buffers_ready; 92 unsigned int buffers_ready;
92 93
@@ -100,17 +101,9 @@ struct vsp1_pipeline {
100 101
101 struct list_head entities; 102 struct list_head entities;
102 103
103 struct vsp1_dl *dl; 104 struct vsp1_dl_list *dl;
104}; 105};
105 106
106static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
107{
108 if (likely(e->pipe))
109 return container_of(e->pipe, struct vsp1_pipeline, pipe);
110 else
111 return NULL;
112}
113
114void vsp1_pipeline_reset(struct vsp1_pipeline *pipe); 107void vsp1_pipeline_reset(struct vsp1_pipeline *pipe);
115void vsp1_pipeline_init(struct vsp1_pipeline *pipe); 108void vsp1_pipeline_init(struct vsp1_pipeline *pipe);
116 109
@@ -119,11 +112,11 @@ bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe);
119int vsp1_pipeline_stop(struct vsp1_pipeline *pipe); 112int vsp1_pipeline_stop(struct vsp1_pipeline *pipe);
120bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe); 113bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe);
121 114
122void vsp1_pipeline_display_start(struct vsp1_pipeline *pipe);
123void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe); 115void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe);
124 116
125void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe, 117void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
126 struct vsp1_entity *input, 118 struct vsp1_entity *input,
119 struct vsp1_dl_list *dl,
127 unsigned int alpha); 120 unsigned int alpha);
128 121
129void vsp1_pipelines_suspend(struct vsp1_device *vsp1); 122void vsp1_pipelines_suspend(struct vsp1_device *vsp1);
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 069216f0eb44..927b5fb94c48 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -217,6 +217,16 @@
217#define VI6_RPF_SRCM_ADDR_C1 0x0344 217#define VI6_RPF_SRCM_ADDR_C1 0x0344
218#define VI6_RPF_SRCM_ADDR_AI 0x0348 218#define VI6_RPF_SRCM_ADDR_AI 0x0348
219 219
220#define VI6_RPF_MULT_ALPHA 0x036c
221#define VI6_RPF_MULT_ALPHA_A_MMD_NONE (0 << 12)
222#define VI6_RPF_MULT_ALPHA_A_MMD_RATIO (1 << 12)
223#define VI6_RPF_MULT_ALPHA_P_MMD_NONE (0 << 8)
224#define VI6_RPF_MULT_ALPHA_P_MMD_RATIO (1 << 8)
225#define VI6_RPF_MULT_ALPHA_P_MMD_IMAGE (2 << 8)
226#define VI6_RPF_MULT_ALPHA_P_MMD_BOTH (3 << 8)
227#define VI6_RPF_MULT_ALPHA_RATIO_MASK (0xff < 0)
228#define VI6_RPF_MULT_ALPHA_RATIO_SHIFT 0
229
220/* ----------------------------------------------------------------------------- 230/* -----------------------------------------------------------------------------
221 * WPF Control Registers 231 * WPF Control Registers
222 */ 232 */
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 5bc1d1574a43..49168db3f529 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -16,6 +16,8 @@
16#include <media/v4l2-subdev.h> 16#include <media/v4l2-subdev.h>
17 17
18#include "vsp1.h" 18#include "vsp1.h"
19#include "vsp1_dl.h"
20#include "vsp1_pipe.h"
19#include "vsp1_rwpf.h" 21#include "vsp1_rwpf.h"
20#include "vsp1_video.h" 22#include "vsp1_video.h"
21 23
@@ -26,64 +28,50 @@
26 * Device Access 28 * Device Access
27 */ 29 */
28 30
29static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data) 31static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf,
32 struct vsp1_dl_list *dl, u32 reg, u32 data)
30{ 33{
31 vsp1_mod_write(&rpf->entity, reg + rpf->entity.index * VI6_RPF_OFFSET, 34 vsp1_dl_list_write(dl, reg + rpf->entity.index * VI6_RPF_OFFSET, data);
32 data);
33} 35}
34 36
35/* ----------------------------------------------------------------------------- 37/* -----------------------------------------------------------------------------
36 * Controls 38 * V4L2 Subdevice Operations
37 */ 39 */
38 40
39static int rpf_s_ctrl(struct v4l2_ctrl *ctrl) 41static struct v4l2_subdev_ops rpf_ops = {
40{ 42 .pad = &vsp1_rwpf_pad_ops,
41 struct vsp1_rwpf *rpf =
42 container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
43 struct vsp1_pipeline *pipe;
44
45 if (!vsp1_entity_is_streaming(&rpf->entity))
46 return 0;
47
48 switch (ctrl->id) {
49 case V4L2_CID_ALPHA_COMPONENT:
50 vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
51 ctrl->val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
52
53 pipe = to_vsp1_pipeline(&rpf->entity.subdev.entity);
54 vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, ctrl->val);
55 break;
56 }
57
58 return 0;
59}
60
61static const struct v4l2_ctrl_ops rpf_ctrl_ops = {
62 .s_ctrl = rpf_s_ctrl,
63}; 43};
64 44
65/* ----------------------------------------------------------------------------- 45/* -----------------------------------------------------------------------------
66 * V4L2 Subdevice Core Operations 46 * VSP1 Entity Operations
67 */ 47 */
68 48
69static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) 49static void rpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl)
50{
51 struct vsp1_rwpf *rpf = entity_to_rwpf(entity);
52
53 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y,
54 rpf->mem.addr[0] + rpf->offsets[0]);
55 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0,
56 rpf->mem.addr[1] + rpf->offsets[1]);
57 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1,
58 rpf->mem.addr[2] + rpf->offsets[1]);
59}
60
61static void rpf_configure(struct vsp1_entity *entity,
62 struct vsp1_pipeline *pipe,
63 struct vsp1_dl_list *dl)
70{ 64{
71 struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); 65 struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
72 struct vsp1_rwpf *rpf = to_rwpf(subdev);
73 struct vsp1_device *vsp1 = rpf->entity.vsp1;
74 const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; 66 const struct vsp1_format_info *fmtinfo = rpf->fmtinfo;
75 const struct v4l2_pix_format_mplane *format = &rpf->format; 67 const struct v4l2_pix_format_mplane *format = &rpf->format;
76 const struct v4l2_rect *crop = &rpf->crop; 68 const struct v4l2_mbus_framefmt *source_format;
69 const struct v4l2_mbus_framefmt *sink_format;
70 const struct v4l2_rect *crop;
71 unsigned int left = 0;
72 unsigned int top = 0;
77 u32 pstride; 73 u32 pstride;
78 u32 infmt; 74 u32 infmt;
79 int ret;
80
81 ret = vsp1_entity_set_streaming(&rpf->entity, enable);
82 if (ret < 0)
83 return ret;
84
85 if (!enable)
86 return 0;
87 75
88 /* Source size, stride and crop offsets. 76 /* Source size, stride and crop offsets.
89 * 77 *
@@ -91,10 +79,12 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
91 * left corner in the plane buffer. Only two offsets are needed, as 79 * left corner in the plane buffer. Only two offsets are needed, as
92 * planes 2 and 3 always have identical strides. 80 * planes 2 and 3 always have identical strides.
93 */ 81 */
94 vsp1_rpf_write(rpf, VI6_RPF_SRC_BSIZE, 82 crop = vsp1_rwpf_get_crop(rpf, rpf->entity.config);
83
84 vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE,
95 (crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | 85 (crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) |
96 (crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); 86 (crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT));
97 vsp1_rpf_write(rpf, VI6_RPF_SRC_ESIZE, 87 vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE,
98 (crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) | 88 (crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) |
99 (crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT)); 89 (crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT));
100 90
@@ -103,26 +93,25 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
103 pstride = format->plane_fmt[0].bytesperline 93 pstride = format->plane_fmt[0].bytesperline
104 << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT; 94 << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT;
105 95
106 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y,
107 rpf->buf_addr[0] + rpf->offsets[0]);
108
109 if (format->num_planes > 1) { 96 if (format->num_planes > 1) {
110 rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline 97 rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline
111 + crop->left * fmtinfo->bpp[1] / 8; 98 + crop->left * fmtinfo->bpp[1] / 8;
112 pstride |= format->plane_fmt[1].bytesperline 99 pstride |= format->plane_fmt[1].bytesperline
113 << VI6_RPF_SRCM_PSTRIDE_C_SHIFT; 100 << VI6_RPF_SRCM_PSTRIDE_C_SHIFT;
114 101 } else {
115 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, 102 rpf->offsets[1] = 0;
116 rpf->buf_addr[1] + rpf->offsets[1]);
117
118 if (format->num_planes > 2)
119 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1,
120 rpf->buf_addr[2] + rpf->offsets[1]);
121 } 103 }
122 104
123 vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); 105 vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_PSTRIDE, pstride);
124 106
125 /* Format */ 107 /* Format */
108 sink_format = vsp1_entity_get_pad_format(&rpf->entity,
109 rpf->entity.config,
110 RWPF_PAD_SINK);
111 source_format = vsp1_entity_get_pad_format(&rpf->entity,
112 rpf->entity.config,
113 RWPF_PAD_SOURCE);
114
126 infmt = VI6_RPF_INFMT_CIPM 115 infmt = VI6_RPF_INFMT_CIPM
127 | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT); 116 | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT);
128 117
@@ -131,88 +120,98 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
131 if (fmtinfo->swap_uv) 120 if (fmtinfo->swap_uv)
132 infmt |= VI6_RPF_INFMT_SPUVS; 121 infmt |= VI6_RPF_INFMT_SPUVS;
133 122
134 if (rpf->entity.formats[RWPF_PAD_SINK].code != 123 if (sink_format->code != source_format->code)
135 rpf->entity.formats[RWPF_PAD_SOURCE].code)
136 infmt |= VI6_RPF_INFMT_CSC; 124 infmt |= VI6_RPF_INFMT_CSC;
137 125
138 vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt); 126 vsp1_rpf_write(rpf, dl, VI6_RPF_INFMT, infmt);
139 vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap); 127 vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap);
140 128
141 /* Output location */ 129 /* Output location */
142 vsp1_rpf_write(rpf, VI6_RPF_LOC, 130 if (pipe->bru) {
143 (rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) | 131 const struct v4l2_rect *compose;
144 (rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT)); 132
133 compose = vsp1_entity_get_pad_compose(pipe->bru,
134 pipe->bru->config,
135 rpf->bru_input);
136 left = compose->left;
137 top = compose->top;
138 }
145 139
146 /* Use the alpha channel (extended to 8 bits) when available or an 140 vsp1_rpf_write(rpf, dl, VI6_RPF_LOC,
147 * alpha value set through the V4L2_CID_ALPHA_COMPONENT control 141 (left << VI6_RPF_LOC_HCOORD_SHIFT) |
148 * otherwise. Disable color keying. 142 (top << VI6_RPF_LOC_VCOORD_SHIFT));
143
144 /* On Gen2 use the alpha channel (extended to 8 bits) when available or
145 * a fixed alpha value set through the V4L2_CID_ALPHA_COMPONENT control
146 * otherwise.
147 *
148 * The Gen3 RPF has extended alpha capability and can both multiply the
149 * alpha channel by a fixed global alpha value, and multiply the pixel
150 * components to convert the input to premultiplied alpha.
151 *
152 * As alpha premultiplication is available in the BRU for both Gen2 and
153 * Gen3 we handle it there and use the Gen3 alpha multiplier for global
154 * alpha multiplication only. This however prevents conversion to
155 * premultiplied alpha if no BRU is present in the pipeline. If that use
156 * case turns out to be useful we will revisit the implementation (for
157 * Gen3 only).
158 *
159 * We enable alpha multiplication on Gen3 using the fixed alpha value
160 * set through the V4L2_CID_ALPHA_COMPONENT control when the input
161 * contains an alpha channel. On Gen2 the global alpha is ignored in
162 * that case.
163 *
164 * In all cases, disable color keying.
149 */ 165 */
150 vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT | 166 vsp1_rpf_write(rpf, dl, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT |
151 (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED 167 (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
152 : VI6_RPF_ALPH_SEL_ASEL_FIXED)); 168 : VI6_RPF_ALPH_SEL_ASEL_FIXED));
153 169
154 if (vsp1->info->uapi) 170 vsp1_rpf_write(rpf, dl, VI6_RPF_VRTCOL_SET,
155 mutex_lock(rpf->ctrls.lock); 171 rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
156 vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, 172
157 rpf->alpha->cur.val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); 173 if (entity->vsp1->info->gen == 3) {
158 vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, rpf->alpha->cur.val); 174 u32 mult;
159 if (vsp1->info->uapi) 175
160 mutex_unlock(rpf->ctrls.lock); 176 if (fmtinfo->alpha) {
161 177 /* When the input contains an alpha channel enable the
162 vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); 178 * alpha multiplier. If the input is premultiplied we
163 vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); 179 * need to multiply both the alpha channel and the pixel
164 180 * components by the global alpha value to keep them
165 return 0; 181 * premultiplied. Otherwise multiply the alpha channel
166} 182 * only.
167 183 */
168/* ----------------------------------------------------------------------------- 184 bool premultiplied = format->flags
169 * V4L2 Subdevice Operations 185 & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
170 */ 186
171 187 mult = VI6_RPF_MULT_ALPHA_A_MMD_RATIO
172static struct v4l2_subdev_video_ops rpf_video_ops = { 188 | (premultiplied ?
173 .s_stream = rpf_s_stream, 189 VI6_RPF_MULT_ALPHA_P_MMD_RATIO :
174}; 190 VI6_RPF_MULT_ALPHA_P_MMD_NONE)
175 191 | (rpf->alpha << VI6_RPF_MULT_ALPHA_RATIO_SHIFT);
176static struct v4l2_subdev_pad_ops rpf_pad_ops = { 192 } else {
177 .enum_mbus_code = vsp1_rwpf_enum_mbus_code, 193 /* When the input doesn't contain an alpha channel the
178 .enum_frame_size = vsp1_rwpf_enum_frame_size, 194 * global alpha value is applied in the unpacking unit,
179 .get_fmt = vsp1_rwpf_get_format, 195 * the alpha multiplier isn't needed and must be
180 .set_fmt = vsp1_rwpf_set_format, 196 * disabled.
181 .get_selection = vsp1_rwpf_get_selection, 197 */
182 .set_selection = vsp1_rwpf_set_selection, 198 mult = VI6_RPF_MULT_ALPHA_A_MMD_NONE
183}; 199 | VI6_RPF_MULT_ALPHA_P_MMD_NONE;
200 }
201
202 vsp1_rpf_write(rpf, dl, VI6_RPF_MULT_ALPHA, mult);
203 }
184 204
185static struct v4l2_subdev_ops rpf_ops = { 205 vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, dl, rpf->alpha);
186 .video = &rpf_video_ops,
187 .pad = &rpf_pad_ops,
188};
189 206
190/* ----------------------------------------------------------------------------- 207 vsp1_rpf_write(rpf, dl, VI6_RPF_MSK_CTRL, 0);
191 * Video Device Operations 208 vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, 0);
192 */
193 209
194static void rpf_set_memory(struct vsp1_rwpf *rpf, struct vsp1_rwpf_memory *mem)
195{
196 unsigned int i;
197
198 for (i = 0; i < 3; ++i)
199 rpf->buf_addr[i] = mem->addr[i];
200
201 if (!vsp1_entity_is_streaming(&rpf->entity))
202 return;
203
204 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y,
205 mem->addr[0] + rpf->offsets[0]);
206 if (mem->num_planes > 1)
207 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0,
208 mem->addr[1] + rpf->offsets[1]);
209 if (mem->num_planes > 2)
210 vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1,
211 mem->addr[2] + rpf->offsets[1]);
212} 210}
213 211
214static const struct vsp1_rwpf_operations rpf_vdev_ops = { 212static const struct vsp1_entity_operations rpf_entity_ops = {
215 .set_memory = rpf_set_memory, 213 .set_memory = rpf_set_memory,
214 .configure = rpf_configure,
216}; 215};
217 216
218/* ----------------------------------------------------------------------------- 217/* -----------------------------------------------------------------------------
@@ -221,51 +220,31 @@ static const struct vsp1_rwpf_operations rpf_vdev_ops = {
221 220
222struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) 221struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
223{ 222{
224 struct v4l2_subdev *subdev;
225 struct vsp1_rwpf *rpf; 223 struct vsp1_rwpf *rpf;
224 char name[6];
226 int ret; 225 int ret;
227 226
228 rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL); 227 rpf = devm_kzalloc(vsp1->dev, sizeof(*rpf), GFP_KERNEL);
229 if (rpf == NULL) 228 if (rpf == NULL)
230 return ERR_PTR(-ENOMEM); 229 return ERR_PTR(-ENOMEM);
231 230
232 rpf->ops = &rpf_vdev_ops;
233
234 rpf->max_width = RPF_MAX_WIDTH; 231 rpf->max_width = RPF_MAX_WIDTH;
235 rpf->max_height = RPF_MAX_HEIGHT; 232 rpf->max_height = RPF_MAX_HEIGHT;
236 233
234 rpf->entity.ops = &rpf_entity_ops;
237 rpf->entity.type = VSP1_ENTITY_RPF; 235 rpf->entity.type = VSP1_ENTITY_RPF;
238 rpf->entity.index = index; 236 rpf->entity.index = index;
239 237
240 ret = vsp1_entity_init(vsp1, &rpf->entity, 2); 238 sprintf(name, "rpf.%u", index);
239 ret = vsp1_entity_init(vsp1, &rpf->entity, name, 2, &rpf_ops);
241 if (ret < 0) 240 if (ret < 0)
242 return ERR_PTR(ret); 241 return ERR_PTR(ret);
243 242
244 /* Initialize the V4L2 subdev. */
245 subdev = &rpf->entity.subdev;
246 v4l2_subdev_init(subdev, &rpf_ops);
247
248 subdev->entity.ops = &vsp1->media_ops;
249 subdev->internal_ops = &vsp1_subdev_internal_ops;
250 snprintf(subdev->name, sizeof(subdev->name), "%s rpf.%u",
251 dev_name(vsp1->dev), index);
252 v4l2_set_subdevdata(subdev, rpf);
253 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
254
255 vsp1_entity_init_formats(subdev, NULL);
256
257 /* Initialize the control handler. */ 243 /* Initialize the control handler. */
258 v4l2_ctrl_handler_init(&rpf->ctrls, 1); 244 ret = vsp1_rwpf_init_ctrls(rpf);
259 rpf->alpha = v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, 245 if (ret < 0) {
260 V4L2_CID_ALPHA_COMPONENT,
261 0, 255, 1, 255);
262
263 rpf->entity.subdev.ctrl_handler = &rpf->ctrls;
264
265 if (rpf->ctrls.error) {
266 dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n", 246 dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n",
267 index); 247 index);
268 ret = rpf->ctrls.error;
269 goto error; 248 goto error;
270 } 249 }
271 250
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c
index 9688c219b30e..3b6e032e7806 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.c
@@ -20,13 +20,20 @@
20#define RWPF_MIN_WIDTH 1 20#define RWPF_MIN_WIDTH 1
21#define RWPF_MIN_HEIGHT 1 21#define RWPF_MIN_HEIGHT 1
22 22
23struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf,
24 struct v4l2_subdev_pad_config *config)
25{
26 return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, config,
27 RWPF_PAD_SINK);
28}
29
23/* ----------------------------------------------------------------------------- 30/* -----------------------------------------------------------------------------
24 * V4L2 Subdevice Pad Operations 31 * V4L2 Subdevice Pad Operations
25 */ 32 */
26 33
27int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, 34static int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev,
28 struct v4l2_subdev_pad_config *cfg, 35 struct v4l2_subdev_pad_config *cfg,
29 struct v4l2_subdev_mbus_code_enum *code) 36 struct v4l2_subdev_mbus_code_enum *code)
30{ 37{
31 static const unsigned int codes[] = { 38 static const unsigned int codes[] = {
32 MEDIA_BUS_FMT_ARGB8888_1X32, 39 MEDIA_BUS_FMT_ARGB8888_1X32,
@@ -41,75 +48,36 @@ int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev,
41 return 0; 48 return 0;
42} 49}
43 50
44int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, 51static int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev,
45 struct v4l2_subdev_pad_config *cfg, 52 struct v4l2_subdev_pad_config *cfg,
46 struct v4l2_subdev_frame_size_enum *fse) 53 struct v4l2_subdev_frame_size_enum *fse)
47{
48 struct vsp1_rwpf *rwpf = to_rwpf(subdev);
49 struct v4l2_mbus_framefmt *format;
50
51 format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, fse->pad,
52 fse->which);
53
54 if (fse->index || fse->code != format->code)
55 return -EINVAL;
56
57 if (fse->pad == RWPF_PAD_SINK) {
58 fse->min_width = RWPF_MIN_WIDTH;
59 fse->max_width = rwpf->max_width;
60 fse->min_height = RWPF_MIN_HEIGHT;
61 fse->max_height = rwpf->max_height;
62 } else {
63 /* The size on the source pad are fixed and always identical to
64 * the size on the sink pad.
65 */
66 fse->min_width = format->width;
67 fse->max_width = format->width;
68 fse->min_height = format->height;
69 fse->max_height = format->height;
70 }
71
72 return 0;
73}
74
75static struct v4l2_rect *
76vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_pad_config *cfg, u32 which)
77{
78 switch (which) {
79 case V4L2_SUBDEV_FORMAT_TRY:
80 return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, cfg, RWPF_PAD_SINK);
81 case V4L2_SUBDEV_FORMAT_ACTIVE:
82 return &rwpf->crop;
83 default:
84 return NULL;
85 }
86}
87
88int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
89 struct v4l2_subdev_format *fmt)
90{ 54{
91 struct vsp1_rwpf *rwpf = to_rwpf(subdev); 55 struct vsp1_rwpf *rwpf = to_rwpf(subdev);
92 56
93 fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, cfg, fmt->pad, 57 return vsp1_subdev_enum_frame_size(subdev, cfg, fse, RWPF_MIN_WIDTH,
94 fmt->which); 58 RWPF_MIN_HEIGHT, rwpf->max_width,
95 59 rwpf->max_height);
96 return 0;
97} 60}
98 61
99int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 62static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
100 struct v4l2_subdev_format *fmt) 63 struct v4l2_subdev_pad_config *cfg,
64 struct v4l2_subdev_format *fmt)
101{ 65{
102 struct vsp1_rwpf *rwpf = to_rwpf(subdev); 66 struct vsp1_rwpf *rwpf = to_rwpf(subdev);
67 struct v4l2_subdev_pad_config *config;
103 struct v4l2_mbus_framefmt *format; 68 struct v4l2_mbus_framefmt *format;
104 struct v4l2_rect *crop; 69 struct v4l2_rect *crop;
105 70
71 config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, fmt->which);
72 if (!config)
73 return -EINVAL;
74
106 /* Default to YUV if the requested format is not supported. */ 75 /* Default to YUV if the requested format is not supported. */
107 if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && 76 if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
108 fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) 77 fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
109 fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; 78 fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
110 79
111 format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, fmt->pad, 80 format = vsp1_entity_get_pad_format(&rwpf->entity, config, fmt->pad);
112 fmt->which);
113 81
114 if (fmt->pad == RWPF_PAD_SOURCE) { 82 if (fmt->pad == RWPF_PAD_SOURCE) {
115 /* The RWPF performs format conversion but can't scale, only the 83 /* The RWPF performs format conversion but can't scale, only the
@@ -131,39 +99,44 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_conf
131 fmt->format = *format; 99 fmt->format = *format;
132 100
133 /* Update the sink crop rectangle. */ 101 /* Update the sink crop rectangle. */
134 crop = vsp1_rwpf_get_crop(rwpf, cfg, fmt->which); 102 crop = vsp1_rwpf_get_crop(rwpf, config);
135 crop->left = 0; 103 crop->left = 0;
136 crop->top = 0; 104 crop->top = 0;
137 crop->width = fmt->format.width; 105 crop->width = fmt->format.width;
138 crop->height = fmt->format.height; 106 crop->height = fmt->format.height;
139 107
140 /* Propagate the format to the source pad. */ 108 /* Propagate the format to the source pad. */
141 format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SOURCE, 109 format = vsp1_entity_get_pad_format(&rwpf->entity, config,
142 fmt->which); 110 RWPF_PAD_SOURCE);
143 *format = fmt->format; 111 *format = fmt->format;
144 112
145 return 0; 113 return 0;
146} 114}
147 115
148int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, 116static int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev,
149 struct v4l2_subdev_pad_config *cfg, 117 struct v4l2_subdev_pad_config *cfg,
150 struct v4l2_subdev_selection *sel) 118 struct v4l2_subdev_selection *sel)
151{ 119{
152 struct vsp1_rwpf *rwpf = to_rwpf(subdev); 120 struct vsp1_rwpf *rwpf = to_rwpf(subdev);
121 struct v4l2_subdev_pad_config *config;
153 struct v4l2_mbus_framefmt *format; 122 struct v4l2_mbus_framefmt *format;
154 123
155 /* Cropping is implemented on the sink pad. */ 124 /* Cropping is implemented on the sink pad. */
156 if (sel->pad != RWPF_PAD_SINK) 125 if (sel->pad != RWPF_PAD_SINK)
157 return -EINVAL; 126 return -EINVAL;
158 127
128 config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, sel->which);
129 if (!config)
130 return -EINVAL;
131
159 switch (sel->target) { 132 switch (sel->target) {
160 case V4L2_SEL_TGT_CROP: 133 case V4L2_SEL_TGT_CROP:
161 sel->r = *vsp1_rwpf_get_crop(rwpf, cfg, sel->which); 134 sel->r = *vsp1_rwpf_get_crop(rwpf, config);
162 break; 135 break;
163 136
164 case V4L2_SEL_TGT_CROP_BOUNDS: 137 case V4L2_SEL_TGT_CROP_BOUNDS:
165 format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, 138 format = vsp1_entity_get_pad_format(&rwpf->entity, config,
166 RWPF_PAD_SINK, sel->which); 139 RWPF_PAD_SINK);
167 sel->r.left = 0; 140 sel->r.left = 0;
168 sel->r.top = 0; 141 sel->r.top = 0;
169 sel->r.width = format->width; 142 sel->r.width = format->width;
@@ -177,11 +150,12 @@ int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev,
177 return 0; 150 return 0;
178} 151}
179 152
180int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, 153static int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev,
181 struct v4l2_subdev_pad_config *cfg, 154 struct v4l2_subdev_pad_config *cfg,
182 struct v4l2_subdev_selection *sel) 155 struct v4l2_subdev_selection *sel)
183{ 156{
184 struct vsp1_rwpf *rwpf = to_rwpf(subdev); 157 struct vsp1_rwpf *rwpf = to_rwpf(subdev);
158 struct v4l2_subdev_pad_config *config;
185 struct v4l2_mbus_framefmt *format; 159 struct v4l2_mbus_framefmt *format;
186 struct v4l2_rect *crop; 160 struct v4l2_rect *crop;
187 161
@@ -192,11 +166,15 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev,
192 if (sel->target != V4L2_SEL_TGT_CROP) 166 if (sel->target != V4L2_SEL_TGT_CROP)
193 return -EINVAL; 167 return -EINVAL;
194 168
169 config = vsp1_entity_get_pad_config(&rwpf->entity, cfg, sel->which);
170 if (!config)
171 return -EINVAL;
172
195 /* Make sure the crop rectangle is entirely contained in the image. The 173 /* Make sure the crop rectangle is entirely contained in the image. The
196 * WPF top and left offsets are limited to 255. 174 * WPF top and left offsets are limited to 255.
197 */ 175 */
198 format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SINK, 176 format = vsp1_entity_get_pad_format(&rwpf->entity, config,
199 sel->which); 177 RWPF_PAD_SINK);
200 178
201 /* Restrict the crop rectangle coordinates to multiples of 2 to avoid 179 /* Restrict the crop rectangle coordinates to multiples of 2 to avoid
202 * shifting the color plane. 180 * shifting the color plane.
@@ -219,14 +197,59 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev,
219 sel->r.height = min_t(unsigned int, sel->r.height, 197 sel->r.height = min_t(unsigned int, sel->r.height,
220 format->height - sel->r.top); 198 format->height - sel->r.top);
221 199
222 crop = vsp1_rwpf_get_crop(rwpf, cfg, sel->which); 200 crop = vsp1_rwpf_get_crop(rwpf, config);
223 *crop = sel->r; 201 *crop = sel->r;
224 202
225 /* Propagate the format to the source pad. */ 203 /* Propagate the format to the source pad. */
226 format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SOURCE, 204 format = vsp1_entity_get_pad_format(&rwpf->entity, config,
227 sel->which); 205 RWPF_PAD_SOURCE);
228 format->width = crop->width; 206 format->width = crop->width;
229 format->height = crop->height; 207 format->height = crop->height;
230 208
231 return 0; 209 return 0;
232} 210}
211
212const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops = {
213 .init_cfg = vsp1_entity_init_cfg,
214 .enum_mbus_code = vsp1_rwpf_enum_mbus_code,
215 .enum_frame_size = vsp1_rwpf_enum_frame_size,
216 .get_fmt = vsp1_subdev_get_pad_format,
217 .set_fmt = vsp1_rwpf_set_format,
218 .get_selection = vsp1_rwpf_get_selection,
219 .set_selection = vsp1_rwpf_set_selection,
220};
221
222/* -----------------------------------------------------------------------------
223 * Controls
224 */
225
226static int vsp1_rwpf_s_ctrl(struct v4l2_ctrl *ctrl)
227{
228 struct vsp1_rwpf *rwpf =
229 container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
230
231 switch (ctrl->id) {
232 case V4L2_CID_ALPHA_COMPONENT:
233 rwpf->alpha = ctrl->val;
234 break;
235 }
236
237 return 0;
238}
239
240static const struct v4l2_ctrl_ops vsp1_rwpf_ctrl_ops = {
241 .s_ctrl = vsp1_rwpf_s_ctrl,
242};
243
244int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf)
245{
246 rwpf->alpha = 255;
247
248 v4l2_ctrl_handler_init(&rwpf->ctrls, 1);
249 v4l2_ctrl_new_std(&rwpf->ctrls, &vsp1_rwpf_ctrl_ops,
250 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
251
252 rwpf->entity.subdev.ctrl_handler = &rwpf->ctrls;
253
254 return rwpf->ctrls.error;
255}
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index 8e8235682ada..9ff7c78f239e 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -24,42 +24,35 @@
24#define RWPF_PAD_SOURCE 1 24#define RWPF_PAD_SOURCE 1
25 25
26struct v4l2_ctrl; 26struct v4l2_ctrl;
27struct vsp1_dl_manager;
28struct vsp1_pipeline;
27struct vsp1_rwpf; 29struct vsp1_rwpf;
28struct vsp1_video; 30struct vsp1_video;
29 31
30struct vsp1_rwpf_memory { 32struct vsp1_rwpf_memory {
31 unsigned int num_planes;
32 dma_addr_t addr[3]; 33 dma_addr_t addr[3];
33 unsigned int length[3];
34};
35
36struct vsp1_rwpf_operations {
37 void (*set_memory)(struct vsp1_rwpf *rwpf,
38 struct vsp1_rwpf_memory *mem);
39}; 34};
40 35
41struct vsp1_rwpf { 36struct vsp1_rwpf {
42 struct vsp1_entity entity; 37 struct vsp1_entity entity;
43 struct v4l2_ctrl_handler ctrls; 38 struct v4l2_ctrl_handler ctrls;
44 struct v4l2_ctrl *alpha;
45 39
40 struct vsp1_pipeline *pipe;
46 struct vsp1_video *video; 41 struct vsp1_video *video;
47 42
48 const struct vsp1_rwpf_operations *ops;
49
50 unsigned int max_width; 43 unsigned int max_width;
51 unsigned int max_height; 44 unsigned int max_height;
52 45
53 struct v4l2_pix_format_mplane format; 46 struct v4l2_pix_format_mplane format;
54 const struct vsp1_format_info *fmtinfo; 47 const struct vsp1_format_info *fmtinfo;
55 struct { 48 unsigned int bru_input;
56 unsigned int left; 49
57 unsigned int top; 50 unsigned int alpha;
58 } location;
59 struct v4l2_rect crop;
60 51
61 unsigned int offsets[2]; 52 unsigned int offsets[2];
62 dma_addr_t buf_addr[3]; 53 struct vsp1_rwpf_memory mem;
54
55 struct vsp1_dl_manager *dlm;
63}; 56};
64 57
65static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) 58static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev)
@@ -67,24 +60,31 @@ static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev)
67 return container_of(subdev, struct vsp1_rwpf, entity.subdev); 60 return container_of(subdev, struct vsp1_rwpf, entity.subdev);
68} 61}
69 62
63static inline struct vsp1_rwpf *entity_to_rwpf(struct vsp1_entity *entity)
64{
65 return container_of(entity, struct vsp1_rwpf, entity);
66}
67
70struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); 68struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index);
71struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); 69struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index);
72 70
73int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, 71int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf);
74 struct v4l2_subdev_pad_config *cfg, 72
75 struct v4l2_subdev_mbus_code_enum *code); 73extern const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops;
76int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, 74
77 struct v4l2_subdev_pad_config *cfg, 75struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf,
78 struct v4l2_subdev_frame_size_enum *fse); 76 struct v4l2_subdev_pad_config *config);
79int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 77/**
80 struct v4l2_subdev_format *fmt); 78 * vsp1_rwpf_set_memory - Configure DMA addresses for a [RW]PF
81int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 79 * @rwpf: the [RW]PF instance
82 struct v4l2_subdev_format *fmt); 80 * @dl: the display list
83int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, 81 *
84 struct v4l2_subdev_pad_config *cfg, 82 * This function applies the cached memory buffer address to the display list.
85 struct v4l2_subdev_selection *sel); 83 */
86int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, 84static inline void vsp1_rwpf_set_memory(struct vsp1_rwpf *rwpf,
87 struct v4l2_subdev_pad_config *cfg, 85 struct vsp1_dl_list *dl)
88 struct v4l2_subdev_selection *sel); 86{
87 rwpf->entity.ops->set_memory(&rwpf->entity, dl);
88}
89 89
90#endif /* __VSP1_RWPF_H__ */ 90#endif /* __VSP1_RWPF_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index cc09efbfb24f..97ef997ae735 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -17,6 +17,7 @@
17#include <media/v4l2-subdev.h> 17#include <media/v4l2-subdev.h>
18 18
19#include "vsp1.h" 19#include "vsp1.h"
20#include "vsp1_dl.h"
20#include "vsp1_sru.h" 21#include "vsp1_sru.h"
21 22
22#define SRU_MIN_SIZE 4U 23#define SRU_MIN_SIZE 4U
@@ -26,14 +27,10 @@
26 * Device Access 27 * Device Access
27 */ 28 */
28 29
29static inline u32 vsp1_sru_read(struct vsp1_sru *sru, u32 reg) 30static inline void vsp1_sru_write(struct vsp1_sru *sru, struct vsp1_dl_list *dl,
31 u32 reg, u32 data)
30{ 32{
31 return vsp1_read(sru->entity.vsp1, reg); 33 vsp1_dl_list_write(dl, reg, data);
32}
33
34static inline void vsp1_sru_write(struct vsp1_sru *sru, u32 reg, u32 data)
35{
36 vsp1_write(sru->entity.vsp1, reg, data);
37} 34}
38 35
39/* ----------------------------------------------------------------------------- 36/* -----------------------------------------------------------------------------
@@ -82,20 +79,10 @@ static int sru_s_ctrl(struct v4l2_ctrl *ctrl)
82{ 79{
83 struct vsp1_sru *sru = 80 struct vsp1_sru *sru =
84 container_of(ctrl->handler, struct vsp1_sru, ctrls); 81 container_of(ctrl->handler, struct vsp1_sru, ctrls);
85 const struct vsp1_sru_param *param;
86 u32 value;
87 82
88 switch (ctrl->id) { 83 switch (ctrl->id) {
89 case V4L2_CID_VSP1_SRU_INTENSITY: 84 case V4L2_CID_VSP1_SRU_INTENSITY:
90 param = &vsp1_sru_params[ctrl->val - 1]; 85 sru->intensity = ctrl->val;
91
92 value = vsp1_sru_read(sru, VI6_SRU_CTRL0);
93 value &= ~(VI6_SRU_CTRL0_PARAM0_MASK |
94 VI6_SRU_CTRL0_PARAM1_MASK);
95 value |= param->ctrl0;
96 vsp1_sru_write(sru, VI6_SRU_CTRL0, value);
97
98 vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2);
99 break; 86 break;
100 } 87 }
101 88
@@ -118,54 +105,7 @@ static const struct v4l2_ctrl_config sru_intensity_control = {
118}; 105};
119 106
120/* ----------------------------------------------------------------------------- 107/* -----------------------------------------------------------------------------
121 * V4L2 Subdevice Core Operations 108 * V4L2 Subdevice Operations
122 */
123
124static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
125{
126 struct vsp1_sru *sru = to_sru(subdev);
127 struct v4l2_mbus_framefmt *input;
128 struct v4l2_mbus_framefmt *output;
129 u32 ctrl0;
130 int ret;
131
132 ret = vsp1_entity_set_streaming(&sru->entity, enable);
133 if (ret < 0)
134 return ret;
135
136 if (!enable)
137 return 0;
138
139 input = &sru->entity.formats[SRU_PAD_SINK];
140 output = &sru->entity.formats[SRU_PAD_SOURCE];
141
142 if (input->code == MEDIA_BUS_FMT_ARGB8888_1X32)
143 ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3
144 | VI6_SRU_CTRL0_PARAM4;
145 else
146 ctrl0 = VI6_SRU_CTRL0_PARAM3;
147
148 if (input->width != output->width)
149 ctrl0 |= VI6_SRU_CTRL0_MODE_UPSCALE;
150
151 /* Take the control handler lock to ensure that the CTRL0 value won't be
152 * changed behind our back by a set control operation.
153 */
154 if (sru->entity.vsp1->info->uapi)
155 mutex_lock(sru->ctrls.lock);
156 ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0)
157 & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK);
158 vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0);
159 if (sru->entity.vsp1->info->uapi)
160 mutex_unlock(sru->ctrls.lock);
161
162 vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5);
163
164 return 0;
165}
166
167/* -----------------------------------------------------------------------------
168 * V4L2 Subdevice Pad Operations
169 */ 109 */
170 110
171static int sru_enum_mbus_code(struct v4l2_subdev *subdev, 111static int sru_enum_mbus_code(struct v4l2_subdev *subdev,
@@ -176,27 +116,9 @@ static int sru_enum_mbus_code(struct v4l2_subdev *subdev,
176 MEDIA_BUS_FMT_ARGB8888_1X32, 116 MEDIA_BUS_FMT_ARGB8888_1X32,
177 MEDIA_BUS_FMT_AYUV8_1X32, 117 MEDIA_BUS_FMT_AYUV8_1X32,
178 }; 118 };
179 struct vsp1_sru *sru = to_sru(subdev);
180 struct v4l2_mbus_framefmt *format;
181
182 if (code->pad == SRU_PAD_SINK) {
183 if (code->index >= ARRAY_SIZE(codes))
184 return -EINVAL;
185
186 code->code = codes[code->index];
187 } else {
188 /* The SRU can't perform format conversion, the sink format is
189 * always identical to the source format.
190 */
191 if (code->index)
192 return -EINVAL;
193 119
194 format = vsp1_entity_get_pad_format(&sru->entity, cfg, 120 return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
195 SRU_PAD_SINK, code->which); 121 ARRAY_SIZE(codes));
196 code->code = format->code;
197 }
198
199 return 0;
200} 122}
201 123
202static int sru_enum_frame_size(struct v4l2_subdev *subdev, 124static int sru_enum_frame_size(struct v4l2_subdev *subdev,
@@ -204,10 +126,14 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev,
204 struct v4l2_subdev_frame_size_enum *fse) 126 struct v4l2_subdev_frame_size_enum *fse)
205{ 127{
206 struct vsp1_sru *sru = to_sru(subdev); 128 struct vsp1_sru *sru = to_sru(subdev);
129 struct v4l2_subdev_pad_config *config;
207 struct v4l2_mbus_framefmt *format; 130 struct v4l2_mbus_framefmt *format;
208 131
209 format = vsp1_entity_get_pad_format(&sru->entity, cfg, 132 config = vsp1_entity_get_pad_config(&sru->entity, cfg, fse->which);
210 SRU_PAD_SINK, fse->which); 133 if (!config)
134 return -EINVAL;
135
136 format = vsp1_entity_get_pad_format(&sru->entity, config, SRU_PAD_SINK);
211 137
212 if (fse->index || fse->code != format->code) 138 if (fse->index || fse->code != format->code)
213 return -EINVAL; 139 return -EINVAL;
@@ -233,20 +159,9 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev,
233 return 0; 159 return 0;
234} 160}
235 161
236static int sru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 162static void sru_try_format(struct vsp1_sru *sru,
237 struct v4l2_subdev_format *fmt) 163 struct v4l2_subdev_pad_config *config,
238{ 164 unsigned int pad, struct v4l2_mbus_framefmt *fmt)
239 struct vsp1_sru *sru = to_sru(subdev);
240
241 fmt->format = *vsp1_entity_get_pad_format(&sru->entity, cfg, fmt->pad,
242 fmt->which);
243
244 return 0;
245}
246
247static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_pad_config *cfg,
248 unsigned int pad, struct v4l2_mbus_framefmt *fmt,
249 enum v4l2_subdev_format_whence which)
250{ 165{
251 struct v4l2_mbus_framefmt *format; 166 struct v4l2_mbus_framefmt *format;
252 unsigned int input_area; 167 unsigned int input_area;
@@ -265,8 +180,8 @@ static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_pad_config *
265 180
266 case SRU_PAD_SOURCE: 181 case SRU_PAD_SOURCE:
267 /* The SRU can't perform format conversion. */ 182 /* The SRU can't perform format conversion. */
268 format = vsp1_entity_get_pad_format(&sru->entity, cfg, 183 format = vsp1_entity_get_pad_format(&sru->entity, config,
269 SRU_PAD_SINK, which); 184 SRU_PAD_SINK);
270 fmt->code = format->code; 185 fmt->code = format->code;
271 186
272 /* We can upscale by 2 in both direction, but not independently. 187 /* We can upscale by 2 in both direction, but not independently.
@@ -295,57 +210,94 @@ static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_pad_config *
295 fmt->colorspace = V4L2_COLORSPACE_SRGB; 210 fmt->colorspace = V4L2_COLORSPACE_SRGB;
296} 211}
297 212
298static int sru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 213static int sru_set_format(struct v4l2_subdev *subdev,
214 struct v4l2_subdev_pad_config *cfg,
299 struct v4l2_subdev_format *fmt) 215 struct v4l2_subdev_format *fmt)
300{ 216{
301 struct vsp1_sru *sru = to_sru(subdev); 217 struct vsp1_sru *sru = to_sru(subdev);
218 struct v4l2_subdev_pad_config *config;
302 struct v4l2_mbus_framefmt *format; 219 struct v4l2_mbus_framefmt *format;
303 220
304 sru_try_format(sru, cfg, fmt->pad, &fmt->format, fmt->which); 221 config = vsp1_entity_get_pad_config(&sru->entity, cfg, fmt->which);
222 if (!config)
223 return -EINVAL;
224
225 sru_try_format(sru, config, fmt->pad, &fmt->format);
305 226
306 format = vsp1_entity_get_pad_format(&sru->entity, cfg, fmt->pad, 227 format = vsp1_entity_get_pad_format(&sru->entity, config, fmt->pad);
307 fmt->which);
308 *format = fmt->format; 228 *format = fmt->format;
309 229
310 if (fmt->pad == SRU_PAD_SINK) { 230 if (fmt->pad == SRU_PAD_SINK) {
311 /* Propagate the format to the source pad. */ 231 /* Propagate the format to the source pad. */
312 format = vsp1_entity_get_pad_format(&sru->entity, cfg, 232 format = vsp1_entity_get_pad_format(&sru->entity, config,
313 SRU_PAD_SOURCE, fmt->which); 233 SRU_PAD_SOURCE);
314 *format = fmt->format; 234 *format = fmt->format;
315 235
316 sru_try_format(sru, cfg, SRU_PAD_SOURCE, format, fmt->which); 236 sru_try_format(sru, config, SRU_PAD_SOURCE, format);
317 } 237 }
318 238
319 return 0; 239 return 0;
320} 240}
321 241
322/* -----------------------------------------------------------------------------
323 * V4L2 Subdevice Operations
324 */
325
326static struct v4l2_subdev_video_ops sru_video_ops = {
327 .s_stream = sru_s_stream,
328};
329
330static struct v4l2_subdev_pad_ops sru_pad_ops = { 242static struct v4l2_subdev_pad_ops sru_pad_ops = {
243 .init_cfg = vsp1_entity_init_cfg,
331 .enum_mbus_code = sru_enum_mbus_code, 244 .enum_mbus_code = sru_enum_mbus_code,
332 .enum_frame_size = sru_enum_frame_size, 245 .enum_frame_size = sru_enum_frame_size,
333 .get_fmt = sru_get_format, 246 .get_fmt = vsp1_subdev_get_pad_format,
334 .set_fmt = sru_set_format, 247 .set_fmt = sru_set_format,
335}; 248};
336 249
337static struct v4l2_subdev_ops sru_ops = { 250static struct v4l2_subdev_ops sru_ops = {
338 .video = &sru_video_ops,
339 .pad = &sru_pad_ops, 251 .pad = &sru_pad_ops,
340}; 252};
341 253
342/* ----------------------------------------------------------------------------- 254/* -----------------------------------------------------------------------------
255 * VSP1 Entity Operations
256 */
257
258static void sru_configure(struct vsp1_entity *entity,
259 struct vsp1_pipeline *pipe,
260 struct vsp1_dl_list *dl)
261{
262 const struct vsp1_sru_param *param;
263 struct vsp1_sru *sru = to_sru(&entity->subdev);
264 struct v4l2_mbus_framefmt *input;
265 struct v4l2_mbus_framefmt *output;
266 u32 ctrl0;
267
268 input = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
269 SRU_PAD_SINK);
270 output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
271 SRU_PAD_SOURCE);
272
273 if (input->code == MEDIA_BUS_FMT_ARGB8888_1X32)
274 ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3
275 | VI6_SRU_CTRL0_PARAM4;
276 else
277 ctrl0 = VI6_SRU_CTRL0_PARAM3;
278
279 if (input->width != output->width)
280 ctrl0 |= VI6_SRU_CTRL0_MODE_UPSCALE;
281
282 param = &vsp1_sru_params[sru->intensity - 1];
283
284 ctrl0 |= param->ctrl0;
285
286 vsp1_sru_write(sru, dl, VI6_SRU_CTRL0, ctrl0);
287 vsp1_sru_write(sru, dl, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5);
288 vsp1_sru_write(sru, dl, VI6_SRU_CTRL2, param->ctrl2);
289}
290
291static const struct vsp1_entity_operations sru_entity_ops = {
292 .configure = sru_configure,
293};
294
295/* -----------------------------------------------------------------------------
343 * Initialization and Cleanup 296 * Initialization and Cleanup
344 */ 297 */
345 298
346struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1) 299struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1)
347{ 300{
348 struct v4l2_subdev *subdev;
349 struct vsp1_sru *sru; 301 struct vsp1_sru *sru;
350 int ret; 302 int ret;
351 303
@@ -353,29 +305,19 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1)
353 if (sru == NULL) 305 if (sru == NULL)
354 return ERR_PTR(-ENOMEM); 306 return ERR_PTR(-ENOMEM);
355 307
308 sru->entity.ops = &sru_entity_ops;
356 sru->entity.type = VSP1_ENTITY_SRU; 309 sru->entity.type = VSP1_ENTITY_SRU;
357 310
358 ret = vsp1_entity_init(vsp1, &sru->entity, 2); 311 ret = vsp1_entity_init(vsp1, &sru->entity, "sru", 2, &sru_ops);
359 if (ret < 0) 312 if (ret < 0)
360 return ERR_PTR(ret); 313 return ERR_PTR(ret);
361 314
362 /* Initialize the V4L2 subdev. */
363 subdev = &sru->entity.subdev;
364 v4l2_subdev_init(subdev, &sru_ops);
365
366 subdev->entity.ops = &vsp1->media_ops;
367 subdev->internal_ops = &vsp1_subdev_internal_ops;
368 snprintf(subdev->name, sizeof(subdev->name), "%s sru",
369 dev_name(vsp1->dev));
370 v4l2_set_subdevdata(subdev, sru);
371 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
372
373 vsp1_entity_init_formats(subdev, NULL);
374
375 /* Initialize the control handler. */ 315 /* Initialize the control handler. */
376 v4l2_ctrl_handler_init(&sru->ctrls, 1); 316 v4l2_ctrl_handler_init(&sru->ctrls, 1);
377 v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL); 317 v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL);
378 318
319 sru->intensity = 1;
320
379 sru->entity.subdev.ctrl_handler = &sru->ctrls; 321 sru->entity.subdev.ctrl_handler = &sru->ctrls;
380 322
381 if (sru->ctrls.error) { 323 if (sru->ctrls.error) {
diff --git a/drivers/media/platform/vsp1/vsp1_sru.h b/drivers/media/platform/vsp1/vsp1_sru.h
index b6768bf3dc47..85e241457af2 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.h
+++ b/drivers/media/platform/vsp1/vsp1_sru.h
@@ -28,6 +28,8 @@ struct vsp1_sru {
28 struct vsp1_entity entity; 28 struct vsp1_entity entity;
29 29
30 struct v4l2_ctrl_handler ctrls; 30 struct v4l2_ctrl_handler ctrls;
31
32 unsigned int intensity;
31}; 33};
32 34
33static inline struct vsp1_sru *to_sru(struct v4l2_subdev *subdev) 35static inline struct vsp1_sru *to_sru(struct v4l2_subdev *subdev)
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index bba67770cf95..1875e29da184 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -17,6 +17,7 @@
17#include <media/v4l2-subdev.h> 17#include <media/v4l2-subdev.h>
18 18
19#include "vsp1.h" 19#include "vsp1.h"
20#include "vsp1_dl.h"
20#include "vsp1_uds.h" 21#include "vsp1_uds.h"
21 22
22#define UDS_MIN_SIZE 4U 23#define UDS_MIN_SIZE 4U
@@ -29,19 +30,21 @@
29 * Device Access 30 * Device Access
30 */ 31 */
31 32
32static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data) 33static inline void vsp1_uds_write(struct vsp1_uds *uds, struct vsp1_dl_list *dl,
34 u32 reg, u32 data)
33{ 35{
34 vsp1_write(uds->entity.vsp1, 36 vsp1_dl_list_write(dl, reg + uds->entity.index * VI6_UDS_OFFSET, data);
35 reg + uds->entity.index * VI6_UDS_OFFSET, data);
36} 37}
37 38
38/* ----------------------------------------------------------------------------- 39/* -----------------------------------------------------------------------------
39 * Scaling Computation 40 * Scaling Computation
40 */ 41 */
41 42
42void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha) 43void vsp1_uds_set_alpha(struct vsp1_uds *uds, struct vsp1_dl_list *dl,
44 unsigned int alpha)
43{ 45{
44 vsp1_uds_write(uds, VI6_UDS_ALPVAL, alpha << VI6_UDS_ALPVAL_VAL0_SHIFT); 46 vsp1_uds_write(uds, dl, VI6_UDS_ALPVAL,
47 alpha << VI6_UDS_ALPVAL_VAL0_SHIFT);
45} 48}
46 49
47/* 50/*
@@ -105,60 +108,6 @@ static unsigned int uds_compute_ratio(unsigned int input, unsigned int output)
105} 108}
106 109
107/* ----------------------------------------------------------------------------- 110/* -----------------------------------------------------------------------------
108 * V4L2 Subdevice Core Operations
109 */
110
111static int uds_s_stream(struct v4l2_subdev *subdev, int enable)
112{
113 struct vsp1_uds *uds = to_uds(subdev);
114 const struct v4l2_mbus_framefmt *output;
115 const struct v4l2_mbus_framefmt *input;
116 unsigned int hscale;
117 unsigned int vscale;
118 bool multitap;
119
120 if (!enable)
121 return 0;
122
123 input = &uds->entity.formats[UDS_PAD_SINK];
124 output = &uds->entity.formats[UDS_PAD_SOURCE];
125
126 hscale = uds_compute_ratio(input->width, output->width);
127 vscale = uds_compute_ratio(input->height, output->height);
128
129 dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale);
130
131 /* Multi-tap scaling can't be enabled along with alpha scaling when
132 * scaling down with a factor lower than or equal to 1/2 in either
133 * direction.
134 */
135 if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192))
136 multitap = false;
137 else
138 multitap = true;
139
140 vsp1_uds_write(uds, VI6_UDS_CTRL,
141 (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) |
142 (multitap ? VI6_UDS_CTRL_BC : 0));
143
144 vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH,
145 (uds_passband_width(hscale)
146 << VI6_UDS_PASS_BWIDTH_H_SHIFT) |
147 (uds_passband_width(vscale)
148 << VI6_UDS_PASS_BWIDTH_V_SHIFT));
149
150 /* Set the scaling ratios and the output size. */
151 vsp1_uds_write(uds, VI6_UDS_SCALE,
152 (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
153 (vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
154 vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE,
155 (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
156 (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
157
158 return 0;
159}
160
161/* -----------------------------------------------------------------------------
162 * V4L2 Subdevice Pad Operations 111 * V4L2 Subdevice Pad Operations
163 */ 112 */
164 113
@@ -170,28 +119,9 @@ static int uds_enum_mbus_code(struct v4l2_subdev *subdev,
170 MEDIA_BUS_FMT_ARGB8888_1X32, 119 MEDIA_BUS_FMT_ARGB8888_1X32,
171 MEDIA_BUS_FMT_AYUV8_1X32, 120 MEDIA_BUS_FMT_AYUV8_1X32,
172 }; 121 };
173 struct vsp1_uds *uds = to_uds(subdev);
174
175 if (code->pad == UDS_PAD_SINK) {
176 if (code->index >= ARRAY_SIZE(codes))
177 return -EINVAL;
178
179 code->code = codes[code->index];
180 } else {
181 struct v4l2_mbus_framefmt *format;
182
183 /* The UDS can't perform format conversion, the sink format is
184 * always identical to the source format.
185 */
186 if (code->index)
187 return -EINVAL;
188 122
189 format = vsp1_entity_get_pad_format(&uds->entity, cfg, 123 return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
190 UDS_PAD_SINK, code->which); 124 ARRAY_SIZE(codes));
191 code->code = format->code;
192 }
193
194 return 0;
195} 125}
196 126
197static int uds_enum_frame_size(struct v4l2_subdev *subdev, 127static int uds_enum_frame_size(struct v4l2_subdev *subdev,
@@ -199,10 +129,15 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev,
199 struct v4l2_subdev_frame_size_enum *fse) 129 struct v4l2_subdev_frame_size_enum *fse)
200{ 130{
201 struct vsp1_uds *uds = to_uds(subdev); 131 struct vsp1_uds *uds = to_uds(subdev);
132 struct v4l2_subdev_pad_config *config;
202 struct v4l2_mbus_framefmt *format; 133 struct v4l2_mbus_framefmt *format;
203 134
204 format = vsp1_entity_get_pad_format(&uds->entity, cfg, 135 config = vsp1_entity_get_pad_config(&uds->entity, cfg, fse->which);
205 UDS_PAD_SINK, fse->which); 136 if (!config)
137 return -EINVAL;
138
139 format = vsp1_entity_get_pad_format(&uds->entity, config,
140 UDS_PAD_SINK);
206 141
207 if (fse->index || fse->code != format->code) 142 if (fse->index || fse->code != format->code)
208 return -EINVAL; 143 return -EINVAL;
@@ -222,20 +157,9 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev,
222 return 0; 157 return 0;
223} 158}
224 159
225static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 160static void uds_try_format(struct vsp1_uds *uds,
226 struct v4l2_subdev_format *fmt) 161 struct v4l2_subdev_pad_config *config,
227{ 162 unsigned int pad, struct v4l2_mbus_framefmt *fmt)
228 struct vsp1_uds *uds = to_uds(subdev);
229
230 fmt->format = *vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad,
231 fmt->which);
232
233 return 0;
234}
235
236static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *cfg,
237 unsigned int pad, struct v4l2_mbus_framefmt *fmt,
238 enum v4l2_subdev_format_whence which)
239{ 163{
240 struct v4l2_mbus_framefmt *format; 164 struct v4l2_mbus_framefmt *format;
241 unsigned int minimum; 165 unsigned int minimum;
@@ -254,8 +178,8 @@ static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *
254 178
255 case UDS_PAD_SOURCE: 179 case UDS_PAD_SOURCE:
256 /* The UDS scales but can't perform format conversion. */ 180 /* The UDS scales but can't perform format conversion. */
257 format = vsp1_entity_get_pad_format(&uds->entity, cfg, 181 format = vsp1_entity_get_pad_format(&uds->entity, config,
258 UDS_PAD_SINK, which); 182 UDS_PAD_SINK);
259 fmt->code = format->code; 183 fmt->code = format->code;
260 184
261 uds_output_limits(format->width, &minimum, &maximum); 185 uds_output_limits(format->width, &minimum, &maximum);
@@ -269,25 +193,30 @@ static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *
269 fmt->colorspace = V4L2_COLORSPACE_SRGB; 193 fmt->colorspace = V4L2_COLORSPACE_SRGB;
270} 194}
271 195
272static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, 196static int uds_set_format(struct v4l2_subdev *subdev,
197 struct v4l2_subdev_pad_config *cfg,
273 struct v4l2_subdev_format *fmt) 198 struct v4l2_subdev_format *fmt)
274{ 199{
275 struct vsp1_uds *uds = to_uds(subdev); 200 struct vsp1_uds *uds = to_uds(subdev);
201 struct v4l2_subdev_pad_config *config;
276 struct v4l2_mbus_framefmt *format; 202 struct v4l2_mbus_framefmt *format;
277 203
278 uds_try_format(uds, cfg, fmt->pad, &fmt->format, fmt->which); 204 config = vsp1_entity_get_pad_config(&uds->entity, cfg, fmt->which);
205 if (!config)
206 return -EINVAL;
207
208 uds_try_format(uds, config, fmt->pad, &fmt->format);
279 209
280 format = vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad, 210 format = vsp1_entity_get_pad_format(&uds->entity, config, fmt->pad);
281 fmt->which);
282 *format = fmt->format; 211 *format = fmt->format;
283 212
284 if (fmt->pad == UDS_PAD_SINK) { 213 if (fmt->pad == UDS_PAD_SINK) {
285 /* Propagate the format to the source pad. */ 214 /* Propagate the format to the source pad. */
286 format = vsp1_entity_get_pad_format(&uds->entity, cfg, 215 format = vsp1_entity_get_pad_format(&uds->entity, config,
287 UDS_PAD_SOURCE, fmt->which); 216 UDS_PAD_SOURCE);
288 *format = fmt->format; 217 *format = fmt->format;
289 218
290 uds_try_format(uds, cfg, UDS_PAD_SOURCE, format, fmt->which); 219 uds_try_format(uds, config, UDS_PAD_SOURCE, format);
291 } 220 }
292 221
293 return 0; 222 return 0;
@@ -297,55 +226,97 @@ static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con
297 * V4L2 Subdevice Operations 226 * V4L2 Subdevice Operations
298 */ 227 */
299 228
300static struct v4l2_subdev_video_ops uds_video_ops = {
301 .s_stream = uds_s_stream,
302};
303
304static struct v4l2_subdev_pad_ops uds_pad_ops = { 229static struct v4l2_subdev_pad_ops uds_pad_ops = {
230 .init_cfg = vsp1_entity_init_cfg,
305 .enum_mbus_code = uds_enum_mbus_code, 231 .enum_mbus_code = uds_enum_mbus_code,
306 .enum_frame_size = uds_enum_frame_size, 232 .enum_frame_size = uds_enum_frame_size,
307 .get_fmt = uds_get_format, 233 .get_fmt = vsp1_subdev_get_pad_format,
308 .set_fmt = uds_set_format, 234 .set_fmt = uds_set_format,
309}; 235};
310 236
311static struct v4l2_subdev_ops uds_ops = { 237static struct v4l2_subdev_ops uds_ops = {
312 .video = &uds_video_ops,
313 .pad = &uds_pad_ops, 238 .pad = &uds_pad_ops,
314}; 239};
315 240
316/* ----------------------------------------------------------------------------- 241/* -----------------------------------------------------------------------------
242 * VSP1 Entity Operations
243 */
244
245static void uds_configure(struct vsp1_entity *entity,
246 struct vsp1_pipeline *pipe,
247 struct vsp1_dl_list *dl)
248{
249 struct vsp1_uds *uds = to_uds(&entity->subdev);
250 const struct v4l2_mbus_framefmt *output;
251 const struct v4l2_mbus_framefmt *input;
252 unsigned int hscale;
253 unsigned int vscale;
254 bool multitap;
255
256 input = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
257 UDS_PAD_SINK);
258 output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
259 UDS_PAD_SOURCE);
260
261 hscale = uds_compute_ratio(input->width, output->width);
262 vscale = uds_compute_ratio(input->height, output->height);
263
264 dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale);
265
266 /* Multi-tap scaling can't be enabled along with alpha scaling when
267 * scaling down with a factor lower than or equal to 1/2 in either
268 * direction.
269 */
270 if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192))
271 multitap = false;
272 else
273 multitap = true;
274
275 vsp1_uds_write(uds, dl, VI6_UDS_CTRL,
276 (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) |
277 (multitap ? VI6_UDS_CTRL_BC : 0));
278
279 vsp1_uds_write(uds, dl, VI6_UDS_PASS_BWIDTH,
280 (uds_passband_width(hscale)
281 << VI6_UDS_PASS_BWIDTH_H_SHIFT) |
282 (uds_passband_width(vscale)
283 << VI6_UDS_PASS_BWIDTH_V_SHIFT));
284
285 /* Set the scaling ratios and the output size. */
286 vsp1_uds_write(uds, dl, VI6_UDS_SCALE,
287 (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
288 (vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
289 vsp1_uds_write(uds, dl, VI6_UDS_CLIP_SIZE,
290 (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
291 (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
292}
293
294static const struct vsp1_entity_operations uds_entity_ops = {
295 .configure = uds_configure,
296};
297
298/* -----------------------------------------------------------------------------
317 * Initialization and Cleanup 299 * Initialization and Cleanup
318 */ 300 */
319 301
320struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index) 302struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index)
321{ 303{
322 struct v4l2_subdev *subdev;
323 struct vsp1_uds *uds; 304 struct vsp1_uds *uds;
305 char name[6];
324 int ret; 306 int ret;
325 307
326 uds = devm_kzalloc(vsp1->dev, sizeof(*uds), GFP_KERNEL); 308 uds = devm_kzalloc(vsp1->dev, sizeof(*uds), GFP_KERNEL);
327 if (uds == NULL) 309 if (uds == NULL)
328 return ERR_PTR(-ENOMEM); 310 return ERR_PTR(-ENOMEM);
329 311
312 uds->entity.ops = &uds_entity_ops;
330 uds->entity.type = VSP1_ENTITY_UDS; 313 uds->entity.type = VSP1_ENTITY_UDS;
331 uds->entity.index = index; 314 uds->entity.index = index;
332 315
333 ret = vsp1_entity_init(vsp1, &uds->entity, 2); 316 sprintf(name, "uds.%u", index);
317 ret = vsp1_entity_init(vsp1, &uds->entity, name, 2, &uds_ops);
334 if (ret < 0) 318 if (ret < 0)
335 return ERR_PTR(ret); 319 return ERR_PTR(ret);
336 320
337 /* Initialize the V4L2 subdev. */
338 subdev = &uds->entity.subdev;
339 v4l2_subdev_init(subdev, &uds_ops);
340
341 subdev->entity.ops = &vsp1->media_ops;
342 subdev->internal_ops = &vsp1_subdev_internal_ops;
343 snprintf(subdev->name, sizeof(subdev->name), "%s uds.%u",
344 dev_name(vsp1->dev), index);
345 v4l2_set_subdevdata(subdev, uds);
346 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
347
348 vsp1_entity_init_formats(subdev, NULL);
349
350 return uds; 321 return uds;
351} 322}
diff --git a/drivers/media/platform/vsp1/vsp1_uds.h b/drivers/media/platform/vsp1/vsp1_uds.h
index 031ac0da1b66..5c8cbfcad4cc 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.h
+++ b/drivers/media/platform/vsp1/vsp1_uds.h
@@ -35,6 +35,7 @@ static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev)
35 35
36struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index); 36struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index);
37 37
38void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha); 38void vsp1_uds_set_alpha(struct vsp1_uds *uds, struct vsp1_dl_list *dl,
39 unsigned int alpha);
39 40
40#endif /* __VSP1_UDS_H__ */ 41#endif /* __VSP1_UDS_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 72cc7d3729f8..a9aec5c0bec6 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -29,6 +29,7 @@
29 29
30#include "vsp1.h" 30#include "vsp1.h"
31#include "vsp1_bru.h" 31#include "vsp1_bru.h"
32#include "vsp1_dl.h"
32#include "vsp1_entity.h" 33#include "vsp1_entity.h"
33#include "vsp1_pipe.h" 34#include "vsp1_pipe.h"
34#include "vsp1_rwpf.h" 35#include "vsp1_rwpf.h"
@@ -171,53 +172,178 @@ static int __vsp1_video_try_format(struct vsp1_video *video,
171 * Pipeline Management 172 * Pipeline Management
172 */ 173 */
173 174
174static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe, 175/*
175 struct vsp1_rwpf *input, 176 * vsp1_video_complete_buffer - Complete the current buffer
176 struct vsp1_rwpf *output) 177 * @video: the video node
178 *
179 * This function completes the current buffer by filling its sequence number,
180 * time stamp and payload size, and hands it back to the videobuf core.
181 *
182 * When operating in DU output mode (deep pipeline to the DU through the LIF),
183 * the VSP1 needs to constantly supply frames to the display. In that case, if
184 * no other buffer is queued, reuse the one that has just been processed instead
185 * of handing it back to the videobuf core.
186 *
187 * Return the next queued buffer or NULL if the queue is empty.
188 */
189static struct vsp1_vb2_buffer *
190vsp1_video_complete_buffer(struct vsp1_video *video)
191{
192 struct vsp1_pipeline *pipe = video->rwpf->pipe;
193 struct vsp1_vb2_buffer *next = NULL;
194 struct vsp1_vb2_buffer *done;
195 unsigned long flags;
196 unsigned int i;
197
198 spin_lock_irqsave(&video->irqlock, flags);
199
200 if (list_empty(&video->irqqueue)) {
201 spin_unlock_irqrestore(&video->irqlock, flags);
202 return NULL;
203 }
204
205 done = list_first_entry(&video->irqqueue,
206 struct vsp1_vb2_buffer, queue);
207
208 /* In DU output mode reuse the buffer if the list is singular. */
209 if (pipe->lif && list_is_singular(&video->irqqueue)) {
210 spin_unlock_irqrestore(&video->irqlock, flags);
211 return done;
212 }
213
214 list_del(&done->queue);
215
216 if (!list_empty(&video->irqqueue))
217 next = list_first_entry(&video->irqqueue,
218 struct vsp1_vb2_buffer, queue);
219
220 spin_unlock_irqrestore(&video->irqlock, flags);
221
222 done->buf.sequence = video->sequence++;
223 done->buf.vb2_buf.timestamp = ktime_get_ns();
224 for (i = 0; i < done->buf.vb2_buf.num_planes; ++i)
225 vb2_set_plane_payload(&done->buf.vb2_buf, i,
226 vb2_plane_size(&done->buf.vb2_buf, i));
227 vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE);
228
229 return next;
230}
231
232static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
233 struct vsp1_rwpf *rwpf)
234{
235 struct vsp1_video *video = rwpf->video;
236 struct vsp1_vb2_buffer *buf;
237 unsigned long flags;
238
239 buf = vsp1_video_complete_buffer(video);
240 if (buf == NULL)
241 return;
242
243 spin_lock_irqsave(&pipe->irqlock, flags);
244
245 video->rwpf->mem = buf->mem;
246 pipe->buffers_ready |= 1 << video->pipe_index;
247
248 spin_unlock_irqrestore(&pipe->irqlock, flags);
249}
250
251static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
252{
253 struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
254 unsigned int i;
255
256 if (!pipe->dl)
257 pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
258
259 for (i = 0; i < vsp1->info->rpf_count; ++i) {
260 struct vsp1_rwpf *rwpf = pipe->inputs[i];
261
262 if (rwpf)
263 vsp1_rwpf_set_memory(rwpf, pipe->dl);
264 }
265
266 if (!pipe->lif)
267 vsp1_rwpf_set_memory(pipe->output, pipe->dl);
268
269 vsp1_dl_list_commit(pipe->dl);
270 pipe->dl = NULL;
271
272 vsp1_pipeline_run(pipe);
273}
274
275static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe)
276{
277 struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
278 enum vsp1_pipeline_state state;
279 unsigned long flags;
280 unsigned int i;
281
282 /* Complete buffers on all video nodes. */
283 for (i = 0; i < vsp1->info->rpf_count; ++i) {
284 if (!pipe->inputs[i])
285 continue;
286
287 vsp1_video_frame_end(pipe, pipe->inputs[i]);
288 }
289
290 vsp1_video_frame_end(pipe, pipe->output);
291
292 spin_lock_irqsave(&pipe->irqlock, flags);
293
294 state = pipe->state;
295 pipe->state = VSP1_PIPELINE_STOPPED;
296
297 /* If a stop has been requested, mark the pipeline as stopped and
298 * return. Otherwise restart the pipeline if ready.
299 */
300 if (state == VSP1_PIPELINE_STOPPING)
301 wake_up(&pipe->wq);
302 else if (vsp1_pipeline_ready(pipe))
303 vsp1_video_pipeline_run(pipe);
304
305 spin_unlock_irqrestore(&pipe->irqlock, flags);
306}
307
308static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
309 struct vsp1_rwpf *input,
310 struct vsp1_rwpf *output)
177{ 311{
178 struct vsp1_entity *entity;
179 struct media_entity_enum ent_enum; 312 struct media_entity_enum ent_enum;
313 struct vsp1_entity *entity;
180 struct media_pad *pad; 314 struct media_pad *pad;
181 int rval;
182 bool bru_found = false; 315 bool bru_found = false;
316 int ret;
183 317
184 input->location.left = 0; 318 ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev);
185 input->location.top = 0; 319 if (ret < 0)
186 320 return ret;
187 rval = media_entity_enum_init(
188 &ent_enum, input->entity.pads[RWPF_PAD_SOURCE].graph_obj.mdev);
189 if (rval)
190 return rval;
191 321
192 pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]); 322 pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]);
193 323
194 while (1) { 324 while (1) {
195 if (pad == NULL) { 325 if (pad == NULL) {
196 rval = -EPIPE; 326 ret = -EPIPE;
197 goto out; 327 goto out;
198 } 328 }
199 329
200 /* We've reached a video node, that shouldn't have happened. */ 330 /* We've reached a video node, that shouldn't have happened. */
201 if (!is_media_entity_v4l2_subdev(pad->entity)) { 331 if (!is_media_entity_v4l2_subdev(pad->entity)) {
202 rval = -EPIPE; 332 ret = -EPIPE;
203 goto out; 333 goto out;
204 } 334 }
205 335
206 entity = to_vsp1_entity( 336 entity = to_vsp1_entity(
207 media_entity_to_v4l2_subdev(pad->entity)); 337 media_entity_to_v4l2_subdev(pad->entity));
208 338
209 /* A BRU is present in the pipeline, store the compose rectangle 339 /* A BRU is present in the pipeline, store the BRU input pad
210 * location in the input RPF for use when configuring the RPF. 340 * number in the input RPF for use when configuring the RPF.
211 */ 341 */
212 if (entity->type == VSP1_ENTITY_BRU) { 342 if (entity->type == VSP1_ENTITY_BRU) {
213 struct vsp1_bru *bru = to_bru(&entity->subdev); 343 struct vsp1_bru *bru = to_bru(&entity->subdev);
214 struct v4l2_rect *rect =
215 &bru->inputs[pad->index].compose;
216 344
217 bru->inputs[pad->index].rpf = input; 345 bru->inputs[pad->index].rpf = input;
218 346 input->bru_input = pad->index;
219 input->location.left = rect->left;
220 input->location.top = rect->top;
221 347
222 bru_found = true; 348 bru_found = true;
223 } 349 }
@@ -229,14 +355,14 @@ static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe,
229 /* Ensure the branch has no loop. */ 355 /* Ensure the branch has no loop. */
230 if (media_entity_enum_test_and_set(&ent_enum, 356 if (media_entity_enum_test_and_set(&ent_enum,
231 &entity->subdev.entity)) { 357 &entity->subdev.entity)) {
232 rval = -EPIPE; 358 ret = -EPIPE;
233 goto out; 359 goto out;
234 } 360 }
235 361
236 /* UDS can't be chained. */ 362 /* UDS can't be chained. */
237 if (entity->type == VSP1_ENTITY_UDS) { 363 if (entity->type == VSP1_ENTITY_UDS) {
238 if (pipe->uds) { 364 if (pipe->uds) {
239 rval = -EPIPE; 365 ret = -EPIPE;
240 goto out; 366 goto out;
241 } 367 }
242 368
@@ -256,16 +382,16 @@ static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe,
256 382
257 /* The last entity must be the output WPF. */ 383 /* The last entity must be the output WPF. */
258 if (entity != &output->entity) 384 if (entity != &output->entity)
259 rval = -EPIPE; 385 ret = -EPIPE;
260 386
261out: 387out:
262 media_entity_enum_cleanup(&ent_enum); 388 media_entity_enum_cleanup(&ent_enum);
263 389
264 return rval; 390 return ret;
265} 391}
266 392
267static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe, 393static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
268 struct vsp1_video *video) 394 struct vsp1_video *video)
269{ 395{
270 struct media_entity_graph graph; 396 struct media_entity_graph graph;
271 struct media_entity *entity = &video->video.entity; 397 struct media_entity *entity = &video->video.entity;
@@ -273,14 +399,10 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe,
273 unsigned int i; 399 unsigned int i;
274 int ret; 400 int ret;
275 401
276 mutex_lock(&mdev->graph_mutex);
277
278 /* Walk the graph to locate the entities and video nodes. */ 402 /* Walk the graph to locate the entities and video nodes. */
279 ret = media_entity_graph_walk_init(&graph, mdev); 403 ret = media_entity_graph_walk_init(&graph, mdev);
280 if (ret) { 404 if (ret)
281 mutex_unlock(&mdev->graph_mutex);
282 return ret; 405 return ret;
283 }
284 406
285 media_entity_graph_walk_start(&graph, entity); 407 media_entity_graph_walk_start(&graph, entity);
286 408
@@ -300,10 +422,12 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe,
300 rwpf = to_rwpf(subdev); 422 rwpf = to_rwpf(subdev);
301 pipe->inputs[rwpf->entity.index] = rwpf; 423 pipe->inputs[rwpf->entity.index] = rwpf;
302 rwpf->video->pipe_index = ++pipe->num_inputs; 424 rwpf->video->pipe_index = ++pipe->num_inputs;
425 rwpf->pipe = pipe;
303 } else if (e->type == VSP1_ENTITY_WPF) { 426 } else if (e->type == VSP1_ENTITY_WPF) {
304 rwpf = to_rwpf(subdev); 427 rwpf = to_rwpf(subdev);
305 pipe->output = rwpf; 428 pipe->output = rwpf;
306 rwpf->video->pipe_index = 0; 429 rwpf->video->pipe_index = 0;
430 rwpf->pipe = pipe;
307 } else if (e->type == VSP1_ENTITY_LIF) { 431 } else if (e->type == VSP1_ENTITY_LIF) {
308 pipe->lif = e; 432 pipe->lif = e;
309 } else if (e->type == VSP1_ENTITY_BRU) { 433 } else if (e->type == VSP1_ENTITY_BRU) {
@@ -311,15 +435,11 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe,
311 } 435 }
312 } 436 }
313 437
314 mutex_unlock(&mdev->graph_mutex);
315
316 media_entity_graph_walk_cleanup(&graph); 438 media_entity_graph_walk_cleanup(&graph);
317 439
318 /* We need one output and at least one input. */ 440 /* We need one output and at least one input. */
319 if (pipe->num_inputs == 0 || !pipe->output) { 441 if (pipe->num_inputs == 0 || !pipe->output)
320 ret = -EPIPE; 442 return -EPIPE;
321 goto error;
322 }
323 443
324 /* Follow links downstream for each input and make sure the graph 444 /* Follow links downstream for each input and make sure the graph
325 * contains no loop and that all branches end at the output WPF. 445 * contains no loop and that all branches end at the output WPF.
@@ -328,143 +448,69 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe,
328 if (!pipe->inputs[i]) 448 if (!pipe->inputs[i])
329 continue; 449 continue;
330 450
331 ret = vsp1_video_pipeline_validate_branch(pipe, pipe->inputs[i], 451 ret = vsp1_video_pipeline_build_branch(pipe, pipe->inputs[i],
332 pipe->output); 452 pipe->output);
333 if (ret < 0) 453 if (ret < 0)
334 goto error; 454 return ret;
335 } 455 }
336 456
337 return 0; 457 return 0;
338
339error:
340 vsp1_pipeline_reset(pipe);
341 return ret;
342} 458}
343 459
344static int vsp1_video_pipeline_init(struct vsp1_pipeline *pipe, 460static int vsp1_video_pipeline_init(struct vsp1_pipeline *pipe,
345 struct vsp1_video *video) 461 struct vsp1_video *video)
346{ 462{
347 int ret; 463 vsp1_pipeline_init(pipe);
348 464
349 mutex_lock(&pipe->lock); 465 pipe->frame_end = vsp1_video_pipeline_frame_end;
350
351 /* If we're the first user validate and initialize the pipeline. */
352 if (pipe->use_count == 0) {
353 ret = vsp1_video_pipeline_validate(pipe, video);
354 if (ret < 0)
355 goto done;
356 }
357 466
358 pipe->use_count++; 467 return vsp1_video_pipeline_build(pipe, video);
359 ret = 0;
360
361done:
362 mutex_unlock(&pipe->lock);
363 return ret;
364} 468}
365 469
366static void vsp1_video_pipeline_cleanup(struct vsp1_pipeline *pipe) 470static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video)
367{
368 mutex_lock(&pipe->lock);
369
370 /* If we're the last user clean up the pipeline. */
371 if (--pipe->use_count == 0)
372 vsp1_pipeline_reset(pipe);
373
374 mutex_unlock(&pipe->lock);
375}
376
377/*
378 * vsp1_video_complete_buffer - Complete the current buffer
379 * @video: the video node
380 *
381 * This function completes the current buffer by filling its sequence number,
382 * time stamp and payload size, and hands it back to the videobuf core.
383 *
384 * When operating in DU output mode (deep pipeline to the DU through the LIF),
385 * the VSP1 needs to constantly supply frames to the display. In that case, if
386 * no other buffer is queued, reuse the one that has just been processed instead
387 * of handing it back to the videobuf core.
388 *
389 * Return the next queued buffer or NULL if the queue is empty.
390 */
391static struct vsp1_vb2_buffer *
392vsp1_video_complete_buffer(struct vsp1_video *video)
393{ 471{
394 struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); 472 struct vsp1_pipeline *pipe;
395 struct vsp1_vb2_buffer *next = NULL; 473 int ret;
396 struct vsp1_vb2_buffer *done;
397 unsigned long flags;
398 unsigned int i;
399
400 spin_lock_irqsave(&video->irqlock, flags);
401
402 if (list_empty(&video->irqqueue)) {
403 spin_unlock_irqrestore(&video->irqlock, flags);
404 return NULL;
405 }
406
407 done = list_first_entry(&video->irqqueue,
408 struct vsp1_vb2_buffer, queue);
409 474
410 /* In DU output mode reuse the buffer if the list is singular. */ 475 /* Get a pipeline object for the video node. If a pipeline has already
411 if (pipe->lif && list_is_singular(&video->irqqueue)) { 476 * been allocated just increment its reference count and return it.
412 spin_unlock_irqrestore(&video->irqlock, flags); 477 * Otherwise allocate a new pipeline and initialize it, it will be freed
413 return done; 478 * when the last reference is released.
479 */
480 if (!video->rwpf->pipe) {
481 pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
482 if (!pipe)
483 return ERR_PTR(-ENOMEM);
484
485 ret = vsp1_video_pipeline_init(pipe, video);
486 if (ret < 0) {
487 vsp1_pipeline_reset(pipe);
488 kfree(pipe);
489 return ERR_PTR(ret);
490 }
491 } else {
492 pipe = video->rwpf->pipe;
493 kref_get(&pipe->kref);
414 } 494 }
415 495
416 list_del(&done->queue); 496 return pipe;
417
418 if (!list_empty(&video->irqqueue))
419 next = list_first_entry(&video->irqqueue,
420 struct vsp1_vb2_buffer, queue);
421
422 spin_unlock_irqrestore(&video->irqlock, flags);
423
424 done->buf.sequence = video->sequence++;
425 done->buf.vb2_buf.timestamp = ktime_get_ns();
426 for (i = 0; i < done->buf.vb2_buf.num_planes; ++i)
427 vb2_set_plane_payload(&done->buf.vb2_buf, i,
428 done->mem.length[i]);
429 vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE);
430
431 return next;
432} 497}
433 498
434static void vsp1_video_frame_end(struct vsp1_pipeline *pipe, 499static void vsp1_video_pipeline_release(struct kref *kref)
435 struct vsp1_rwpf *rwpf)
436{ 500{
437 struct vsp1_video *video = rwpf->video; 501 struct vsp1_pipeline *pipe = container_of(kref, typeof(*pipe), kref);
438 struct vsp1_vb2_buffer *buf;
439 unsigned long flags;
440 502
441 buf = vsp1_video_complete_buffer(video); 503 vsp1_pipeline_reset(pipe);
442 if (buf == NULL) 504 kfree(pipe);
443 return;
444
445 spin_lock_irqsave(&pipe->irqlock, flags);
446
447 video->rwpf->ops->set_memory(video->rwpf, &buf->mem);
448 pipe->buffers_ready |= 1 << video->pipe_index;
449
450 spin_unlock_irqrestore(&pipe->irqlock, flags);
451} 505}
452 506
453static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe) 507static void vsp1_video_pipeline_put(struct vsp1_pipeline *pipe)
454{ 508{
455 struct vsp1_device *vsp1 = pipe->output->entity.vsp1; 509 struct media_device *mdev = &pipe->output->entity.vsp1->media_dev;
456 unsigned int i;
457
458 /* Complete buffers on all video nodes. */
459 for (i = 0; i < vsp1->info->rpf_count; ++i) {
460 if (!pipe->inputs[i])
461 continue;
462 510
463 vsp1_video_frame_end(pipe, pipe->inputs[i]); 511 mutex_lock(&mdev->graph_mutex);
464 } 512 kref_put(&pipe->kref, vsp1_video_pipeline_release);
465 513 mutex_unlock(&mdev->graph_mutex);
466 if (!pipe->lif)
467 vsp1_video_frame_end(pipe, pipe->output);
468} 514}
469 515
470/* ----------------------------------------------------------------------------- 516/* -----------------------------------------------------------------------------
@@ -513,16 +559,16 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb)
513 if (vb->num_planes < format->num_planes) 559 if (vb->num_planes < format->num_planes)
514 return -EINVAL; 560 return -EINVAL;
515 561
516 buf->mem.num_planes = vb->num_planes;
517
518 for (i = 0; i < vb->num_planes; ++i) { 562 for (i = 0; i < vb->num_planes; ++i) {
519 buf->mem.addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); 563 buf->mem.addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
520 buf->mem.length[i] = vb2_plane_size(vb, i);
521 564
522 if (buf->mem.length[i] < format->plane_fmt[i].sizeimage) 565 if (vb2_plane_size(vb, i) < format->plane_fmt[i].sizeimage)
523 return -EINVAL; 566 return -EINVAL;
524 } 567 }
525 568
569 for ( ; i < 3; ++i)
570 buf->mem.addr[i] = 0;
571
526 return 0; 572 return 0;
527} 573}
528 574
@@ -530,7 +576,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
530{ 576{
531 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 577 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
532 struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue); 578 struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue);
533 struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); 579 struct vsp1_pipeline *pipe = video->rwpf->pipe;
534 struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf); 580 struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf);
535 unsigned long flags; 581 unsigned long flags;
536 bool empty; 582 bool empty;
@@ -545,54 +591,66 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
545 591
546 spin_lock_irqsave(&pipe->irqlock, flags); 592 spin_lock_irqsave(&pipe->irqlock, flags);
547 593
548 video->rwpf->ops->set_memory(video->rwpf, &buf->mem); 594 video->rwpf->mem = buf->mem;
549 pipe->buffers_ready |= 1 << video->pipe_index; 595 pipe->buffers_ready |= 1 << video->pipe_index;
550 596
551 if (vb2_is_streaming(&video->queue) && 597 if (vb2_is_streaming(&video->queue) &&
552 vsp1_pipeline_ready(pipe)) 598 vsp1_pipeline_ready(pipe))
553 vsp1_pipeline_run(pipe); 599 vsp1_video_pipeline_run(pipe);
554 600
555 spin_unlock_irqrestore(&pipe->irqlock, flags); 601 spin_unlock_irqrestore(&pipe->irqlock, flags);
556} 602}
557 603
604static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe)
605{
606 struct vsp1_entity *entity;
607
608 /* Prepare the display list. */
609 pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
610 if (!pipe->dl)
611 return -ENOMEM;
612
613 if (pipe->uds) {
614 struct vsp1_uds *uds = to_uds(&pipe->uds->subdev);
615
616 /* If a BRU is present in the pipeline before the UDS, the alpha
617 * component doesn't need to be scaled as the BRU output alpha
618 * value is fixed to 255. Otherwise we need to scale the alpha
619 * component only when available at the input RPF.
620 */
621 if (pipe->uds_input->type == VSP1_ENTITY_BRU) {
622 uds->scale_alpha = false;
623 } else {
624 struct vsp1_rwpf *rpf =
625 to_rwpf(&pipe->uds_input->subdev);
626
627 uds->scale_alpha = rpf->fmtinfo->alpha;
628 }
629 }
630
631 list_for_each_entry(entity, &pipe->entities, list_pipe) {
632 vsp1_entity_route_setup(entity, pipe->dl);
633
634 if (entity->ops->configure)
635 entity->ops->configure(entity, pipe, pipe->dl);
636 }
637
638 return 0;
639}
640
558static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count) 641static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
559{ 642{
560 struct vsp1_video *video = vb2_get_drv_priv(vq); 643 struct vsp1_video *video = vb2_get_drv_priv(vq);
561 struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); 644 struct vsp1_pipeline *pipe = video->rwpf->pipe;
562 struct vsp1_entity *entity;
563 unsigned long flags; 645 unsigned long flags;
564 int ret; 646 int ret;
565 647
566 mutex_lock(&pipe->lock); 648 mutex_lock(&pipe->lock);
567 if (pipe->stream_count == pipe->num_inputs) { 649 if (pipe->stream_count == pipe->num_inputs) {
568 if (pipe->uds) { 650 ret = vsp1_video_setup_pipeline(pipe);
569 struct vsp1_uds *uds = to_uds(&pipe->uds->subdev); 651 if (ret < 0) {
570 652 mutex_unlock(&pipe->lock);
571 /* If a BRU is present in the pipeline before the UDS, 653 return ret;
572 * the alpha component doesn't need to be scaled as the
573 * BRU output alpha value is fixed to 255. Otherwise we
574 * need to scale the alpha component only when available
575 * at the input RPF.
576 */
577 if (pipe->uds_input->type == VSP1_ENTITY_BRU) {
578 uds->scale_alpha = false;
579 } else {
580 struct vsp1_rwpf *rpf =
581 to_rwpf(&pipe->uds_input->subdev);
582
583 uds->scale_alpha = rpf->fmtinfo->alpha;
584 }
585 }
586
587 list_for_each_entry(entity, &pipe->entities, list_pipe) {
588 vsp1_entity_route_setup(entity);
589
590 ret = v4l2_subdev_call(&entity->subdev, video,
591 s_stream, 1);
592 if (ret < 0) {
593 mutex_unlock(&pipe->lock);
594 return ret;
595 }
596 } 654 }
597 } 655 }
598 656
@@ -601,7 +659,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
601 659
602 spin_lock_irqsave(&pipe->irqlock, flags); 660 spin_lock_irqsave(&pipe->irqlock, flags);
603 if (vsp1_pipeline_ready(pipe)) 661 if (vsp1_pipeline_ready(pipe))
604 vsp1_pipeline_run(pipe); 662 vsp1_video_pipeline_run(pipe);
605 spin_unlock_irqrestore(&pipe->irqlock, flags); 663 spin_unlock_irqrestore(&pipe->irqlock, flags);
606 664
607 return 0; 665 return 0;
@@ -610,7 +668,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
610static void vsp1_video_stop_streaming(struct vb2_queue *vq) 668static void vsp1_video_stop_streaming(struct vb2_queue *vq)
611{ 669{
612 struct vsp1_video *video = vb2_get_drv_priv(vq); 670 struct vsp1_video *video = vb2_get_drv_priv(vq);
613 struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity); 671 struct vsp1_pipeline *pipe = video->rwpf->pipe;
614 struct vsp1_vb2_buffer *buffer; 672 struct vsp1_vb2_buffer *buffer;
615 unsigned long flags; 673 unsigned long flags;
616 int ret; 674 int ret;
@@ -621,11 +679,14 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
621 ret = vsp1_pipeline_stop(pipe); 679 ret = vsp1_pipeline_stop(pipe);
622 if (ret == -ETIMEDOUT) 680 if (ret == -ETIMEDOUT)
623 dev_err(video->vsp1->dev, "pipeline stop timeout\n"); 681 dev_err(video->vsp1->dev, "pipeline stop timeout\n");
682
683 vsp1_dl_list_put(pipe->dl);
684 pipe->dl = NULL;
624 } 685 }
625 mutex_unlock(&pipe->lock); 686 mutex_unlock(&pipe->lock);
626 687
627 vsp1_video_pipeline_cleanup(pipe);
628 media_entity_pipeline_stop(&video->video.entity); 688 media_entity_pipeline_stop(&video->video.entity);
689 vsp1_video_pipeline_put(pipe);
629 690
630 /* Remove all buffers from the IRQ queue. */ 691 /* Remove all buffers from the IRQ queue. */
631 spin_lock_irqsave(&video->irqlock, flags); 692 spin_lock_irqsave(&video->irqlock, flags);
@@ -737,6 +798,7 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
737{ 798{
738 struct v4l2_fh *vfh = file->private_data; 799 struct v4l2_fh *vfh = file->private_data;
739 struct vsp1_video *video = to_vsp1_video(vfh->vdev); 800 struct vsp1_video *video = to_vsp1_video(vfh->vdev);
801 struct media_device *mdev = &video->vsp1->media_dev;
740 struct vsp1_pipeline *pipe; 802 struct vsp1_pipeline *pipe;
741 int ret; 803 int ret;
742 804
@@ -745,18 +807,25 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
745 807
746 video->sequence = 0; 808 video->sequence = 0;
747 809
748 /* Start streaming on the pipeline. No link touching an entity in the 810 /* Get a pipeline for the video node and start streaming on it. No link
749 * pipeline can be activated or deactivated once streaming is started. 811 * touching an entity in the pipeline can be activated or deactivated
750 * 812 * once streaming is started.
751 * Use the VSP1 pipeline object embedded in the first video object that
752 * starts streaming.
753 */ 813 */
754 pipe = video->video.entity.pipe 814 mutex_lock(&mdev->graph_mutex);
755 ? to_vsp1_pipeline(&video->video.entity) : &video->pipe;
756 815
757 ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe); 816 pipe = vsp1_video_pipeline_get(video);
758 if (ret < 0) 817 if (IS_ERR(pipe)) {
759 return ret; 818 mutex_unlock(&mdev->graph_mutex);
819 return PTR_ERR(pipe);
820 }
821
822 ret = __media_entity_pipeline_start(&video->video.entity, &pipe->pipe);
823 if (ret < 0) {
824 mutex_unlock(&mdev->graph_mutex);
825 goto err_pipe;
826 }
827
828 mutex_unlock(&mdev->graph_mutex);
760 829
761 /* Verify that the configured format matches the output of the connected 830 /* Verify that the configured format matches the output of the connected
762 * subdev. 831 * subdev.
@@ -765,21 +834,17 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
765 if (ret < 0) 834 if (ret < 0)
766 goto err_stop; 835 goto err_stop;
767 836
768 ret = vsp1_video_pipeline_init(pipe, video);
769 if (ret < 0)
770 goto err_stop;
771
772 /* Start the queue. */ 837 /* Start the queue. */
773 ret = vb2_streamon(&video->queue, type); 838 ret = vb2_streamon(&video->queue, type);
774 if (ret < 0) 839 if (ret < 0)
775 goto err_cleanup; 840 goto err_stop;
776 841
777 return 0; 842 return 0;
778 843
779err_cleanup:
780 vsp1_video_pipeline_cleanup(pipe);
781err_stop: 844err_stop:
782 media_entity_pipeline_stop(&video->video.entity); 845 media_entity_pipeline_stop(&video->video.entity);
846err_pipe:
847 vsp1_video_pipeline_put(pipe);
783 return ret; 848 return ret;
784} 849}
785 850
@@ -895,26 +960,16 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
895 spin_lock_init(&video->irqlock); 960 spin_lock_init(&video->irqlock);
896 INIT_LIST_HEAD(&video->irqqueue); 961 INIT_LIST_HEAD(&video->irqqueue);
897 962
898 vsp1_pipeline_init(&video->pipe);
899 video->pipe.frame_end = vsp1_video_pipeline_frame_end;
900
901 /* Initialize the media entity... */ 963 /* Initialize the media entity... */
902 ret = media_entity_pads_init(&video->video.entity, 1, &video->pad); 964 ret = media_entity_pads_init(&video->video.entity, 1, &video->pad);
903 if (ret < 0) 965 if (ret < 0)
904 return ERR_PTR(ret); 966 return ERR_PTR(ret);
905 967
906 /* ... and the format ... */ 968 /* ... and the format ... */
907 rwpf->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT); 969 rwpf->format.pixelformat = VSP1_VIDEO_DEF_FORMAT;
908 rwpf->format.pixelformat = rwpf->fmtinfo->fourcc;
909 rwpf->format.colorspace = V4L2_COLORSPACE_SRGB;
910 rwpf->format.field = V4L2_FIELD_NONE;
911 rwpf->format.width = VSP1_VIDEO_DEF_WIDTH; 970 rwpf->format.width = VSP1_VIDEO_DEF_WIDTH;
912 rwpf->format.height = VSP1_VIDEO_DEF_HEIGHT; 971 rwpf->format.height = VSP1_VIDEO_DEF_HEIGHT;
913 rwpf->format.num_planes = 1; 972 __vsp1_video_try_format(video, &rwpf->format, &rwpf->fmtinfo);
914 rwpf->format.plane_fmt[0].bytesperline =
915 rwpf->format.width * rwpf->fmtinfo->bpp[0] / 8;
916 rwpf->format.plane_fmt[0].sizeimage =
917 rwpf->format.plane_fmt[0].bytesperline * rwpf->format.height;
918 973
919 /* ... and the video node... */ 974 /* ... and the video node... */
920 video->video.v4l2_dev = &video->vsp1->v4l2_dev; 975 video->video.v4l2_dev = &video->vsp1->v4l2_dev;
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index 64abd39ee1e7..867b00807c46 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -18,7 +18,6 @@
18 18
19#include <media/videobuf2-v4l2.h> 19#include <media/videobuf2-v4l2.h>
20 20
21#include "vsp1_pipe.h"
22#include "vsp1_rwpf.h" 21#include "vsp1_rwpf.h"
23 22
24struct vsp1_vb2_buffer { 23struct vsp1_vb2_buffer {
@@ -44,7 +43,6 @@ struct vsp1_video {
44 43
45 struct mutex lock; 44 struct mutex lock;
46 45
47 struct vsp1_pipeline pipe;
48 unsigned int pipe_index; 46 unsigned int pipe_index;
49 47
50 struct vb2_queue queue; 48 struct vb2_queue queue;
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index c78d4af50fcf..6c91eaa35e75 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -16,124 +16,114 @@
16#include <media/v4l2-subdev.h> 16#include <media/v4l2-subdev.h>
17 17
18#include "vsp1.h" 18#include "vsp1.h"
19#include "vsp1_dl.h"
20#include "vsp1_pipe.h"
19#include "vsp1_rwpf.h" 21#include "vsp1_rwpf.h"
20#include "vsp1_video.h" 22#include "vsp1_video.h"
21 23
22#define WPF_MAX_WIDTH 2048 24#define WPF_GEN2_MAX_WIDTH 2048U
23#define WPF_MAX_HEIGHT 2048 25#define WPF_GEN2_MAX_HEIGHT 2048U
26#define WPF_GEN3_MAX_WIDTH 8190U
27#define WPF_GEN3_MAX_HEIGHT 8190U
24 28
25/* ----------------------------------------------------------------------------- 29/* -----------------------------------------------------------------------------
26 * Device Access 30 * Device Access
27 */ 31 */
28 32
29static inline u32 vsp1_wpf_read(struct vsp1_rwpf *wpf, u32 reg) 33static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf,
34 struct vsp1_dl_list *dl, u32 reg, u32 data)
30{ 35{
31 return vsp1_read(wpf->entity.vsp1, 36 vsp1_dl_list_write(dl, reg + wpf->entity.index * VI6_WPF_OFFSET, data);
32 reg + wpf->entity.index * VI6_WPF_OFFSET);
33}
34
35static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data)
36{
37 vsp1_mod_write(&wpf->entity,
38 reg + wpf->entity.index * VI6_WPF_OFFSET, data);
39} 37}
40 38
41/* ----------------------------------------------------------------------------- 39/* -----------------------------------------------------------------------------
42 * Controls 40 * V4L2 Subdevice Core Operations
43 */ 41 */
44 42
45static int wpf_s_ctrl(struct v4l2_ctrl *ctrl) 43static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
46{ 44{
47 struct vsp1_rwpf *wpf = 45 struct vsp1_rwpf *wpf = to_rwpf(subdev);
48 container_of(ctrl->handler, struct vsp1_rwpf, ctrls); 46 struct vsp1_device *vsp1 = wpf->entity.vsp1;
49 u32 value;
50 47
51 if (!vsp1_entity_is_streaming(&wpf->entity)) 48 if (enable)
52 return 0; 49 return 0;
53 50
54 switch (ctrl->id) { 51 /* Write to registers directly when stopping the stream as there will be
55 case V4L2_CID_ALPHA_COMPONENT: 52 * no pipeline run to apply the display list.
56 value = vsp1_wpf_read(wpf, VI6_WPF_OUTFMT); 53 */
57 value &= ~VI6_WPF_OUTFMT_PDV_MASK; 54 vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0);
58 value |= ctrl->val << VI6_WPF_OUTFMT_PDV_SHIFT; 55 vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET +
59 vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, value); 56 VI6_WPF_SRCRPF, 0);
60 break;
61 }
62 57
63 return 0; 58 return 0;
64} 59}
65 60
66static const struct v4l2_ctrl_ops wpf_ctrl_ops = {
67 .s_ctrl = wpf_s_ctrl,
68};
69
70/* ----------------------------------------------------------------------------- 61/* -----------------------------------------------------------------------------
71 * V4L2 Subdevice Core Operations 62 * V4L2 Subdevice Operations
72 */ 63 */
73 64
74static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) 65static struct v4l2_subdev_video_ops wpf_video_ops = {
75{ 66 .s_stream = wpf_s_stream,
76 struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); 67};
77 struct vsp1_rwpf *wpf = to_rwpf(subdev);
78 struct vsp1_device *vsp1 = wpf->entity.vsp1;
79 const struct v4l2_rect *crop = &wpf->crop;
80 unsigned int i;
81 u32 srcrpf = 0;
82 u32 outfmt = 0;
83 int ret;
84
85 ret = vsp1_entity_set_streaming(&wpf->entity, enable);
86 if (ret < 0)
87 return ret;
88 68
89 if (!enable) { 69static struct v4l2_subdev_ops wpf_ops = {
90 vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); 70 .video = &wpf_video_ops,
91 vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + 71 .pad = &vsp1_rwpf_pad_ops,
92 VI6_WPF_SRCRPF, 0); 72};
93 return 0;
94 }
95 73
96 /* Sources. If the pipeline has a single input and BRU is not used, 74/* -----------------------------------------------------------------------------
97 * configure it as the master layer. Otherwise configure all 75 * VSP1 Entity Operations
98 * inputs as sub-layers and select the virtual RPF as the master 76 */
99 * layer.
100 */
101 for (i = 0; i < vsp1->info->rpf_count; ++i) {
102 struct vsp1_rwpf *input = pipe->inputs[i];
103 77
104 if (!input) 78static void vsp1_wpf_destroy(struct vsp1_entity *entity)
105 continue; 79{
80 struct vsp1_rwpf *wpf = entity_to_rwpf(entity);
106 81
107 srcrpf |= (!pipe->bru && pipe->num_inputs == 1) 82 vsp1_dlm_destroy(wpf->dlm);
108 ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index) 83}
109 : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
110 }
111 84
112 if (pipe->bru || pipe->num_inputs > 1) 85static void wpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl)
113 srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST; 86{
87 struct vsp1_rwpf *wpf = entity_to_rwpf(entity);
114 88
115 vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf); 89 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, wpf->mem.addr[0]);
90 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, wpf->mem.addr[1]);
91 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, wpf->mem.addr[2]);
92}
116 93
117 /* Destination stride. */ 94static void wpf_configure(struct vsp1_entity *entity,
118 if (!pipe->lif) { 95 struct vsp1_pipeline *pipe,
119 struct v4l2_pix_format_mplane *format = &wpf->format; 96 struct vsp1_dl_list *dl)
97{
98 struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev);
99 struct vsp1_device *vsp1 = wpf->entity.vsp1;
100 const struct v4l2_mbus_framefmt *source_format;
101 const struct v4l2_mbus_framefmt *sink_format;
102 const struct v4l2_rect *crop;
103 unsigned int i;
104 u32 outfmt = 0;
105 u32 srcrpf = 0;
120 106
121 vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_Y, 107 /* Cropping */
122 format->plane_fmt[0].bytesperline); 108 crop = vsp1_rwpf_get_crop(wpf, wpf->entity.config);
123 if (format->num_planes > 1)
124 vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_C,
125 format->plane_fmt[1].bytesperline);
126 }
127 109
128 vsp1_wpf_write(wpf, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | 110 vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN |
129 (crop->left << VI6_WPF_SZCLIP_OFST_SHIFT) | 111 (crop->left << VI6_WPF_SZCLIP_OFST_SHIFT) |
130 (crop->width << VI6_WPF_SZCLIP_SIZE_SHIFT)); 112 (crop->width << VI6_WPF_SZCLIP_SIZE_SHIFT));
131 vsp1_wpf_write(wpf, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN | 113 vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN |
132 (crop->top << VI6_WPF_SZCLIP_OFST_SHIFT) | 114 (crop->top << VI6_WPF_SZCLIP_OFST_SHIFT) |
133 (crop->height << VI6_WPF_SZCLIP_SIZE_SHIFT)); 115 (crop->height << VI6_WPF_SZCLIP_SIZE_SHIFT));
134 116
135 /* Format */ 117 /* Format */
118 sink_format = vsp1_entity_get_pad_format(&wpf->entity,
119 wpf->entity.config,
120 RWPF_PAD_SINK);
121 source_format = vsp1_entity_get_pad_format(&wpf->entity,
122 wpf->entity.config,
123 RWPF_PAD_SOURCE);
124
136 if (!pipe->lif) { 125 if (!pipe->lif) {
126 const struct v4l2_pix_format_mplane *format = &wpf->format;
137 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; 127 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
138 128
139 outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT; 129 outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT;
@@ -145,73 +135,58 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
145 if (fmtinfo->swap_uv) 135 if (fmtinfo->swap_uv)
146 outfmt |= VI6_WPF_OUTFMT_SPUVS; 136 outfmt |= VI6_WPF_OUTFMT_SPUVS;
147 137
148 vsp1_wpf_write(wpf, VI6_WPF_DSWAP, fmtinfo->swap); 138 /* Destination stride and byte swapping. */
139 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_STRIDE_Y,
140 format->plane_fmt[0].bytesperline);
141 if (format->num_planes > 1)
142 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_STRIDE_C,
143 format->plane_fmt[1].bytesperline);
144
145 vsp1_wpf_write(wpf, dl, VI6_WPF_DSWAP, fmtinfo->swap);
149 } 146 }
150 147
151 if (wpf->entity.formats[RWPF_PAD_SINK].code != 148 if (sink_format->code != source_format->code)
152 wpf->entity.formats[RWPF_PAD_SOURCE].code)
153 outfmt |= VI6_WPF_OUTFMT_CSC; 149 outfmt |= VI6_WPF_OUTFMT_CSC;
154 150
155 /* Take the control handler lock to ensure that the PDV value won't be 151 outfmt |= wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT;
156 * changed behind our back by a set control operation. 152 vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, outfmt);
157 */
158 if (vsp1->info->uapi)
159 mutex_lock(wpf->ctrls.lock);
160 outfmt |= wpf->alpha->cur.val << VI6_WPF_OUTFMT_PDV_SHIFT;
161 vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt);
162 if (vsp1->info->uapi)
163 mutex_unlock(wpf->ctrls.lock);
164
165 vsp1_mod_write(&wpf->entity, VI6_DPR_WPF_FPORCH(wpf->entity.index),
166 VI6_DPR_WPF_FPORCH_FP_WPFN);
167 153
168 vsp1_mod_write(&wpf->entity, VI6_WPF_WRBCK_CTRL, 0); 154 vsp1_dl_list_write(dl, VI6_DPR_WPF_FPORCH(wpf->entity.index),
155 VI6_DPR_WPF_FPORCH_FP_WPFN);
169 156
170 /* Enable interrupts */ 157 vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0);
171 vsp1_write(vsp1, VI6_WPF_IRQ_STA(wpf->entity.index), 0);
172 vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index),
173 VI6_WFP_IRQ_ENB_FREE);
174
175 return 0;
176}
177 158
178/* ----------------------------------------------------------------------------- 159 /* Sources. If the pipeline has a single input and BRU is not used,
179 * V4L2 Subdevice Operations 160 * configure it as the master layer. Otherwise configure all
180 */ 161 * inputs as sub-layers and select the virtual RPF as the master
162 * layer.
163 */
164 for (i = 0; i < vsp1->info->rpf_count; ++i) {
165 struct vsp1_rwpf *input = pipe->inputs[i];
181 166
182static struct v4l2_subdev_video_ops wpf_video_ops = { 167 if (!input)
183 .s_stream = wpf_s_stream, 168 continue;
184};
185 169
186static struct v4l2_subdev_pad_ops wpf_pad_ops = { 170 srcrpf |= (!pipe->bru && pipe->num_inputs == 1)
187 .enum_mbus_code = vsp1_rwpf_enum_mbus_code, 171 ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
188 .enum_frame_size = vsp1_rwpf_enum_frame_size, 172 : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
189 .get_fmt = vsp1_rwpf_get_format, 173 }
190 .set_fmt = vsp1_rwpf_set_format,
191 .get_selection = vsp1_rwpf_get_selection,
192 .set_selection = vsp1_rwpf_set_selection,
193};
194 174
195static struct v4l2_subdev_ops wpf_ops = { 175 if (pipe->bru || pipe->num_inputs > 1)
196 .video = &wpf_video_ops, 176 srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST;
197 .pad = &wpf_pad_ops,
198};
199 177
200/* ----------------------------------------------------------------------------- 178 vsp1_wpf_write(wpf, dl, VI6_WPF_SRCRPF, srcrpf);
201 * Video Device Operations
202 */
203 179
204static void wpf_set_memory(struct vsp1_rwpf *wpf, struct vsp1_rwpf_memory *mem) 180 /* Enable interrupts */
205{ 181 vsp1_dl_list_write(dl, VI6_WPF_IRQ_STA(wpf->entity.index), 0);
206 vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, mem->addr[0]); 182 vsp1_dl_list_write(dl, VI6_WPF_IRQ_ENB(wpf->entity.index),
207 if (mem->num_planes > 1) 183 VI6_WFP_IRQ_ENB_FREE);
208 vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, mem->addr[1]);
209 if (mem->num_planes > 2)
210 vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, mem->addr[2]);
211} 184}
212 185
213static const struct vsp1_rwpf_operations wpf_vdev_ops = { 186static const struct vsp1_entity_operations wpf_entity_ops = {
187 .destroy = vsp1_wpf_destroy,
214 .set_memory = wpf_set_memory, 188 .set_memory = wpf_set_memory,
189 .configure = wpf_configure,
215}; 190};
216 191
217/* ----------------------------------------------------------------------------- 192/* -----------------------------------------------------------------------------
@@ -220,51 +195,43 @@ static const struct vsp1_rwpf_operations wpf_vdev_ops = {
220 195
221struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) 196struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
222{ 197{
223 struct v4l2_subdev *subdev;
224 struct vsp1_rwpf *wpf; 198 struct vsp1_rwpf *wpf;
199 char name[6];
225 int ret; 200 int ret;
226 201
227 wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL); 202 wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL);
228 if (wpf == NULL) 203 if (wpf == NULL)
229 return ERR_PTR(-ENOMEM); 204 return ERR_PTR(-ENOMEM);
230 205
231 wpf->ops = &wpf_vdev_ops; 206 if (vsp1->info->gen == 2) {
232 207 wpf->max_width = WPF_GEN2_MAX_WIDTH;
233 wpf->max_width = WPF_MAX_WIDTH; 208 wpf->max_height = WPF_GEN2_MAX_HEIGHT;
234 wpf->max_height = WPF_MAX_HEIGHT; 209 } else {
210 wpf->max_width = WPF_GEN3_MAX_WIDTH;
211 wpf->max_height = WPF_GEN3_MAX_HEIGHT;
212 }
235 213
214 wpf->entity.ops = &wpf_entity_ops;
236 wpf->entity.type = VSP1_ENTITY_WPF; 215 wpf->entity.type = VSP1_ENTITY_WPF;
237 wpf->entity.index = index; 216 wpf->entity.index = index;
238 217
239 ret = vsp1_entity_init(vsp1, &wpf->entity, 2); 218 sprintf(name, "wpf.%u", index);
219 ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops);
240 if (ret < 0) 220 if (ret < 0)
241 return ERR_PTR(ret); 221 return ERR_PTR(ret);
242 222
243 /* Initialize the V4L2 subdev. */ 223 /* Initialize the display list manager. */
244 subdev = &wpf->entity.subdev; 224 wpf->dlm = vsp1_dlm_create(vsp1, index, 4);
245 v4l2_subdev_init(subdev, &wpf_ops); 225 if (!wpf->dlm) {
246 226 ret = -ENOMEM;
247 subdev->entity.ops = &vsp1->media_ops; 227 goto error;
248 subdev->internal_ops = &vsp1_subdev_internal_ops; 228 }
249 snprintf(subdev->name, sizeof(subdev->name), "%s wpf.%u",
250 dev_name(vsp1->dev), index);
251 v4l2_set_subdevdata(subdev, wpf);
252 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
253
254 vsp1_entity_init_formats(subdev, NULL);
255 229
256 /* Initialize the control handler. */ 230 /* Initialize the control handler. */
257 v4l2_ctrl_handler_init(&wpf->ctrls, 1); 231 ret = vsp1_rwpf_init_ctrls(wpf);
258 wpf->alpha = v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, 232 if (ret < 0) {
259 V4L2_CID_ALPHA_COMPONENT,
260 0, 255, 1, 255);
261
262 wpf->entity.subdev.ctrl_handler = &wpf->ctrls;
263
264 if (wpf->ctrls.error) {
265 dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n", 233 dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
266 index); 234 index);
267 ret = wpf->ctrls.error;
268 goto error; 235 goto error;
269 } 236 }
270 237
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index e795a4501e8b..feb3b2f1d874 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -351,19 +351,15 @@ static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
351 struct xvip_graph_entity *entity; 351 struct xvip_graph_entity *entity;
352 struct device_node *remote; 352 struct device_node *remote;
353 struct device_node *ep = NULL; 353 struct device_node *ep = NULL;
354 struct device_node *next;
355 int ret = 0; 354 int ret = 0;
356 355
357 dev_dbg(xdev->dev, "parsing node %s\n", node->full_name); 356 dev_dbg(xdev->dev, "parsing node %s\n", node->full_name);
358 357
359 while (1) { 358 while (1) {
360 next = of_graph_get_next_endpoint(node, ep); 359 ep = of_graph_get_next_endpoint(node, ep);
361 if (next == NULL) 360 if (ep == NULL)
362 break; 361 break;
363 362
364 of_node_put(ep);
365 ep = next;
366
367 dev_dbg(xdev->dev, "handling endpoint %s\n", ep->full_name); 363 dev_dbg(xdev->dev, "handling endpoint %s\n", ep->full_name);
368 364
369 remote = of_graph_get_remote_port_parent(ep); 365 remote = of_graph_get_remote_port_parent(ep);
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 3f61d77d4147..9f5b59706741 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -873,13 +873,10 @@ static int ati_remote_probe(struct usb_interface *interface,
873 strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys)); 873 strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys));
874 strlcat(ati_remote->mouse_phys, "/input1", sizeof(ati_remote->mouse_phys)); 874 strlcat(ati_remote->mouse_phys, "/input1", sizeof(ati_remote->mouse_phys));
875 875
876 if (udev->manufacturer) 876 snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name), "%s%s%s",
877 strlcpy(ati_remote->rc_name, udev->manufacturer, 877 udev->manufacturer ?: "",
878 sizeof(ati_remote->rc_name)); 878 udev->manufacturer && udev->product ? " " : "",
879 879 udev->product ?: "");
880 if (udev->product)
881 snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
882 "%s %s", ati_remote->rc_name, udev->product);
883 880
884 if (!strlen(ati_remote->rc_name)) 881 if (!strlen(ati_remote->rc_name))
885 snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name), 882 snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 35155ae500c7..5cf2e749b9eb 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -188,6 +188,7 @@
188#define VENDOR_TWISTEDMELON 0x2596 188#define VENDOR_TWISTEDMELON 0x2596
189#define VENDOR_HAUPPAUGE 0x2040 189#define VENDOR_HAUPPAUGE 0x2040
190#define VENDOR_PCTV 0x2013 190#define VENDOR_PCTV 0x2013
191#define VENDOR_ADAPTEC 0x03f3
191 192
192enum mceusb_model_type { 193enum mceusb_model_type {
193 MCE_GEN2 = 0, /* Most boards */ 194 MCE_GEN2 = 0, /* Most boards */
@@ -302,6 +303,9 @@ static struct usb_device_id mceusb_dev_table[] = {
302 /* SMK/I-O Data GV-MC7/RCKIT Receiver */ 303 /* SMK/I-O Data GV-MC7/RCKIT Receiver */
303 { USB_DEVICE(VENDOR_SMK, 0x0353), 304 { USB_DEVICE(VENDOR_SMK, 0x0353),
304 .driver_info = MCE_GEN2_NO_TX }, 305 .driver_info = MCE_GEN2_NO_TX },
306 /* SMK RXX6000 Infrared Receiver */
307 { USB_DEVICE(VENDOR_SMK, 0x0357),
308 .driver_info = MCE_GEN2_NO_TX },
305 /* Tatung eHome Infrared Transceiver */ 309 /* Tatung eHome Infrared Transceiver */
306 { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, 310 { USB_DEVICE(VENDOR_TATUNG, 0x9150) },
307 /* Shuttle eHome Infrared Transceiver */ 311 /* Shuttle eHome Infrared Transceiver */
@@ -405,6 +409,8 @@ static struct usb_device_id mceusb_dev_table[] = {
405 .driver_info = HAUPPAUGE_CX_HYBRID_TV }, 409 .driver_info = HAUPPAUGE_CX_HYBRID_TV },
406 { USB_DEVICE(VENDOR_PCTV, 0x025e), 410 { USB_DEVICE(VENDOR_PCTV, 0x025e),
407 .driver_info = HAUPPAUGE_CX_HYBRID_TV }, 411 .driver_info = HAUPPAUGE_CX_HYBRID_TV },
412 /* Adaptec / HP eHome Receiver */
413 { USB_DEVICE(VENDOR_ADAPTEC, 0x0094) },
408 414
409 /* Terminating entry */ 415 /* Terminating entry */
410 { } 416 { }
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 4e9bbe735ae9..7dfc7c2188f0 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1263,6 +1263,9 @@ unlock:
1263 1263
1264static void rc_dev_release(struct device *device) 1264static void rc_dev_release(struct device *device)
1265{ 1265{
1266 struct rc_dev *dev = to_rc_dev(device);
1267
1268 kfree(dev);
1266} 1269}
1267 1270
1268#define ADD_HOTPLUG_VAR(fmt, val...) \ 1271#define ADD_HOTPLUG_VAR(fmt, val...) \
@@ -1384,7 +1387,9 @@ void rc_free_device(struct rc_dev *dev)
1384 1387
1385 put_device(&dev->dev); 1388 put_device(&dev->dev);
1386 1389
1387 kfree(dev); 1390 /* kfree(dev) will be called by the callback function
1391 rc_dev_release() */
1392
1388 module_put(THIS_MODULE); 1393 module_put(THIS_MODULE);
1389} 1394}
1390EXPORT_SYMBOL_GPL(rc_free_device); 1395EXPORT_SYMBOL_GPL(rc_free_device);
@@ -1492,9 +1497,7 @@ int rc_register_device(struct rc_dev *dev)
1492 } 1497 }
1493 1498
1494 /* Allow the RC sysfs nodes to be accessible */ 1499 /* Allow the RC sysfs nodes to be accessible */
1495 mutex_lock(&dev->lock);
1496 atomic_set(&dev->initialized, 1); 1500 atomic_set(&dev->initialized, 1);
1497 mutex_unlock(&dev->lock);
1498 1501
1499 IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n", 1502 IR_dprintk(1, "Registered rc%u (driver: %s, remote: %s, mode %s)\n",
1500 dev->minor, 1503 dev->minor,
diff --git a/drivers/media/tuners/qm1d1c0042.c b/drivers/media/tuners/qm1d1c0042.c
index 18bc745ed108..9af2a155cfca 100644
--- a/drivers/media/tuners/qm1d1c0042.c
+++ b/drivers/media/tuners/qm1d1c0042.c
@@ -32,14 +32,24 @@
32#include "qm1d1c0042.h" 32#include "qm1d1c0042.h"
33 33
34#define QM1D1C0042_NUM_REGS 0x20 34#define QM1D1C0042_NUM_REGS 0x20
35 35#define QM1D1C0042_NUM_REG_ROWS 2
36static const u8 reg_initval[QM1D1C0042_NUM_REGS] = { 36
37 0x48, 0x1c, 0xa0, 0x10, 0xbc, 0xc5, 0x20, 0x33, 37static const u8
38 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 38reg_initval[QM1D1C0042_NUM_REG_ROWS][QM1D1C0042_NUM_REGS] = { {
39 0x00, 0xff, 0xf3, 0x00, 0x2a, 0x64, 0xa6, 0x86, 39 0x48, 0x1c, 0xa0, 0x10, 0xbc, 0xc5, 0x20, 0x33,
40 0x8c, 0xcf, 0xb8, 0xf1, 0xa8, 0xf2, 0x89, 0x00 40 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
41 0x00, 0xff, 0xf3, 0x00, 0x2a, 0x64, 0xa6, 0x86,
42 0x8c, 0xcf, 0xb8, 0xf1, 0xa8, 0xf2, 0x89, 0x00
43 }, {
44 0x68, 0x1c, 0xc0, 0x10, 0xbc, 0xc1, 0x11, 0x33,
45 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
46 0x00, 0xff, 0xf3, 0x00, 0x3f, 0x25, 0x5c, 0xd6,
47 0x55, 0xcf, 0x95, 0xf6, 0x36, 0xf2, 0x09, 0x00
48 }
41}; 49};
42 50
51static int reg_index;
52
43static const struct qm1d1c0042_config default_cfg = { 53static const struct qm1d1c0042_config default_cfg = {
44 .xtal_freq = 16000, 54 .xtal_freq = 16000,
45 .lpf = 1, 55 .lpf = 1,
@@ -320,7 +330,6 @@ static int qm1d1c0042_init(struct dvb_frontend *fe)
320 int i, ret; 330 int i, ret;
321 331
322 state = fe->tuner_priv; 332 state = fe->tuner_priv;
323 memcpy(state->regs, reg_initval, sizeof(reg_initval));
324 333
325 reg_write(state, 0x01, 0x0c); 334 reg_write(state, 0x01, 0x0c);
326 reg_write(state, 0x01, 0x0c); 335 reg_write(state, 0x01, 0x0c);
@@ -330,15 +339,22 @@ static int qm1d1c0042_init(struct dvb_frontend *fe)
330 goto failed; 339 goto failed;
331 usleep_range(2000, 3000); 340 usleep_range(2000, 3000);
332 341
333 val = state->regs[0x01] | 0x10; 342 ret = reg_write(state, 0x01, 0x1c); /* soft reset off */
334 ret = reg_write(state, 0x01, val); /* soft reset off */
335 if (ret < 0) 343 if (ret < 0)
336 goto failed; 344 goto failed;
337 345
338 /* check ID */ 346 /* check ID and choose initial registers corresponding ID */
339 ret = reg_read(state, 0x00, &val); 347 ret = reg_read(state, 0x00, &val);
340 if (ret < 0 || val != 0x48) 348 if (ret < 0)
349 goto failed;
350 for (reg_index = 0; reg_index < QM1D1C0042_NUM_REG_ROWS;
351 reg_index++) {
352 if (val == reg_initval[reg_index][0x00])
353 break;
354 }
355 if (reg_index >= QM1D1C0042_NUM_REG_ROWS)
341 goto failed; 356 goto failed;
357 memcpy(state->regs, reg_initval[reg_index], QM1D1C0042_NUM_REGS);
342 usleep_range(2000, 3000); 358 usleep_range(2000, 3000);
343 359
344 state->regs[0x0c] |= 0x40; 360 state->regs[0x0c] |= 0x40;
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 243ac3816028..b07a681f3fbc 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -84,11 +84,22 @@ static int si2157_init(struct dvb_frontend *fe)
84 struct si2157_cmd cmd; 84 struct si2157_cmd cmd;
85 const struct firmware *fw; 85 const struct firmware *fw;
86 const char *fw_name; 86 const char *fw_name;
87 unsigned int chip_id; 87 unsigned int uitmp, chip_id;
88 88
89 dev_dbg(&client->dev, "\n"); 89 dev_dbg(&client->dev, "\n");
90 90
91 if (dev->fw_loaded) 91 /* Returned IF frequency is garbage when firmware is not running */
92 memcpy(cmd.args, "\x15\x00\x06\x07", 4);
93 cmd.wlen = 4;
94 cmd.rlen = 4;
95 ret = si2157_cmd_execute(client, &cmd);
96 if (ret)
97 goto err;
98
99 uitmp = cmd.args[2] << 0 | cmd.args[3] << 8;
100 dev_dbg(&client->dev, "if_frequency kHz=%u\n", uitmp);
101
102 if (uitmp == dev->if_frequency / 1000)
92 goto warm; 103 goto warm;
93 104
94 /* power up */ 105 /* power up */
@@ -203,9 +214,6 @@ skip_fw_download:
203 214
204 dev_info(&client->dev, "firmware version: %c.%c.%d\n", 215 dev_info(&client->dev, "firmware version: %c.%c.%d\n",
205 cmd.args[6], cmd.args[7], cmd.args[8]); 216 cmd.args[6], cmd.args[7], cmd.args[8]);
206
207 dev->fw_loaded = true;
208
209warm: 217warm:
210 /* init statistics in order signal app which are supported */ 218 /* init statistics in order signal app which are supported */
211 c->strength.len = 1; 219 c->strength.len = 1;
@@ -422,7 +430,6 @@ static int si2157_probe(struct i2c_client *client,
422 dev->fe = cfg->fe; 430 dev->fe = cfg->fe;
423 dev->inversion = cfg->inversion; 431 dev->inversion = cfg->inversion;
424 dev->if_port = cfg->if_port; 432 dev->if_port = cfg->if_port;
425 dev->fw_loaded = false;
426 dev->chiptype = (u8)id->driver_data; 433 dev->chiptype = (u8)id->driver_data;
427 dev->if_frequency = 5000000; /* default value of property 0x0706 */ 434 dev->if_frequency = 5000000; /* default value of property 0x0706 */
428 mutex_init(&dev->i2c_mutex); 435 mutex_init(&dev->i2c_mutex);
diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h
index 589d558d381c..d6b2c7b44053 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -26,7 +26,6 @@ struct si2157_dev {
26 struct mutex i2c_mutex; 26 struct mutex i2c_mutex;
27 struct dvb_frontend *fe; 27 struct dvb_frontend *fe;
28 bool active; 28 bool active;
29 bool fw_loaded;
30 bool inversion; 29 bool inversion;
31 u8 chiptype; 30 u8 chiptype;
32 u8 if_port; 31 u8 if_port;
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index cc22b32776ad..321ea5cf1329 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -131,22 +131,36 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
131 return status; 131 return status;
132} 132}
133 133
134#ifdef CONFIG_MEDIA_CONTROLLER
135static void au0828_media_graph_notify(struct media_entity *new,
136 void *notify_data);
137#endif
138
134static void au0828_unregister_media_device(struct au0828_dev *dev) 139static void au0828_unregister_media_device(struct au0828_dev *dev)
135{ 140{
136
137#ifdef CONFIG_MEDIA_CONTROLLER 141#ifdef CONFIG_MEDIA_CONTROLLER
138 if (dev->media_dev && 142 struct media_device *mdev = dev->media_dev;
139 media_devnode_is_registered(&dev->media_dev->devnode)) { 143 struct media_entity_notify *notify, *nextp;
140 /* clear enable_source, disable_source */ 144
141 dev->media_dev->source_priv = NULL; 145 if (!mdev || !media_devnode_is_registered(&mdev->devnode))
142 dev->media_dev->enable_source = NULL; 146 return;
143 dev->media_dev->disable_source = NULL; 147
144 148 /* Remove au0828 entity_notify callbacks */
145 media_device_unregister(dev->media_dev); 149 list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list) {
146 media_device_cleanup(dev->media_dev); 150 if (notify->notify != au0828_media_graph_notify)
147 kfree(dev->media_dev); 151 continue;
148 dev->media_dev = NULL; 152 media_device_unregister_entity_notify(mdev, notify);
149 } 153 }
154
155 /* clear enable_source, disable_source */
156 dev->media_dev->source_priv = NULL;
157 dev->media_dev->enable_source = NULL;
158 dev->media_dev->disable_source = NULL;
159
160 media_device_unregister(dev->media_dev);
161 media_device_cleanup(dev->media_dev);
162 kfree(dev->media_dev);
163 dev->media_dev = NULL;
150#endif 164#endif
151} 165}
152 166
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 32d7db96479c..7d0ec4cb248c 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -679,8 +679,6 @@ int au0828_v4l2_device_register(struct usb_interface *interface,
679 if (retval) { 679 if (retval) {
680 pr_err("%s() v4l2_device_register failed\n", 680 pr_err("%s() v4l2_device_register failed\n",
681 __func__); 681 __func__);
682 mutex_unlock(&dev->lock);
683 kfree(dev);
684 return retval; 682 return retval;
685 } 683 }
686 684
@@ -691,8 +689,6 @@ int au0828_v4l2_device_register(struct usb_interface *interface,
691 if (retval) { 689 if (retval) {
692 pr_err("%s() v4l2_ctrl_handler_init failed\n", 690 pr_err("%s() v4l2_ctrl_handler_init failed\n",
693 __func__); 691 __func__);
694 mutex_unlock(&dev->lock);
695 kfree(dev);
696 return retval; 692 return retval;
697 } 693 }
698 dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl; 694 dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl;
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 87f32846f1c0..dd7b378fe070 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -55,7 +55,6 @@
55#define NTSC_STD_H 480 55#define NTSC_STD_H 480
56 56
57#define AU0828_INTERLACED_DEFAULT 1 57#define AU0828_INTERLACED_DEFAULT 1
58#define V4L2_CID_PRIVATE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0)
59 58
60/* Defination for AU0828 USB transfer */ 59/* Defination for AU0828 USB transfer */
61#define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ 60#define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
index c9320d6c6131..00da024b47a6 100644
--- a/drivers/media/usb/cx231xx/cx231xx-417.c
+++ b/drivers/media/usb/cx231xx/cx231xx-417.c
@@ -360,7 +360,7 @@ static int wait_for_mci_complete(struct cx231xx *dev)
360 360
361 if (count++ > 100) { 361 if (count++ > 100) {
362 dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio); 362 dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio);
363 return -1; 363 return -EIO;
364 } 364 }
365 } 365 }
366 return 0; 366 return 0;
@@ -856,7 +856,7 @@ static int cx231xx_find_mailbox(struct cx231xx *dev)
856 } 856 }
857 } 857 }
858 dprintk(3, "Mailbox signature values not found!\n"); 858 dprintk(3, "Mailbox signature values not found!\n");
859 return -1; 859 return -EIO;
860} 860}
861 861
862static void mci_write_memory_to_gpio(struct cx231xx *dev, u32 address, u32 value, 862static void mci_write_memory_to_gpio(struct cx231xx *dev, u32 address, u32 value,
@@ -960,13 +960,14 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
960 p_fw = p_current_fw; 960 p_fw = p_current_fw;
961 if (p_current_fw == NULL) { 961 if (p_current_fw == NULL) {
962 dprintk(2, "FAIL!!!\n"); 962 dprintk(2, "FAIL!!!\n");
963 return -1; 963 return -ENOMEM;
964 } 964 }
965 965
966 p_buffer = vmalloc(4096); 966 p_buffer = vmalloc(4096);
967 if (p_buffer == NULL) { 967 if (p_buffer == NULL) {
968 dprintk(2, "FAIL!!!\n"); 968 dprintk(2, "FAIL!!!\n");
969 return -1; 969 vfree(p_current_fw);
970 return -ENOMEM;
970 } 971 }
971 972
972 dprintk(2, "%s()\n", __func__); 973 dprintk(2, "%s()\n", __func__);
@@ -989,7 +990,9 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
989 if (retval != 0) { 990 if (retval != 0) {
990 dev_err(dev->dev, 991 dev_err(dev->dev,
991 "%s: Error with mc417_register_write\n", __func__); 992 "%s: Error with mc417_register_write\n", __func__);
992 return -1; 993 vfree(p_current_fw);
994 vfree(p_buffer);
995 return retval;
993 } 996 }
994 997
995 retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME, 998 retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME,
@@ -1001,7 +1004,9 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
1001 CX231xx_FIRM_IMAGE_NAME); 1004 CX231xx_FIRM_IMAGE_NAME);
1002 dev_err(dev->dev, 1005 dev_err(dev->dev,
1003 "Please fix your hotplug setup, the board will not work without firmware loaded!\n"); 1006 "Please fix your hotplug setup, the board will not work without firmware loaded!\n");
1004 return -1; 1007 vfree(p_current_fw);
1008 vfree(p_buffer);
1009 return retval;
1005 } 1010 }
1006 1011
1007 if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) { 1012 if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) {
@@ -1009,14 +1014,18 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
1009 "ERROR: Firmware size mismatch (have %zd, expected %d)\n", 1014 "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
1010 firmware->size, CX231xx_FIRM_IMAGE_SIZE); 1015 firmware->size, CX231xx_FIRM_IMAGE_SIZE);
1011 release_firmware(firmware); 1016 release_firmware(firmware);
1012 return -1; 1017 vfree(p_current_fw);
1018 vfree(p_buffer);
1019 return -EINVAL;
1013 } 1020 }
1014 1021
1015 if (0 != memcmp(firmware->data, magic, 8)) { 1022 if (0 != memcmp(firmware->data, magic, 8)) {
1016 dev_err(dev->dev, 1023 dev_err(dev->dev,
1017 "ERROR: Firmware magic mismatch, wrong file?\n"); 1024 "ERROR: Firmware magic mismatch, wrong file?\n");
1018 release_firmware(firmware); 1025 release_firmware(firmware);
1019 return -1; 1026 vfree(p_current_fw);
1027 vfree(p_buffer);
1028 return -EINVAL;
1020 } 1029 }
1021 1030
1022 initGPIO(dev); 1031 initGPIO(dev);
@@ -1131,21 +1140,21 @@ static int cx231xx_initialize_codec(struct cx231xx *dev)
1131 if (retval < 0) { 1140 if (retval < 0) {
1132 dev_err(dev->dev, "%s: mailbox < 0, error\n", 1141 dev_err(dev->dev, "%s: mailbox < 0, error\n",
1133 __func__); 1142 __func__);
1134 return -1; 1143 return retval;
1135 } 1144 }
1136 dev->cx23417_mailbox = retval; 1145 dev->cx23417_mailbox = retval;
1137 retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); 1146 retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
1138 if (retval < 0) { 1147 if (retval < 0) {
1139 dev_err(dev->dev, 1148 dev_err(dev->dev,
1140 "ERROR: cx23417 firmware ping failed!\n"); 1149 "ERROR: cx23417 firmware ping failed!\n");
1141 return -1; 1150 return retval;
1142 } 1151 }
1143 retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, 1152 retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
1144 &version); 1153 &version);
1145 if (retval < 0) { 1154 if (retval < 0) {
1146 dev_err(dev->dev, 1155 dev_err(dev->dev,
1147 "ERROR: cx23417 firmware get encoder: version failed!\n"); 1156 "ERROR: cx23417 firmware get encoder: version failed!\n");
1148 return -1; 1157 return retval;
1149 } 1158 }
1150 dprintk(1, "cx23417 firmware version is 0x%08x\n", version); 1159 dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
1151 msleep(200); 1160 msleep(200);
diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c
index f497888d94bf..6741fd02b50f 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -752,7 +752,8 @@ EXPORT_SYMBOL_GPL(cx231xx_set_mode);
752int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size) 752int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size)
753{ 753{
754 int errCode = 0; 754 int errCode = 0;
755 int actlen, ret = -ENOMEM; 755 int actlen = -1;
756 int ret = -ENOMEM;
756 u32 *buffer; 757 u32 *buffer;
757 758
758 buffer = kzalloc(4096, GFP_KERNEL); 759 buffer = kzalloc(4096, GFP_KERNEL);
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h
index df22001f9e41..89e629a24aec 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.h
+++ b/drivers/media/usb/dvb-usb-v2/af9035.h
@@ -118,20 +118,20 @@ static const u32 clock_lut_it9135[] = {
118 * Values 0, 3 and 5 are seen to this day. 0 for single TS and 3/5 for dual TS. 118 * Values 0, 3 and 5 are seen to this day. 0 for single TS and 3/5 for dual TS.
119 */ 119 */
120 120
121#define EEPROM_BASE_AF9035 0x42fd 121#define EEPROM_BASE_AF9035 0x42f5
122#define EEPROM_BASE_IT9135 0x499c 122#define EEPROM_BASE_IT9135 0x4994
123#define EEPROM_SHIFT 0x10 123#define EEPROM_SHIFT 0x10
124 124
125#define EEPROM_IR_MODE 0x10 125#define EEPROM_IR_MODE 0x18
126#define EEPROM_TS_MODE 0x29 126#define EEPROM_TS_MODE 0x31
127#define EEPROM_2ND_DEMOD_ADDR 0x2a 127#define EEPROM_2ND_DEMOD_ADDR 0x32
128#define EEPROM_IR_TYPE 0x2c 128#define EEPROM_IR_TYPE 0x34
129#define EEPROM_1_IF_L 0x30 129#define EEPROM_1_IF_L 0x38
130#define EEPROM_1_IF_H 0x31 130#define EEPROM_1_IF_H 0x39
131#define EEPROM_1_TUNER_ID 0x34 131#define EEPROM_1_TUNER_ID 0x3c
132#define EEPROM_2_IF_L 0x40 132#define EEPROM_2_IF_L 0x48
133#define EEPROM_2_IF_H 0x41 133#define EEPROM_2_IF_H 0x49
134#define EEPROM_2_TUNER_ID 0x44 134#define EEPROM_2_TUNER_ID 0x4c
135 135
136/* USB commands */ 136/* USB commands */
137#define CMD_MEM_RD 0x00 137#define CMD_MEM_RD 0x00
diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c
index 92e47d6c3ee3..2e711362847e 100644
--- a/drivers/media/usb/dvb-usb/az6027.c
+++ b/drivers/media/usb/dvb-usb/az6027.c
@@ -1090,6 +1090,7 @@ static struct usb_device_id az6027_usb_table[] = {
1090 { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) }, 1090 { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) },
1091 { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) }, 1091 { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) },
1092 { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT_V2) }, 1092 { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT_V2) },
1093 { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT_V3) },
1093 { }, 1094 { },
1094}; 1095};
1095 1096
@@ -1138,7 +1139,7 @@ static struct dvb_usb_device_properties az6027_properties = {
1138 1139
1139 .i2c_algo = &az6027_i2c_algo, 1140 .i2c_algo = &az6027_i2c_algo,
1140 1141
1141 .num_device_descs = 7, 1142 .num_device_descs = 8,
1142 .devices = { 1143 .devices = {
1143 { 1144 {
1144 .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", 1145 .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)",
@@ -1168,6 +1169,10 @@ static struct dvb_usb_device_properties az6027_properties = {
1168 .name = "Elgato EyeTV Sat", 1169 .name = "Elgato EyeTV Sat",
1169 .cold_ids = { &az6027_usb_table[6], NULL }, 1170 .cold_ids = { &az6027_usb_table[6], NULL },
1170 .warm_ids = { NULL }, 1171 .warm_ids = { NULL },
1172 }, {
1173 .name = "Elgato EyeTV Sat",
1174 .cold_ids = { &az6027_usb_table[7], NULL },
1175 .warm_ids = { NULL },
1171 }, 1176 },
1172 { NULL }, 1177 { NULL },
1173 } 1178 }
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index ea0391e32d23..0857b56e652c 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -3814,6 +3814,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
3814 { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E) }, 3814 { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E) },
3815 { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E_SE) }, 3815 { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E_SE) },
3816 { USB_DEVICE(USB_VID_PCTV, USB_PID_DIBCOM_STK8096PVR) }, 3816 { USB_DEVICE(USB_VID_PCTV, USB_PID_DIBCOM_STK8096PVR) },
3817 { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096PVR) },
3817 { 0 } /* Terminating entry */ 3818 { 0 } /* Terminating entry */
3818}; 3819};
3819MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); 3820MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -5017,7 +5018,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
5017 .num_device_descs = 1, 5018 .num_device_descs = 1,
5018 .devices = { 5019 .devices = {
5019 { "DiBcom STK8096-PVR reference design", 5020 { "DiBcom STK8096-PVR reference design",
5020 { &dib0700_usb_id_table[83], NULL }, 5021 { &dib0700_usb_id_table[83],
5022 &dib0700_usb_id_table[84], NULL},
5021 { NULL }, 5023 { NULL },
5022 }, 5024 },
5023 }, 5025 },
diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c
index 35de6095926d..6eea4e68891d 100644
--- a/drivers/media/usb/dvb-usb/dibusb-common.c
+++ b/drivers/media/usb/dvb-usb/dibusb-common.c
@@ -184,6 +184,8 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
184} 184}
185EXPORT_SYMBOL(dibusb_read_eeprom_byte); 185EXPORT_SYMBOL(dibusb_read_eeprom_byte);
186 186
187#if IS_ENABLED(CONFIG_DVB_DIB3000MC)
188
187/* 3000MC/P stuff */ 189/* 3000MC/P stuff */
188// Config Adjacent channels Perf -cal22 190// Config Adjacent channels Perf -cal22
189static struct dibx000_agc_config dib3000p_mt2060_agc_config = { 191static struct dibx000_agc_config dib3000p_mt2060_agc_config = {
@@ -242,8 +244,6 @@ static struct dibx000_agc_config dib3000p_panasonic_agc_config = {
242 .agc2_slope2 = 0x1e, 244 .agc2_slope2 = 0x1e,
243}; 245};
244 246
245#if IS_ENABLED(CONFIG_DVB_DIB3000MC)
246
247static struct dib3000mc_config mod3000p_dib3000p_config = { 247static struct dib3000mc_config mod3000p_dib3000p_config = {
248 &dib3000p_panasonic_agc_config, 248 &dib3000p_panasonic_agc_config,
249 249
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 6d0dd859d684..49b55d7069b1 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -13,6 +13,7 @@
13 * 13 *
14 * see Documentation/dvb/README.dvb-usb for more information 14 * see Documentation/dvb/README.dvb-usb for more information
15 */ 15 */
16#include "dvb-usb-ids.h"
16#include "dw2102.h" 17#include "dw2102.h"
17#include "si21xx.h" 18#include "si21xx.h"
18#include "stv0299.h" 19#include "stv0299.h"
@@ -38,61 +39,6 @@
38/* Max transfer size done by I2C transfer functions */ 39/* Max transfer size done by I2C transfer functions */
39#define MAX_XFER_SIZE 64 40#define MAX_XFER_SIZE 64
40 41
41#ifndef USB_PID_DW2102
42#define USB_PID_DW2102 0x2102
43#endif
44
45#ifndef USB_PID_DW2104
46#define USB_PID_DW2104 0x2104
47#endif
48
49#ifndef USB_PID_DW3101
50#define USB_PID_DW3101 0x3101
51#endif
52
53#ifndef USB_PID_CINERGY_S
54#define USB_PID_CINERGY_S 0x0064
55#endif
56
57#ifndef USB_PID_TEVII_S630
58#define USB_PID_TEVII_S630 0xd630
59#endif
60
61#ifndef USB_PID_TEVII_S650
62#define USB_PID_TEVII_S650 0xd650
63#endif
64
65#ifndef USB_PID_TEVII_S660
66#define USB_PID_TEVII_S660 0xd660
67#endif
68
69#ifndef USB_PID_TEVII_S662
70#define USB_PID_TEVII_S662 0xd662
71#endif
72
73#ifndef USB_PID_TEVII_S480_1
74#define USB_PID_TEVII_S480_1 0xd481
75#endif
76
77#ifndef USB_PID_TEVII_S480_2
78#define USB_PID_TEVII_S480_2 0xd482
79#endif
80
81#ifndef USB_PID_PROF_1100
82#define USB_PID_PROF_1100 0xb012
83#endif
84
85#ifndef USB_PID_TEVII_S421
86#define USB_PID_TEVII_S421 0xd421
87#endif
88
89#ifndef USB_PID_TEVII_S632
90#define USB_PID_TEVII_S632 0xd632
91#endif
92
93#ifndef USB_PID_GOTVIEW_SAT_HD
94#define USB_PID_GOTVIEW_SAT_HD 0x5456
95#endif
96 42
97#define DW210X_READ_MSG 0 43#define DW210X_READ_MSG 0
98#define DW210X_WRITE_MSG 1 44#define DW210X_WRITE_MSG 1
@@ -1709,7 +1655,7 @@ static struct usb_device_id dw2102_table[] = {
1709 [CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, 1655 [CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
1710 [CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)}, 1656 [CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
1711 [TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)}, 1657 [TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
1712 [TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)}, 1658 [TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S)},
1713 [CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, 1659 [CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
1714 [TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, 1660 [TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
1715 [PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, 1661 [PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
@@ -1801,7 +1747,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
1801 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, 1747 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
1802 DW210X_WRITE_MSG); 1748 DW210X_WRITE_MSG);
1803 break; 1749 break;
1804 case USB_PID_CINERGY_S: 1750 case USB_PID_TERRATEC_CINERGY_S:
1805 case USB_PID_DW2102: 1751 case USB_PID_DW2102:
1806 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, 1752 dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
1807 DW210X_WRITE_MSG); 1753 DW210X_WRITE_MSG);
@@ -1843,6 +1789,9 @@ static int dw2102_load_firmware(struct usb_device *dev,
1843 msleep(100); 1789 msleep(100);
1844 kfree(p); 1790 kfree(p);
1845 } 1791 }
1792
1793 if (le16_to_cpu(dev->descriptor.idProduct) == 0x2101)
1794 release_firmware(fw);
1846 return ret; 1795 return ret;
1847} 1796}
1848 1797
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c
index ec397c4b7cc8..c05de1b088a4 100644
--- a/drivers/media/usb/dvb-usb/pctv452e.c
+++ b/drivers/media/usb/dvb-usb/pctv452e.c
@@ -995,11 +995,11 @@ static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
995 /* parameter for the MPEG2-data transfer */ 995 /* parameter for the MPEG2-data transfer */
996 .stream = { 996 .stream = {
997 .type = USB_ISOC, 997 .type = USB_ISOC,
998 .count = 7, 998 .count = 4,
999 .endpoint = 0x02, 999 .endpoint = 0x02,
1000 .u = { 1000 .u = {
1001 .isoc = { 1001 .isoc = {
1002 .framesperurb = 4, 1002 .framesperurb = 64,
1003 .framesize = 940, 1003 .framesize = 940,
1004 .interval = 1 1004 .interval = 1
1005 } 1005 }
diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig
index e382210c4ada..d917b0a2beb1 100644
--- a/drivers/media/usb/em28xx/Kconfig
+++ b/drivers/media/usb/em28xx/Kconfig
@@ -59,6 +59,8 @@ config VIDEO_EM28XX_DVB
59 select DVB_DRX39XYJ if MEDIA_SUBDRV_AUTOSELECT 59 select DVB_DRX39XYJ if MEDIA_SUBDRV_AUTOSELECT
60 select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT 60 select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
61 select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT 61 select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
62 select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT
63 select MEDIA_TUNER_QM1D1C0042 if MEDIA_SUBDRV_AUTOSELECT
62 ---help--- 64 ---help---
63 This adds support for DVB cards based on the 65 This adds support for DVB cards based on the
64 Empiatech em28xx chips. 66 Empiatech em28xx chips.
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 930e3e3fc948..e397f544f108 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -492,6 +492,44 @@ static struct em28xx_reg_seq terratec_t2_stick_hd[] = {
492 {-1, -1, -1, -1}, 492 {-1, -1, -1, -1},
493}; 493};
494 494
495static struct em28xx_reg_seq plex_px_bcud[] = {
496 {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0},
497 {0x0d, 0xff, 0xff, 0},
498 {EM2874_R50_IR_CONFIG, 0x01, 0xff, 0},
499 {EM28XX_R06_I2C_CLK, 0x40, 0xff, 0},
500 {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 100},
501 {EM28XX_R12_VINENABLE, 0x20, 0x20, 0},
502 {0x0d, 0x42, 0xff, 1000},
503 {EM2874_R80_GPIO_P0_CTRL, 0xfc, 0xff, 10},
504 {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 10},
505 {0x73, 0xfd, 0xff, 100},
506 {-1, -1, -1, -1},
507};
508
509/*
510 * 2040:0265 Hauppauge WinTV-dualHD DVB
511 * reg 0x80/0x84:
512 * GPIO_0: Yellow LED tuner 1, 0=on, 1=off
513 * GPIO_1: Green LED tuner 1, 0=on, 1=off
514 * GPIO_2: Yellow LED tuner 2, 0=on, 1=off
515 * GPIO_3: Green LED tuner 2, 0=on, 1=off
516 * GPIO_5: Reset #2, 0=active
517 * GPIO_6: Reset #1, 0=active
518 */
519static struct em28xx_reg_seq hauppauge_dualhd_dvb[] = {
520 {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0},
521 {0x0d, 0xff, 0xff, 200},
522 {0x50, 0x04, 0xff, 300},
523 {EM2874_R80_GPIO_P0_CTRL, 0xbf, 0xff, 100}, /* demod 1 reset */
524 {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100},
525 {EM2874_R80_GPIO_P0_CTRL, 0xdf, 0xff, 100}, /* demod 2 reset */
526 {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100},
527 {EM2874_R5F_TS_ENABLE, 0x44, 0xff, 50},
528 {EM2874_R5D_TS1_PKT_SIZE, 0x05, 0xff, 50},
529 {EM2874_R5E_TS2_PKT_SIZE, 0x05, 0xff, 50},
530 {-1, -1, -1, -1},
531};
532
495/* 533/*
496 * Button definitions 534 * Button definitions
497 */ 535 */
@@ -571,6 +609,22 @@ static struct em28xx_led terratec_grabby_leds[] = {
571 {-1, 0, 0, 0}, 609 {-1, 0, 0, 0},
572}; 610};
573 611
612static struct em28xx_led hauppauge_dualhd_leds[] = {
613 {
614 .role = EM28XX_LED_DIGITAL_CAPTURING,
615 .gpio_reg = EM2874_R80_GPIO_P0_CTRL,
616 .gpio_mask = EM_GPIO_1,
617 .inverted = 1,
618 },
619 {
620 .role = EM28XX_LED_DIGITAL_CAPTURING_TS2,
621 .gpio_reg = EM2874_R80_GPIO_P0_CTRL,
622 .gpio_mask = EM_GPIO_3,
623 .inverted = 1,
624 },
625 {-1, 0, 0, 0},
626};
627
574/* 628/*
575 * Board definitions 629 * Board definitions
576 */ 630 */
@@ -2306,6 +2360,35 @@ struct em28xx_board em28xx_boards[] = {
2306 .has_dvb = 1, 2360 .has_dvb = 1,
2307 .ir_codes = RC_MAP_TERRATEC_SLIM_2, 2361 .ir_codes = RC_MAP_TERRATEC_SLIM_2,
2308 }, 2362 },
2363
2364 /*
2365 * 3275:0085 PLEX PX-BCUD.
2366 * Empia EM28178, TOSHIBA TC90532XBG, Sharp QM1D1C0042
2367 */
2368 [EM28178_BOARD_PLEX_PX_BCUD] = {
2369 .name = "PLEX PX-BCUD",
2370 .xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ,
2371 .def_i2c_bus = 1,
2372 .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE,
2373 .tuner_type = TUNER_ABSENT,
2374 .tuner_gpio = plex_px_bcud,
2375 .has_dvb = 1,
2376 },
2377 /*
2378 * 2040:0265 Hauppauge WinTV-dualHD (DVB version).
2379 * Empia EM28274, 2x Silicon Labs Si2168, 2x Silicon Labs Si2157
2380 */
2381 [EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB] = {
2382 .name = "Hauppauge WinTV-dualHD DVB",
2383 .def_i2c_bus = 1,
2384 .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
2385 EM28XX_I2C_FREQ_400_KHZ,
2386 .tuner_type = TUNER_ABSENT,
2387 .tuner_gpio = hauppauge_dualhd_dvb,
2388 .has_dvb = 1,
2389 .ir_codes = RC_MAP_HAUPPAUGE,
2390 .leds = hauppauge_dualhd_leds,
2391 },
2309}; 2392};
2310EXPORT_SYMBOL_GPL(em28xx_boards); 2393EXPORT_SYMBOL_GPL(em28xx_boards);
2311 2394
@@ -2429,6 +2512,8 @@ struct usb_device_id em28xx_id_table[] = {
2429 .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, 2512 .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
2430 { USB_DEVICE(0x2040, 0x651f), 2513 { USB_DEVICE(0x2040, 0x651f),
2431 .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 }, 2514 .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 },
2515 { USB_DEVICE(0x2040, 0x0265),
2516 .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB },
2432 { USB_DEVICE(0x0438, 0xb002), 2517 { USB_DEVICE(0x0438, 0xb002),
2433 .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, 2518 .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 },
2434 { USB_DEVICE(0x2001, 0xf112), 2519 { USB_DEVICE(0x2001, 0xf112),
@@ -2495,6 +2580,8 @@ struct usb_device_id em28xx_id_table[] = {
2495 .driver_info = EM2861_BOARD_LEADTEK_VC100 }, 2580 .driver_info = EM2861_BOARD_LEADTEK_VC100 },
2496 { USB_DEVICE(0xeb1a, 0x8179), 2581 { USB_DEVICE(0xeb1a, 0x8179),
2497 .driver_info = EM28178_BOARD_TERRATEC_T2_STICK_HD }, 2582 .driver_info = EM28178_BOARD_TERRATEC_T2_STICK_HD },
2583 { USB_DEVICE(0x3275, 0x0085),
2584 .driver_info = EM28178_BOARD_PLEX_PX_BCUD },
2498 { }, 2585 { },
2499}; 2586};
2500MODULE_DEVICE_TABLE(usb, em28xx_id_table); 2587MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2861,6 +2948,7 @@ static void em28xx_card_setup(struct em28xx *dev)
2861 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: 2948 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
2862 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: 2949 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
2863 case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: 2950 case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
2951 case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB:
2864 { 2952 {
2865 struct tveeprom tv; 2953 struct tveeprom tv;
2866 2954
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 5d209c7c54d5..1a5c01202f73 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -58,6 +58,8 @@
58#include "ts2020.h" 58#include "ts2020.h"
59#include "si2168.h" 59#include "si2168.h"
60#include "si2157.h" 60#include "si2157.h"
61#include "tc90522.h"
62#include "qm1d1c0042.h"
61 63
62MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 64MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
63MODULE_LICENSE("GPL"); 65MODULE_LICENSE("GPL");
@@ -787,6 +789,68 @@ static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
787 return 0; 789 return 0;
788} 790}
789 791
792static void px_bcud_init(struct em28xx *dev)
793{
794 int i;
795 struct {
796 unsigned char r[4];
797 int len;
798 } regs1[] = {
799 {{ 0x0e, 0x77 }, 2},
800 {{ 0x0f, 0x77 }, 2},
801 {{ 0x03, 0x90 }, 2},
802 }, regs2[] = {
803 {{ 0x07, 0x01 }, 2},
804 {{ 0x08, 0x10 }, 2},
805 {{ 0x13, 0x00 }, 2},
806 {{ 0x17, 0x00 }, 2},
807 {{ 0x03, 0x01 }, 2},
808 {{ 0x10, 0xb1 }, 2},
809 {{ 0x11, 0x40 }, 2},
810 {{ 0x85, 0x7a }, 2},
811 {{ 0x87, 0x04 }, 2},
812 };
813 static struct em28xx_reg_seq gpio[] = {
814 {EM28XX_R06_I2C_CLK, 0x40, 0xff, 300},
815 {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 60},
816 {EM28XX_R15_RGAIN, 0x20, 0xff, 0},
817 {EM28XX_R16_GGAIN, 0x20, 0xff, 0},
818 {EM28XX_R17_BGAIN, 0x20, 0xff, 0},
819 {EM28XX_R18_ROFFSET, 0x00, 0xff, 0},
820 {EM28XX_R19_GOFFSET, 0x00, 0xff, 0},
821 {EM28XX_R1A_BOFFSET, 0x00, 0xff, 0},
822 {EM28XX_R23_UOFFSET, 0x00, 0xff, 0},
823 {EM28XX_R24_VOFFSET, 0x00, 0xff, 0},
824 {EM28XX_R26_COMPR, 0x00, 0xff, 0},
825 {0x13, 0x08, 0xff, 0},
826 {EM28XX_R12_VINENABLE, 0x27, 0xff, 0},
827 {EM28XX_R0C_USBSUSP, 0x10, 0xff, 0},
828 {EM28XX_R27_OUTFMT, 0x00, 0xff, 0},
829 {EM28XX_R10_VINMODE, 0x00, 0xff, 0},
830 {EM28XX_R11_VINCTRL, 0x11, 0xff, 0},
831 {EM2874_R50_IR_CONFIG, 0x01, 0xff, 0},
832 {EM2874_R5F_TS_ENABLE, 0x80, 0xff, 0},
833 {EM28XX_R06_I2C_CLK, 0x46, 0xff, 0},
834 };
835 em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x46);
836 /* sleeping ISDB-T */
837 dev->dvb->i2c_client_demod->addr = 0x14;
838 for (i = 0; i < ARRAY_SIZE(regs1); i++)
839 i2c_master_send(dev->dvb->i2c_client_demod, regs1[i].r,
840 regs1[i].len);
841 /* sleeping ISDB-S */
842 dev->dvb->i2c_client_demod->addr = 0x15;
843 for (i = 0; i < ARRAY_SIZE(regs2); i++)
844 i2c_master_send(dev->dvb->i2c_client_demod, regs2[i].r,
845 regs2[i].len);
846 for (i = 0; i < ARRAY_SIZE(gpio); i++) {
847 em28xx_write_reg_bits(dev, gpio[i].reg, gpio[i].val,
848 gpio[i].mask);
849 if (gpio[i].sleep > 0)
850 msleep(gpio[i].sleep);
851 }
852};
853
790static struct mt352_config terratec_xs_mt352_cfg = { 854static struct mt352_config terratec_xs_mt352_cfg = {
791 .demod_address = (0x1e >> 1), 855 .demod_address = (0x1e >> 1),
792 .no_tuner = 1, 856 .no_tuner = 1,
@@ -1762,6 +1826,127 @@ static int em28xx_dvb_init(struct em28xx *dev)
1762 dvb->i2c_client_tuner = client; 1826 dvb->i2c_client_tuner = client;
1763 } 1827 }
1764 break; 1828 break;
1829
1830 case EM28178_BOARD_PLEX_PX_BCUD:
1831 {
1832 struct i2c_client *client;
1833 struct i2c_board_info info;
1834 struct tc90522_config tc90522_config;
1835 struct qm1d1c0042_config qm1d1c0042_config;
1836
1837 /* attach demod */
1838 memset(&tc90522_config, 0, sizeof(tc90522_config));
1839 memset(&info, 0, sizeof(struct i2c_board_info));
1840 strlcpy(info.type, "tc90522sat", I2C_NAME_SIZE);
1841 info.addr = 0x15;
1842 info.platform_data = &tc90522_config;
1843 request_module("tc90522");
1844 client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
1845 if (client == NULL || client->dev.driver == NULL) {
1846 result = -ENODEV;
1847 goto out_free;
1848 }
1849 dvb->i2c_client_demod = client;
1850 if (!try_module_get(client->dev.driver->owner)) {
1851 i2c_unregister_device(client);
1852 result = -ENODEV;
1853 goto out_free;
1854 }
1855
1856 /* attach tuner */
1857 memset(&qm1d1c0042_config, 0,
1858 sizeof(qm1d1c0042_config));
1859 qm1d1c0042_config.fe = tc90522_config.fe;
1860 qm1d1c0042_config.lpf = 1;
1861 memset(&info, 0, sizeof(struct i2c_board_info));
1862 strlcpy(info.type, "qm1d1c0042", I2C_NAME_SIZE);
1863 info.addr = 0x61;
1864 info.platform_data = &qm1d1c0042_config;
1865 request_module(info.type);
1866 client = i2c_new_device(tc90522_config.tuner_i2c,
1867 &info);
1868 if (client == NULL || client->dev.driver == NULL) {
1869 module_put(dvb->i2c_client_demod->dev.driver->owner);
1870 i2c_unregister_device(dvb->i2c_client_demod);
1871 result = -ENODEV;
1872 goto out_free;
1873 }
1874 dvb->i2c_client_tuner = client;
1875 if (!try_module_get(client->dev.driver->owner)) {
1876 i2c_unregister_device(client);
1877 module_put(dvb->i2c_client_demod->dev.driver->owner);
1878 i2c_unregister_device(dvb->i2c_client_demod);
1879 result = -ENODEV;
1880 goto out_free;
1881 }
1882 dvb->fe[0] = tc90522_config.fe;
1883 px_bcud_init(dev);
1884 }
1885 break;
1886 case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB:
1887 {
1888 struct i2c_adapter *adapter;
1889 struct i2c_client *client;
1890 struct i2c_board_info info;
1891 struct si2168_config si2168_config;
1892 struct si2157_config si2157_config;
1893
1894 /* attach demod */
1895 memset(&si2168_config, 0, sizeof(si2168_config));
1896 si2168_config.i2c_adapter = &adapter;
1897 si2168_config.fe = &dvb->fe[0];
1898 si2168_config.ts_mode = SI2168_TS_SERIAL;
1899 memset(&info, 0, sizeof(struct i2c_board_info));
1900 strlcpy(info.type, "si2168", I2C_NAME_SIZE);
1901 info.addr = 0x64;
1902 info.platform_data = &si2168_config;
1903 request_module(info.type);
1904 client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
1905 if (client == NULL || client->dev.driver == NULL) {
1906 result = -ENODEV;
1907 goto out_free;
1908 }
1909
1910 if (!try_module_get(client->dev.driver->owner)) {
1911 i2c_unregister_device(client);
1912 result = -ENODEV;
1913 goto out_free;
1914 }
1915
1916 dvb->i2c_client_demod = client;
1917
1918 /* attach tuner */
1919 memset(&si2157_config, 0, sizeof(si2157_config));
1920 si2157_config.fe = dvb->fe[0];
1921 si2157_config.if_port = 1;
1922#ifdef CONFIG_MEDIA_CONTROLLER_DVB
1923 si2157_config.mdev = dev->media_dev;
1924#endif
1925 memset(&info, 0, sizeof(struct i2c_board_info));
1926 strlcpy(info.type, "si2157", I2C_NAME_SIZE);
1927 info.addr = 0x60;
1928 info.platform_data = &si2157_config;
1929 request_module(info.type);
1930 client = i2c_new_device(adapter, &info);
1931 if (client == NULL || client->dev.driver == NULL) {
1932 module_put(dvb->i2c_client_demod->dev.driver->owner);
1933 i2c_unregister_device(dvb->i2c_client_demod);
1934 result = -ENODEV;
1935 goto out_free;
1936 }
1937
1938 if (!try_module_get(client->dev.driver->owner)) {
1939 i2c_unregister_device(client);
1940 module_put(dvb->i2c_client_demod->dev.driver->owner);
1941 i2c_unregister_device(dvb->i2c_client_demod);
1942 result = -ENODEV;
1943 goto out_free;
1944 }
1945
1946 dvb->i2c_client_tuner = client;
1947
1948 }
1949 break;
1765 default: 1950 default:
1766 em28xx_errdev("/2: The frontend of your DVB/ATSC card" 1951 em28xx_errdev("/2: The frontend of your DVB/ATSC card"
1767 " isn't supported yet\n"); 1952 " isn't supported yet\n");
diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
index 13cbb7f3ea10..afe7a66d7dc8 100644
--- a/drivers/media/usb/em28xx/em28xx-reg.h
+++ b/drivers/media/usb/em28xx/em28xx-reg.h
@@ -193,6 +193,19 @@
193/* em2874 registers */ 193/* em2874 registers */
194#define EM2874_R50_IR_CONFIG 0x50 194#define EM2874_R50_IR_CONFIG 0x50
195#define EM2874_R51_IR 0x51 195#define EM2874_R51_IR 0x51
196#define EM2874_R5D_TS1_PKT_SIZE 0x5d
197#define EM2874_R5E_TS2_PKT_SIZE 0x5e
198 /*
199 * For both TS1 and TS2, In isochronous mode:
200 * 0x01 188 bytes
201 * 0x02 376 bytes
202 * 0x03 564 bytes
203 * 0x04 752 bytes
204 * 0x05 940 bytes
205 * In bulk mode:
206 * 0x01..0xff total packet count in 188-byte
207 */
208
196#define EM2874_R5F_TS_ENABLE 0x5f 209#define EM2874_R5F_TS_ENABLE 0x5f
197 210
198/* em2874/174/84, em25xx, em276x/7x/8x GPIO registers */ 211/* em2874/174/84, em25xx, em276x/7x/8x GPIO registers */
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 267444961775..d148463b22c1 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -145,6 +145,8 @@
145#define EM2861_BOARD_LEADTEK_VC100 95 145#define EM2861_BOARD_LEADTEK_VC100 95
146#define EM28178_BOARD_TERRATEC_T2_STICK_HD 96 146#define EM28178_BOARD_TERRATEC_T2_STICK_HD 96
147#define EM2884_BOARD_ELGATO_EYETV_HYBRID_2008 97 147#define EM2884_BOARD_ELGATO_EYETV_HYBRID_2008 97
148#define EM28178_BOARD_PLEX_PX_BCUD 98
149#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB 99
148 150
149/* Limits minimum and default number of buffers */ 151/* Limits minimum and default number of buffers */
150#define EM28XX_MIN_BUF 4 152#define EM28XX_MIN_BUF 4
@@ -406,6 +408,7 @@ enum em28xx_adecoder {
406enum em28xx_led_role { 408enum em28xx_led_role {
407 EM28XX_LED_ANALOG_CAPTURING = 0, 409 EM28XX_LED_ANALOG_CAPTURING = 0,
408 EM28XX_LED_DIGITAL_CAPTURING, 410 EM28XX_LED_DIGITAL_CAPTURING,
411 EM28XX_LED_DIGITAL_CAPTURING_TS2,
409 EM28XX_LED_ILLUMINATION, 412 EM28XX_LED_ILLUMINATION,
410 EM28XX_NUM_LED_ROLES, /* must be the last */ 413 EM28XX_NUM_LED_ROLES, /* must be the last */
411}; 414};
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index 358c1c186d03..ea01ee5df60a 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -1125,7 +1125,7 @@ int go7007_v4l2_init(struct go7007 *go)
1125 vdev->queue = &go->vidq; 1125 vdev->queue = &go->vidq;
1126 video_set_drvdata(vdev, go); 1126 video_set_drvdata(vdev, go);
1127 vdev->v4l2_dev = &go->v4l2_dev; 1127 vdev->v4l2_dev = &go->v4l2_dev;
1128 if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd)) 1128 if (!v4l2_device_has_op(&go->v4l2_dev, 0, video, querystd))
1129 v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD); 1129 v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD);
1130 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) { 1130 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) {
1131 v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY); 1131 v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY);
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index 1a093e5953fd..83e9a3eb3859 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -3672,11 +3672,10 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
3672 3672
3673 3673
3674 hdw->cmd_debug_state = 1; 3674 hdw->cmd_debug_state = 1;
3675 if (write_len) { 3675 if (write_len && write_data)
3676 hdw->cmd_debug_code = ((unsigned char *)write_data)[0]; 3676 hdw->cmd_debug_code = ((unsigned char *)write_data)[0];
3677 } else { 3677 else
3678 hdw->cmd_debug_code = 0; 3678 hdw->cmd_debug_code = 0;
3679 }
3680 hdw->cmd_debug_write_len = write_len; 3679 hdw->cmd_debug_write_len = write_len;
3681 hdw->cmd_debug_read_len = read_len; 3680 hdw->cmd_debug_read_len = read_len;
3682 3681
@@ -3688,7 +3687,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
3688 setup_timer(&timer, pvr2_ctl_timeout, (unsigned long)hdw); 3687 setup_timer(&timer, pvr2_ctl_timeout, (unsigned long)hdw);
3689 timer.expires = jiffies + timeout; 3688 timer.expires = jiffies + timeout;
3690 3689
3691 if (write_len) { 3690 if (write_len && write_data) {
3692 hdw->cmd_debug_state = 2; 3691 hdw->cmd_debug_state = 2;
3693 /* Transfer write data to internal buffer */ 3692 /* Transfer write data to internal buffer */
3694 for (idx = 0; idx < write_len; idx++) { 3693 for (idx = 0; idx < write_len; idx++) {
@@ -3795,7 +3794,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
3795 goto done; 3794 goto done;
3796 } 3795 }
3797 } 3796 }
3798 if (read_len) { 3797 if (read_len && read_data) {
3799 /* Validate results of read request */ 3798 /* Validate results of read request */
3800 if ((hdw->ctl_read_urb->status != 0) && 3799 if ((hdw->ctl_read_urb->status != 0) &&
3801 (hdw->ctl_read_urb->status != -ENOENT) && 3800 (hdw->ctl_read_urb->status != -ENOENT) &&
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 019644ff627d..bacecbd68a6d 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -280,7 +280,8 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
280static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) 280static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
281{ 281{
282 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || 282 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
283 copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format))) 283 copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
284 copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
284 return -EFAULT; 285 return -EFAULT;
285 return __put_v4l2_format32(&kp->format, &up->format); 286 return __put_v4l2_format32(&kp->format, &up->format);
286} 287}
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index d8e5994cccf1..70b559d7ca80 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -735,6 +735,7 @@ static int video_register_media_controller(struct video_device *vdev, int type)
735 if (!vdev->v4l2_dev->mdev) 735 if (!vdev->v4l2_dev->mdev)
736 return 0; 736 return 0;
737 737
738 vdev->entity.obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE;
738 vdev->entity.function = MEDIA_ENT_F_UNKNOWN; 739 vdev->entity.function = MEDIA_ENT_F_UNKNOWN;
739 740
740 switch (type) { 741 switch (type) {
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 170dd68d27f4..28e5be2c2eef 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1020,9 +1020,12 @@ static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
1020 struct file *file, void *fh, void *arg) 1020 struct file *file, void *fh, void *arg)
1021{ 1021{
1022 struct v4l2_capability *cap = (struct v4l2_capability *)arg; 1022 struct v4l2_capability *cap = (struct v4l2_capability *)arg;
1023 struct video_device *vfd = video_devdata(file);
1023 int ret; 1024 int ret;
1024 1025
1025 cap->version = LINUX_VERSION_CODE; 1026 cap->version = LINUX_VERSION_CODE;
1027 cap->device_caps = vfd->device_caps;
1028 cap->capabilities = vfd->device_caps | V4L2_CAP_DEVICE_CAPS;
1026 1029
1027 ret = ops->vidioc_querycap(file, fh, cap); 1030 ret = ops->vidioc_querycap(file, fh, cap);
1028 1031
@@ -2157,40 +2160,56 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops,
2157 struct file *file, void *fh, void *arg) 2160 struct file *file, void *fh, void *arg)
2158{ 2161{
2159 struct v4l2_cropcap *p = arg; 2162 struct v4l2_cropcap *p = arg;
2163 struct v4l2_selection s = { .type = p->type };
2164 int ret = 0;
2160 2165
2161 if (ops->vidioc_g_selection) { 2166 /* setting trivial pixelaspect */
2162 struct v4l2_selection s = { .type = p->type }; 2167 p->pixelaspect.numerator = 1;
2163 int ret; 2168 p->pixelaspect.denominator = 1;
2164 2169
2165 /* obtaining bounds */ 2170 /*
2166 if (V4L2_TYPE_IS_OUTPUT(p->type)) 2171 * The determine_valid_ioctls() call already should ensure
2167 s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; 2172 * that this can never happen, but just in case...
2168 else 2173 */
2169 s.target = V4L2_SEL_TGT_CROP_BOUNDS; 2174 if (WARN_ON(!ops->vidioc_cropcap && !ops->vidioc_cropcap))
2175 return -ENOTTY;
2170 2176
2171 ret = ops->vidioc_g_selection(file, fh, &s); 2177 if (ops->vidioc_cropcap)
2172 if (ret) 2178 ret = ops->vidioc_cropcap(file, fh, p);
2173 return ret;
2174 p->bounds = s.r;
2175 2179
2176 /* obtaining defrect */ 2180 if (!ops->vidioc_g_selection)
2177 if (V4L2_TYPE_IS_OUTPUT(p->type)) 2181 return ret;
2178 s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
2179 else
2180 s.target = V4L2_SEL_TGT_CROP_DEFAULT;
2181 2182
2182 ret = ops->vidioc_g_selection(file, fh, &s); 2183 /*
2183 if (ret) 2184 * Ignore ENOTTY or ENOIOCTLCMD error returns, just use the
2184 return ret; 2185 * square pixel aspect ratio in that case.
2185 p->defrect = s.r; 2186 */
2186 } 2187 if (ret && ret != -ENOTTY && ret != -ENOIOCTLCMD)
2188 return ret;
2187 2189
2188 /* setting trivial pixelaspect */ 2190 /* Use g_selection() to fill in the bounds and defrect rectangles */
2189 p->pixelaspect.numerator = 1;
2190 p->pixelaspect.denominator = 1;
2191 2191
2192 if (ops->vidioc_cropcap) 2192 /* obtaining bounds */
2193 return ops->vidioc_cropcap(file, fh, p); 2193 if (V4L2_TYPE_IS_OUTPUT(p->type))
2194 s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
2195 else
2196 s.target = V4L2_SEL_TGT_CROP_BOUNDS;
2197
2198 ret = ops->vidioc_g_selection(file, fh, &s);
2199 if (ret)
2200 return ret;
2201 p->bounds = s.r;
2202
2203 /* obtaining defrect */
2204 if (V4L2_TYPE_IS_OUTPUT(p->type))
2205 s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
2206 else
2207 s.target = V4L2_SEL_TGT_CROP_DEFAULT;
2208
2209 ret = ops->vidioc_g_selection(file, fh, &s);
2210 if (ret)
2211 return ret;
2212 p->defrect = s.r;
2194 2213
2195 return 0; 2214 return 0;
2196} 2215}
diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
index 2228cd3a846e..ca94bded3386 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -263,7 +263,7 @@ static int pipeline_pm_use_count(struct media_entity *entity,
263 media_entity_graph_walk_start(graph, entity); 263 media_entity_graph_walk_start(graph, entity);
264 264
265 while ((entity = media_entity_graph_walk_next(graph))) { 265 while ((entity = media_entity_graph_walk_next(graph))) {
266 if (is_media_entity_v4l2_io(entity)) 266 if (is_media_entity_v4l2_video_device(entity))
267 use += entity->use_count; 267 use += entity->use_count;
268 } 268 }
269 269
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index d63083803144..953eab08e420 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -35,9 +35,11 @@
35static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) 35static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
36{ 36{
37#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 37#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
38 fh->pad = kzalloc(sizeof(*fh->pad) * sd->entity.num_pads, GFP_KERNEL); 38 if (sd->entity.num_pads) {
39 if (fh->pad == NULL) 39 fh->pad = v4l2_subdev_alloc_pad_config(sd);
40 return -ENOMEM; 40 if (fh->pad == NULL)
41 return -ENOMEM;
42 }
41#endif 43#endif
42 return 0; 44 return 0;
43} 45}
@@ -45,7 +47,7 @@ static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
45static void subdev_fh_free(struct v4l2_subdev_fh *fh) 47static void subdev_fh_free(struct v4l2_subdev_fh *fh)
46{ 48{
47#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) 49#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
48 kfree(fh->pad); 50 v4l2_subdev_free_pad_config(fh->pad);
49 fh->pad = NULL; 51 fh->pad = NULL;
50#endif 52#endif
51} 53}
@@ -508,7 +510,7 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
508 if (source_fmt->format.width != sink_fmt->format.width 510 if (source_fmt->format.width != sink_fmt->format.width
509 || source_fmt->format.height != sink_fmt->format.height 511 || source_fmt->format.height != sink_fmt->format.height
510 || source_fmt->format.code != sink_fmt->format.code) 512 || source_fmt->format.code != sink_fmt->format.code)
511 return -EINVAL; 513 return -EPIPE;
512 514
513 /* The field order must match, or the sink field order must be NONE 515 /* The field order must match, or the sink field order must be NONE
514 * to support interlaced hardware connected to bridges that support 516 * to support interlaced hardware connected to bridges that support
@@ -516,7 +518,7 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
516 */ 518 */
517 if (source_fmt->format.field != sink_fmt->format.field && 519 if (source_fmt->format.field != sink_fmt->format.field &&
518 sink_fmt->format.field != V4L2_FIELD_NONE) 520 sink_fmt->format.field != V4L2_FIELD_NONE)
519 return -EINVAL; 521 return -EPIPE;
520 522
521 return 0; 523 return 0;
522} 524}
@@ -569,6 +571,35 @@ int v4l2_subdev_link_validate(struct media_link *link)
569 sink, link, &source_fmt, &sink_fmt); 571 sink, link, &source_fmt, &sink_fmt);
570} 572}
571EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate); 573EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate);
574
575struct v4l2_subdev_pad_config *
576v4l2_subdev_alloc_pad_config(struct v4l2_subdev *sd)
577{
578 struct v4l2_subdev_pad_config *cfg;
579 int ret;
580
581 if (!sd->entity.num_pads)
582 return NULL;
583
584 cfg = kcalloc(sd->entity.num_pads, sizeof(*cfg), GFP_KERNEL);
585 if (!cfg)
586 return NULL;
587
588 ret = v4l2_subdev_call(sd, pad, init_cfg, cfg);
589 if (ret < 0 && ret != -ENOIOCTLCMD) {
590 kfree(cfg);
591 return NULL;
592 }
593
594 return cfg;
595}
596EXPORT_SYMBOL_GPL(v4l2_subdev_alloc_pad_config);
597
598void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config *cfg)
599{
600 kfree(cfg);
601}
602EXPORT_SYMBOL_GPL(v4l2_subdev_free_pad_config);
572#endif /* CONFIG_MEDIA_CONTROLLER */ 603#endif /* CONFIG_MEDIA_CONTROLLER */
573 604
574void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) 605void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
@@ -584,6 +615,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
584 sd->host_priv = NULL; 615 sd->host_priv = NULL;
585#if defined(CONFIG_MEDIA_CONTROLLER) 616#if defined(CONFIG_MEDIA_CONTROLLER)
586 sd->entity.name = sd->name; 617 sd->entity.name = sd->name;
618 sd->entity.obj_type = MEDIA_ENTITY_TYPE_V4L2_SUBDEV;
587 sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; 619 sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
588#endif 620#endif
589} 621}
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index 0078b6a92f0b..de7e9f52e7eb 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -37,6 +37,8 @@ source "drivers/staging/media/omap4iss/Kconfig"
37 37
38source "drivers/staging/media/timb/Kconfig" 38source "drivers/staging/media/timb/Kconfig"
39 39
40source "drivers/staging/media/tw686x-kh/Kconfig"
41
40# Keep LIRC at the end, as it has sub-menus 42# Keep LIRC at the end, as it has sub-menus
41source "drivers/staging/media/lirc/Kconfig" 43source "drivers/staging/media/lirc/Kconfig"
42 44
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 91495882a36c..60a35b3a47e7 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1/
8obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ 8obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
9obj-$(CONFIG_DVB_MN88472) += mn88472/ 9obj-$(CONFIG_DVB_MN88472) += mn88472/
10obj-$(CONFIG_VIDEO_TIMBERDALE) += timb/ 10obj-$(CONFIG_VIDEO_TIMBERDALE) += timb/
11obj-$(CONFIG_VIDEO_TW686X_KH) += tw686x-kh/
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c
index abf330f92c0b..8dade197f053 100644
--- a/drivers/staging/media/bcm2048/radio-bcm2048.c
+++ b/drivers/staging/media/bcm2048/radio-bcm2048.c
@@ -308,7 +308,7 @@ module_param(radio_nr, int, 0);
308MODULE_PARM_DESC(radio_nr, 308MODULE_PARM_DESC(radio_nr,
309 "Minor number for radio device (-1 ==> auto assign)"); 309 "Minor number for radio device (-1 ==> auto assign)");
310 310
311static struct region_info region_configs[] = { 311static const struct region_info region_configs[] = {
312 /* USA */ 312 /* USA */
313 { 313 {
314 .channel_spacing = 20, 314 .channel_spacing = 20,
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index be72a8e5f221..ea3ddec75806 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -154,7 +154,7 @@ static int vpfe_prepare_pipeline(struct vpfe_video_device *video)
154 while ((entity = media_entity_graph_walk_next(&graph))) { 154 while ((entity = media_entity_graph_walk_next(&graph))) {
155 if (entity == &video->video_dev.entity) 155 if (entity == &video->video_dev.entity)
156 continue; 156 continue;
157 if (!is_media_entity_v4l2_io(entity)) 157 if (!is_media_entity_v4l2_video_device(entity))
158 continue; 158 continue;
159 far_end = to_vpfe_video(media_entity_to_video_device(entity)); 159 far_end = to_vpfe_video(media_entity_to_video_device(entity));
160 if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 160 if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
index f54349bce4de..cf8da23558bb 100644
--- a/drivers/staging/media/omap4iss/iss_video.c
+++ b/drivers/staging/media/omap4iss/iss_video.c
@@ -223,7 +223,7 @@ iss_video_far_end(struct iss_video *video)
223 if (entity == &video->video.entity) 223 if (entity == &video->video.entity)
224 continue; 224 continue;
225 225
226 if (!is_media_entity_v4l2_io(entity)) 226 if (!is_media_entity_v4l2_video_device(entity))
227 continue; 227 continue;
228 228
229 far_end = to_iss_video(media_entity_to_video_device(entity)); 229 far_end = to_iss_video(media_entity_to_video_device(entity));
diff --git a/drivers/staging/media/tw686x-kh/Kconfig b/drivers/staging/media/tw686x-kh/Kconfig
new file mode 100644
index 000000000000..6264d30edf5a
--- /dev/null
+++ b/drivers/staging/media/tw686x-kh/Kconfig
@@ -0,0 +1,17 @@
1config VIDEO_TW686X_KH
2 tristate "Intersil/Techwell TW686x Video For Linux"
3 depends on VIDEO_DEV && PCI && VIDEO_V4L2
4 depends on !(VIDEO_TW686X=y || VIDEO_TW686X=m) || COMPILE_TEST
5 select VIDEOBUF2_DMA_SG
6 help
7 Support for Intersil/Techwell TW686x-based frame grabber cards.
8
9 Currently supported chips:
10 - TW6864 (4 video channels),
11 - TW6865 (4 video channels, not tested, second generation chip),
12 - TW6868 (8 video channels but only 4 first channels using
13 built-in video decoder are supported, not tested),
14 - TW6869 (8 video channels, second generation chip).
15
16 To compile this driver as a module, choose M here: the module
17 will be named tw686x-kh.
diff --git a/drivers/staging/media/tw686x-kh/Makefile b/drivers/staging/media/tw686x-kh/Makefile
new file mode 100644
index 000000000000..2a36a38cf30e
--- /dev/null
+++ b/drivers/staging/media/tw686x-kh/Makefile
@@ -0,0 +1,3 @@
1tw686x-kh-objs := tw686x-kh-core.o tw686x-kh-video.o
2
3obj-$(CONFIG_VIDEO_TW686X_KH) += tw686x-kh.o
diff --git a/drivers/staging/media/tw686x-kh/TODO b/drivers/staging/media/tw686x-kh/TODO
new file mode 100644
index 000000000000..480a495b11fb
--- /dev/null
+++ b/drivers/staging/media/tw686x-kh/TODO
@@ -0,0 +1,6 @@
1TODO:
2
3- implement V4L2_FIELD_INTERLACED* mode(s).
4- add audio support
5
6Please Cc: patches to Krzysztof Halasa <khalasa@piap.pl>.
diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-core.c b/drivers/staging/media/tw686x-kh/tw686x-kh-core.c
new file mode 100644
index 000000000000..03b3b62c59c4
--- /dev/null
+++ b/drivers/staging/media/tw686x-kh/tw686x-kh-core.c
@@ -0,0 +1,140 @@
1/*
2 * Copyright (C) 2015 Industrial Research Institute for Automation
3 * and Measurements PIAP
4 *
5 * Written by Krzysztof Ha?asa.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License
9 * as published by the Free Software Foundation.
10 */
11
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/slab.h>
17#include "tw686x-kh.h"
18#include "tw686x-kh-regs.h"
19
20static irqreturn_t tw686x_irq(int irq, void *dev_id)
21{
22 struct tw686x_dev *dev = (struct tw686x_dev *)dev_id;
23 u32 int_status = reg_read(dev, INT_STATUS); /* cleared on read */
24 unsigned long flags;
25 unsigned int handled = 0;
26
27 if (int_status) {
28 spin_lock_irqsave(&dev->irq_lock, flags);
29 dev->dma_requests |= int_status;
30 spin_unlock_irqrestore(&dev->irq_lock, flags);
31
32 if (int_status & 0xFF0000FF)
33 handled = tw686x_kh_video_irq(dev);
34 }
35
36 return IRQ_RETVAL(handled);
37}
38
39static int tw686x_probe(struct pci_dev *pci_dev,
40 const struct pci_device_id *pci_id)
41{
42 struct tw686x_dev *dev;
43 int err;
44
45 dev = devm_kzalloc(&pci_dev->dev, sizeof(*dev) +
46 (pci_id->driver_data & TYPE_MAX_CHANNELS) *
47 sizeof(dev->video_channels[0]), GFP_KERNEL);
48 if (!dev)
49 return -ENOMEM;
50
51 sprintf(dev->name, "TW%04X", pci_dev->device);
52 dev->type = pci_id->driver_data;
53
54 pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx\n", dev->name,
55 pci_name(pci_dev), pci_dev->irq,
56 (unsigned long)pci_resource_start(pci_dev, 0));
57
58 dev->pci_dev = pci_dev;
59 if (pcim_enable_device(pci_dev))
60 return -EIO;
61
62 pci_set_master(pci_dev);
63
64 if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) {
65 pr_err("%s: 32-bit PCI DMA not supported\n", dev->name);
66 return -EIO;
67 }
68
69 err = pci_request_regions(pci_dev, dev->name);
70 if (err < 0) {
71 pr_err("%s: Unable to get MMIO region\n", dev->name);
72 return err;
73 }
74
75 dev->mmio = pci_ioremap_bar(pci_dev, 0);
76 if (!dev->mmio) {
77 pr_err("%s: Unable to remap MMIO region\n", dev->name);
78 return -EIO;
79 }
80
81 reg_write(dev, SYS_SOFT_RST, 0x0F); /* Reset all subsystems */
82 mdelay(1);
83
84 reg_write(dev, SRST[0], 0x3F);
85 if (max_channels(dev) > 4)
86 reg_write(dev, SRST[1], 0x3F);
87 reg_write(dev, DMA_CMD, 0);
88 reg_write(dev, DMA_CHANNEL_ENABLE, 0);
89 reg_write(dev, DMA_CHANNEL_TIMEOUT, 0x3EFF0FF0);
90 reg_write(dev, DMA_TIMER_INTERVAL, 0x38000);
91 reg_write(dev, DMA_CONFIG, 0xFFFFFF04);
92
93 spin_lock_init(&dev->irq_lock);
94
95 err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw686x_irq,
96 IRQF_SHARED, dev->name, dev);
97 if (err < 0) {
98 pr_err("%s: Unable to get IRQ\n", dev->name);
99 return err;
100 }
101
102 err = tw686x_kh_video_init(dev);
103 if (err)
104 return err;
105
106 pci_set_drvdata(pci_dev, dev);
107 return 0;
108}
109
110static void tw686x_remove(struct pci_dev *pci_dev)
111{
112 struct tw686x_dev *dev = pci_get_drvdata(pci_dev);
113
114 tw686x_kh_video_free(dev);
115}
116
117/* driver_data is number of A/V channels */
118static const struct pci_device_id tw686x_pci_tbl[] = {
119 {PCI_DEVICE(0x1797, 0x6864), .driver_data = 4},
120 /* not tested */
121 {PCI_DEVICE(0x1797, 0x6865), .driver_data = 4 | TYPE_SECOND_GEN},
122 /* TW6868 supports 8 A/V channels with an external TW2865 chip -
123 not supported by the driver */
124 {PCI_DEVICE(0x1797, 0x6868), .driver_data = 4}, /* not tested */
125 {PCI_DEVICE(0x1797, 0x6869), .driver_data = 8 | TYPE_SECOND_GEN},
126 {}
127};
128
129static struct pci_driver tw686x_pci_driver = {
130 .name = "tw686x-kh",
131 .id_table = tw686x_pci_tbl,
132 .probe = tw686x_probe,
133 .remove = tw686x_remove,
134};
135
136MODULE_DESCRIPTION("Driver for video frame grabber cards based on Intersil/Techwell TW686[4589]");
137MODULE_AUTHOR("Krzysztof Halasa");
138MODULE_LICENSE("GPL v2");
139MODULE_DEVICE_TABLE(pci, tw686x_pci_tbl);
140module_pci_driver(tw686x_pci_driver);
diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-regs.h b/drivers/staging/media/tw686x-kh/tw686x-kh-regs.h
new file mode 100644
index 000000000000..53e1889babd0
--- /dev/null
+++ b/drivers/staging/media/tw686x-kh/tw686x-kh-regs.h
@@ -0,0 +1,103 @@
1/* DMA controller registers */
2#define REG8_1(a0) ((const u16[8]) {a0, a0 + 1, a0 + 2, a0 + 3, \
3 a0 + 4, a0 + 5, a0 + 6, a0 + 7})
4#define REG8_2(a0) ((const u16[8]) {a0, a0 + 2, a0 + 4, a0 + 6, \
5 a0 + 8, a0 + 0xA, a0 + 0xC, a0 + 0xE})
6#define REG8_8(a0) ((const u16[8]) {a0, a0 + 8, a0 + 0x10, a0 + 0x18, \
7 a0 + 0x20, a0 + 0x28, a0 + 0x30, a0 + 0x38})
8#define INT_STATUS 0x00
9#define PB_STATUS 0x01
10#define DMA_CMD 0x02
11#define VIDEO_FIFO_STATUS 0x03
12#define VIDEO_CHANNEL_ID 0x04
13#define VIDEO_PARSER_STATUS 0x05
14#define SYS_SOFT_RST 0x06
15#define DMA_PAGE_TABLE0_ADDR ((const u16[8]) {0x08, 0xD0, 0xD2, 0xD4, \
16 0xD6, 0xD8, 0xDA, 0xDC})
17#define DMA_PAGE_TABLE1_ADDR ((const u16[8]) {0x09, 0xD1, 0xD3, 0xD5, \
18 0xD7, 0xD9, 0xDB, 0xDD})
19#define DMA_CHANNEL_ENABLE 0x0A
20#define DMA_CONFIG 0x0B
21#define DMA_TIMER_INTERVAL 0x0C
22#define DMA_CHANNEL_TIMEOUT 0x0D
23#define VDMA_CHANNEL_CONFIG REG8_1(0x10)
24#define ADMA_P_ADDR REG8_2(0x18)
25#define ADMA_B_ADDR REG8_2(0x19)
26#define DMA10_P_ADDR 0x28 /* ??? */
27#define DMA10_B_ADDR 0x29
28#define VIDEO_CONTROL1 0x2A
29#define VIDEO_CONTROL2 0x2B
30#define AUDIO_CONTROL1 0x2C
31#define AUDIO_CONTROL2 0x2D
32#define PHASE_REF 0x2E
33#define GPIO_REG 0x2F
34#define INTL_HBAR_CTRL REG8_1(0x30)
35#define AUDIO_CONTROL3 0x38
36#define VIDEO_FIELD_CTRL REG8_1(0x39)
37#define HSCALER_CTRL REG8_1(0x42)
38#define VIDEO_SIZE REG8_1(0x4A)
39#define VIDEO_SIZE_F2 REG8_1(0x52)
40#define MD_CONF REG8_1(0x60)
41#define MD_INIT REG8_1(0x68)
42#define MD_MAP0 REG8_1(0x70)
43#define VDMA_P_ADDR REG8_8(0x80) /* not used in DMA SG mode */
44#define VDMA_WHP REG8_8(0x81)
45#define VDMA_B_ADDR REG8_8(0x82)
46#define VDMA_F2_P_ADDR REG8_8(0x84)
47#define VDMA_F2_WHP REG8_8(0x85)
48#define VDMA_F2_B_ADDR REG8_8(0x86)
49#define EP_REG_ADDR 0xFE
50#define EP_REG_DATA 0xFF
51
52/* Video decoder registers */
53#define VDREG8(a0) ((const u16[8]) { \
54 a0 + 0x000, a0 + 0x010, a0 + 0x020, a0 + 0x030, \
55 a0 + 0x100, a0 + 0x110, a0 + 0x120, a0 + 0x130})
56#define VIDSTAT VDREG8(0x100)
57#define BRIGHT VDREG8(0x101)
58#define CONTRAST VDREG8(0x102)
59#define SHARPNESS VDREG8(0x103)
60#define SAT_U VDREG8(0x104)
61#define SAT_V VDREG8(0x105)
62#define HUE VDREG8(0x106)
63#define CROP_HI VDREG8(0x107)
64#define VDELAY_LO VDREG8(0x108)
65#define VACTIVE_LO VDREG8(0x109)
66#define HDELAY_LO VDREG8(0x10A)
67#define HACTIVE_LO VDREG8(0x10B)
68#define MVSN VDREG8(0x10C)
69#define STATUS2 VDREG8(0x10C)
70#define SDT VDREG8(0x10E)
71#define SDT_EN VDREG8(0x10F)
72
73#define VSCALE_LO VDREG8(0x144)
74#define SCALE_HI VDREG8(0x145)
75#define HSCALE_LO VDREG8(0x146)
76#define F2CROP_HI VDREG8(0x147)
77#define F2VDELAY_LO VDREG8(0x148)
78#define F2VACTIVE_LO VDREG8(0x149)
79#define F2HDELAY_LO VDREG8(0x14A)
80#define F2HACTIVE_LO VDREG8(0x14B)
81#define F2VSCALE_LO VDREG8(0x14C)
82#define F2SCALE_HI VDREG8(0x14D)
83#define F2HSCALE_LO VDREG8(0x14E)
84#define F2CNT VDREG8(0x14F)
85
86#define VDREG2(a0) ((const u16[2]) {a0, a0 + 0x100})
87#define SRST VDREG2(0x180)
88#define ACNTL VDREG2(0x181)
89#define ACNTL2 VDREG2(0x182)
90#define CNTRL1 VDREG2(0x183)
91#define CKHY VDREG2(0x184)
92#define SHCOR VDREG2(0x185)
93#define CORING VDREG2(0x186)
94#define CLMPG VDREG2(0x187)
95#define IAGC VDREG2(0x188)
96#define VCTRL1 VDREG2(0x18F)
97#define MISC1 VDREG2(0x194)
98#define LOOP VDREG2(0x195)
99#define MISC2 VDREG2(0x196)
100
101#define CLMD VDREG2(0x197)
102#define AIGAIN ((const u16[8]) {0x1D0, 0x1D1, 0x1D2, 0x1D3, \
103 0x2D0, 0x2D1, 0x2D2, 0x2D3})
diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c
new file mode 100644
index 000000000000..6ecb504a79f9
--- /dev/null
+++ b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c
@@ -0,0 +1,821 @@
1/*
2 * Copyright (C) 2015 Industrial Research Institute for Automation
3 * and Measurements PIAP
4 *
5 * Written by Krzysztof Ha?asa.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License
9 * as published by the Free Software Foundation.
10 */
11
12#include <linux/init.h>
13#include <linux/list.h>
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/slab.h>
17#include <media/v4l2-common.h>
18#include <media/v4l2-event.h>
19#include "tw686x-kh.h"
20#include "tw686x-kh-regs.h"
21
22#define MAX_SG_ENTRY_SIZE (/* 8192 - 128 */ 4096)
23#define MAX_SG_DESC_COUNT 256 /* PAL 704x576 needs up to 198 4-KB pages */
24
25static const struct tw686x_format formats[] = {
26 {
27 .name = "4:2:2 packed, UYVY", /* aka Y422 */
28 .fourcc = V4L2_PIX_FMT_UYVY,
29 .mode = 0,
30 .depth = 16,
31 }, {
32#if 0
33 .name = "4:2:0 packed, YUV",
34 .mode = 1, /* non-standard */
35 .depth = 12,
36 }, {
37 .name = "4:1:1 packed, YUV",
38 .mode = 2, /* non-standard */
39 .depth = 12,
40 }, {
41#endif
42 .name = "4:1:1 packed, YUV",
43 .fourcc = V4L2_PIX_FMT_Y41P,
44 .mode = 3,
45 .depth = 12,
46 }, {
47 .name = "15 bpp RGB",
48 .fourcc = V4L2_PIX_FMT_RGB555,
49 .mode = 4,
50 .depth = 16,
51 }, {
52 .name = "16 bpp RGB",
53 .fourcc = V4L2_PIX_FMT_RGB565,
54 .mode = 5,
55 .depth = 16,
56 }, {
57 .name = "4:2:2 packed, YUYV",
58 .fourcc = V4L2_PIX_FMT_YUYV,
59 .mode = 6,
60 .depth = 16,
61 }
62 /* mode 7 is "reserved" */
63};
64
65static const v4l2_std_id video_standards[7] = {
66 V4L2_STD_NTSC,
67 V4L2_STD_PAL,
68 V4L2_STD_SECAM,
69 V4L2_STD_NTSC_443,
70 V4L2_STD_PAL_M,
71 V4L2_STD_PAL_N,
72 V4L2_STD_PAL_60,
73};
74
75static const struct tw686x_format *format_by_fourcc(unsigned int fourcc)
76{
77 unsigned int cnt;
78
79 for (cnt = 0; cnt < ARRAY_SIZE(formats); cnt++)
80 if (formats[cnt].fourcc == fourcc)
81 return &formats[cnt];
82 return NULL;
83}
84
85static void tw686x_get_format(struct tw686x_video_channel *vc,
86 struct v4l2_format *f)
87{
88 const struct tw686x_format *format;
89 unsigned int width, height, height_div = 1;
90
91 format = format_by_fourcc(f->fmt.pix.pixelformat);
92 if (!format) {
93 format = &formats[0];
94 f->fmt.pix.pixelformat = format->fourcc;
95 }
96
97 width = 704;
98 if (f->fmt.pix.width < width * 3 / 4 /* halfway */)
99 width /= 2;
100
101 height = (vc->video_standard & V4L2_STD_625_50) ? 576 : 480;
102 if (f->fmt.pix.height < height * 3 / 4 /* halfway */)
103 height_div = 2;
104
105 switch (f->fmt.pix.field) {
106 case V4L2_FIELD_TOP:
107 case V4L2_FIELD_BOTTOM:
108 height_div = 2;
109 break;
110 case V4L2_FIELD_SEQ_BT:
111 if (height_div > 1)
112 f->fmt.pix.field = V4L2_FIELD_BOTTOM;
113 break;
114 default:
115 if (height_div > 1)
116 f->fmt.pix.field = V4L2_FIELD_TOP;
117 else
118 f->fmt.pix.field = V4L2_FIELD_SEQ_TB;
119 }
120 height /= height_div;
121
122 f->fmt.pix.width = width;
123 f->fmt.pix.height = height;
124 f->fmt.pix.bytesperline = f->fmt.pix.width * format->depth / 8;
125 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
126 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
127}
128
129/* video queue operations */
130
131static int tw686x_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
132 unsigned int *nplanes, unsigned int sizes[],
133 void *alloc_ctxs[])
134{
135 struct tw686x_video_channel *vc = vb2_get_drv_priv(vq);
136 unsigned int size = vc->width * vc->height * vc->format->depth / 8;
137
138 alloc_ctxs[0] = vc->alloc_ctx;
139 if (*nbuffers < 2)
140 *nbuffers = 2;
141
142 if (*nplanes)
143 return sizes[0] < size ? -EINVAL : 0;
144
145 sizes[0] = size;
146 *nplanes = 1; /* packed formats only */
147 return 0;
148}
149
150static void tw686x_buf_queue(struct vb2_buffer *vb)
151{
152 struct tw686x_video_channel *vc = vb2_get_drv_priv(vb->vb2_queue);
153 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
154 struct tw686x_vb2_buf *buf;
155
156 buf = container_of(vbuf, struct tw686x_vb2_buf, vb);
157
158 spin_lock(&vc->qlock);
159 list_add_tail(&buf->list, &vc->vidq_queued);
160 spin_unlock(&vc->qlock);
161}
162
163static void setup_descs(struct tw686x_video_channel *vc, unsigned int n)
164{
165loop:
166 while (!list_empty(&vc->vidq_queued)) {
167 struct vdma_desc *descs = vc->sg_descs[n];
168 struct tw686x_vb2_buf *buf;
169 struct sg_table *vbuf;
170 struct scatterlist *sg;
171 unsigned int buf_len, count = 0;
172 int i;
173
174 buf = list_first_entry(&vc->vidq_queued, struct tw686x_vb2_buf,
175 list);
176 list_del(&buf->list);
177
178 buf_len = vc->width * vc->height * vc->format->depth / 8;
179 if (vb2_plane_size(&buf->vb.vb2_buf, 0) < buf_len) {
180 pr_err("Video buffer size too small\n");
181 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
182 goto loop; /* try another */
183 }
184
185 vbuf = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
186 for_each_sg(vbuf->sgl, sg, vbuf->nents, i) {
187 dma_addr_t phys = sg_dma_address(sg);
188 unsigned int len = sg_dma_len(sg);
189
190 while (len && buf_len) {
191 unsigned int entry_len = min_t(unsigned int, len,
192 MAX_SG_ENTRY_SIZE);
193 entry_len = min(entry_len, buf_len);
194 if (count == MAX_SG_DESC_COUNT) {
195 pr_err("Video buffer size too fragmented\n");
196 vb2_buffer_done(&buf->vb.vb2_buf,
197 VB2_BUF_STATE_ERROR);
198 goto loop;
199 }
200 descs[count].phys = cpu_to_le32(phys);
201 descs[count++].flags_length =
202 cpu_to_le32(0x40000000 /* available */ |
203 entry_len);
204 phys += entry_len;
205 len -= entry_len;
206 buf_len -= entry_len;
207 }
208 if (!buf_len)
209 break;
210 }
211
212 /* clear the remaining entries */
213 while (count < MAX_SG_DESC_COUNT) {
214 descs[count].phys = 0;
215 descs[count++].flags_length = 0; /* unavailable */
216 }
217
218 buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
219 vc->curr_bufs[n] = buf;
220 return;
221 }
222 vc->curr_bufs[n] = NULL;
223}
224
225/* On TW6864 and TW6868, all channels share the pair of video DMA SG tables,
226 with 10-bit start_idx and end_idx determining start and end of frame buffer
227 for particular channel.
228 TW6868 with all its 8 channels would be problematic (only 127 SG entries per
229 channel) but we support only 4 channels on this chip anyway (the first
230 4 channels are driven with internal video decoder, the other 4 would require
231 an external TW286x part).
232
233 On TW6865 and TW6869, each channel has its own DMA SG table, with indexes
234 starting with 0. Both chips have complete sets of internal video decoders
235 (respectively 4 or 8-channel).
236
237 All chips have separate SG tables for two video frames. */
238
239static void setup_dma_cfg(struct tw686x_video_channel *vc)
240{
241 unsigned int field_width = 704;
242 unsigned int field_height = (vc->video_standard & V4L2_STD_625_50) ?
243 288 : 240;
244 unsigned int start_idx = is_second_gen(vc->dev) ? 0 :
245 vc->ch * MAX_SG_DESC_COUNT;
246 unsigned int end_idx = start_idx + MAX_SG_DESC_COUNT - 1;
247 u32 dma_cfg = (0 << 30) /* input selection */ |
248 (1 << 29) /* field2 dropped (if any) */ |
249 ((vc->height < 300) << 28) /* field dropping */ |
250 (1 << 27) /* master */ |
251 (0 << 25) /* master channel (for slave only) */ |
252 (0 << 24) /* (no) vertical (line) decimation */ |
253 ((vc->width < 400) << 23) /* horizontal decimation */ |
254 (vc->format->mode << 20) /* output video format */ |
255 (end_idx << 10) /* DMA end index */ |
256 start_idx /* DMA start index */;
257 u32 reg;
258
259 reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], dma_cfg);
260 reg_write(vc->dev, VIDEO_SIZE[vc->ch], (1 << 31) | (field_height << 16)
261 | field_width);
262 reg = reg_read(vc->dev, VIDEO_CONTROL1);
263 if (vc->video_standard & V4L2_STD_625_50)
264 reg |= 1 << (vc->ch + 13);
265 else
266 reg &= ~(1 << (vc->ch + 13));
267 reg_write(vc->dev, VIDEO_CONTROL1, reg);
268}
269
270static int tw686x_start_streaming(struct vb2_queue *vq, unsigned int count)
271{
272 struct tw686x_video_channel *vc = vb2_get_drv_priv(vq);
273 struct tw686x_dev *dev = vc->dev;
274 u32 dma_ch_mask;
275 unsigned int n;
276
277 setup_dma_cfg(vc);
278
279 /* queue video buffers if available */
280 spin_lock(&vc->qlock);
281 for (n = 0; n < 2; n++)
282 setup_descs(vc, n);
283 spin_unlock(&vc->qlock);
284
285 dev->video_active |= 1 << vc->ch;
286 vc->seq = 0;
287 dma_ch_mask = reg_read(dev, DMA_CHANNEL_ENABLE) | (1 << vc->ch);
288 reg_write(dev, DMA_CHANNEL_ENABLE, dma_ch_mask);
289 reg_write(dev, DMA_CMD, (1 << 31) | dma_ch_mask);
290 return 0;
291}
292
293static void tw686x_stop_streaming(struct vb2_queue *vq)
294{
295 struct tw686x_video_channel *vc = vb2_get_drv_priv(vq);
296 struct tw686x_dev *dev = vc->dev;
297 u32 dma_ch_mask = reg_read(dev, DMA_CHANNEL_ENABLE);
298 u32 dma_cmd = reg_read(dev, DMA_CMD);
299 unsigned int n;
300
301 dma_ch_mask &= ~(1 << vc->ch);
302 reg_write(dev, DMA_CHANNEL_ENABLE, dma_ch_mask);
303
304 dev->video_active &= ~(1 << vc->ch);
305
306 dma_cmd &= ~(1 << vc->ch);
307 reg_write(dev, DMA_CMD, dma_cmd);
308
309 if (!dev->video_active) {
310 reg_write(dev, DMA_CMD, 0);
311 reg_write(dev, DMA_CHANNEL_ENABLE, 0);
312 }
313
314 spin_lock(&vc->qlock);
315 while (!list_empty(&vc->vidq_queued)) {
316 struct tw686x_vb2_buf *buf;
317
318 buf = list_entry(vc->vidq_queued.next, struct tw686x_vb2_buf,
319 list);
320 list_del(&buf->list);
321 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
322 }
323
324 for (n = 0; n < 2; n++)
325 if (vc->curr_bufs[n])
326 vb2_buffer_done(&vc->curr_bufs[n]->vb.vb2_buf,
327 VB2_BUF_STATE_ERROR);
328
329 spin_unlock(&vc->qlock);
330}
331
332static struct vb2_ops tw686x_video_qops = {
333 .queue_setup = tw686x_queue_setup,
334 .buf_queue = tw686x_buf_queue,
335 .start_streaming = tw686x_start_streaming,
336 .stop_streaming = tw686x_stop_streaming,
337 .wait_prepare = vb2_ops_wait_prepare,
338 .wait_finish = vb2_ops_wait_finish,
339};
340
341static int tw686x_s_ctrl(struct v4l2_ctrl *ctrl)
342{
343 struct tw686x_video_channel *vc;
344 struct tw686x_dev *dev;
345 unsigned int ch;
346
347 vc = container_of(ctrl->handler, struct tw686x_video_channel,
348 ctrl_handler);
349 dev = vc->dev;
350 ch = vc->ch;
351
352 switch (ctrl->id) {
353 case V4L2_CID_BRIGHTNESS:
354 reg_write(dev, BRIGHT[ch], ctrl->val & 0xFF);
355 return 0;
356
357 case V4L2_CID_CONTRAST:
358 reg_write(dev, CONTRAST[ch], ctrl->val);
359 return 0;
360
361 case V4L2_CID_SATURATION:
362 reg_write(dev, SAT_U[ch], ctrl->val);
363 reg_write(dev, SAT_V[ch], ctrl->val);
364 return 0;
365
366 case V4L2_CID_HUE:
367 reg_write(dev, HUE[ch], ctrl->val & 0xFF);
368 return 0;
369 }
370
371 return -EINVAL;
372}
373
374static const struct v4l2_ctrl_ops ctrl_ops = {
375 .s_ctrl = tw686x_s_ctrl,
376};
377
378static int tw686x_g_fmt_vid_cap(struct file *file, void *priv,
379 struct v4l2_format *f)
380{
381 struct tw686x_video_channel *vc = video_drvdata(file);
382
383 f->fmt.pix.width = vc->width;
384 f->fmt.pix.height = vc->height;
385 f->fmt.pix.field = vc->field;
386 f->fmt.pix.pixelformat = vc->format->fourcc;
387 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
388 f->fmt.pix.bytesperline = f->fmt.pix.width * vc->format->depth / 8;
389 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
390 return 0;
391}
392
393static int tw686x_try_fmt_vid_cap(struct file *file, void *priv,
394 struct v4l2_format *f)
395{
396 tw686x_get_format(video_drvdata(file), f);
397 return 0;
398}
399
400static int tw686x_s_fmt_vid_cap(struct file *file, void *priv,
401 struct v4l2_format *f)
402{
403 struct tw686x_video_channel *vc = video_drvdata(file);
404
405 tw686x_get_format(vc, f);
406 vc->format = format_by_fourcc(f->fmt.pix.pixelformat);
407 vc->field = f->fmt.pix.field;
408 vc->width = f->fmt.pix.width;
409 vc->height = f->fmt.pix.height;
410 return 0;
411}
412
413static int tw686x_querycap(struct file *file, void *priv,
414 struct v4l2_capability *cap)
415{
416 struct tw686x_video_channel *vc = video_drvdata(file);
417 struct tw686x_dev *dev = vc->dev;
418
419 strcpy(cap->driver, "tw686x-kh");
420 strcpy(cap->card, dev->name);
421 sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci_dev));
422 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
423 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
424 return 0;
425}
426
427static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id)
428{
429 struct tw686x_video_channel *vc = video_drvdata(file);
430 unsigned int cnt;
431 u32 sdt = 0; /* default */
432
433 for (cnt = 0; cnt < ARRAY_SIZE(video_standards); cnt++)
434 if (id & video_standards[cnt]) {
435 sdt = cnt;
436 break;
437 }
438
439 reg_write(vc->dev, SDT[vc->ch], sdt);
440 vc->video_standard = video_standards[sdt];
441 return 0;
442}
443
444static int tw686x_g_std(struct file *file, void *priv, v4l2_std_id *id)
445{
446 struct tw686x_video_channel *vc = video_drvdata(file);
447
448 *id = vc->video_standard;
449 return 0;
450}
451
452static int tw686x_enum_fmt_vid_cap(struct file *file, void *priv,
453 struct v4l2_fmtdesc *f)
454{
455 if (f->index >= ARRAY_SIZE(formats))
456 return -EINVAL;
457
458 strlcpy(f->description, formats[f->index].name, sizeof(f->description));
459 f->pixelformat = formats[f->index].fourcc;
460 return 0;
461}
462
463static int tw686x_g_parm(struct file *file, void *priv,
464 struct v4l2_streamparm *sp)
465{
466 struct tw686x_video_channel *vc = video_drvdata(file);
467
468 if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
469 return -EINVAL;
470 memset(&sp->parm.capture, 0, sizeof(sp->parm.capture));
471 sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
472 v4l2_video_std_frame_period(vc->video_standard,
473 &sp->parm.capture.timeperframe);
474
475 return 0;
476}
477
478static int tw686x_enum_input(struct file *file, void *priv,
479 struct v4l2_input *inp)
480{
481 /* the chip has internal multiplexer, support can be added
482 if the actual hw uses it */
483 if (inp->index)
484 return -EINVAL;
485
486 snprintf(inp->name, sizeof(inp->name), "Composite");
487 inp->type = V4L2_INPUT_TYPE_CAMERA;
488 inp->std = V4L2_STD_ALL;
489 inp->capabilities = V4L2_IN_CAP_STD;
490 return 0;
491}
492
493static int tw686x_g_input(struct file *file, void *priv, unsigned int *v)
494{
495 *v = 0;
496 return 0;
497}
498
499static int tw686x_s_input(struct file *file, void *priv, unsigned int v)
500{
501 if (v)
502 return -EINVAL;
503 return 0;
504}
505
506static const struct v4l2_file_operations tw686x_video_fops = {
507 .owner = THIS_MODULE,
508 .open = v4l2_fh_open,
509 .unlocked_ioctl = video_ioctl2,
510 .release = vb2_fop_release,
511 .poll = vb2_fop_poll,
512 .read = vb2_fop_read,
513 .mmap = vb2_fop_mmap,
514};
515
516static const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = {
517 .vidioc_querycap = tw686x_querycap,
518 .vidioc_enum_fmt_vid_cap = tw686x_enum_fmt_vid_cap,
519 .vidioc_g_fmt_vid_cap = tw686x_g_fmt_vid_cap,
520 .vidioc_s_fmt_vid_cap = tw686x_s_fmt_vid_cap,
521 .vidioc_try_fmt_vid_cap = tw686x_try_fmt_vid_cap,
522 .vidioc_reqbufs = vb2_ioctl_reqbufs,
523 .vidioc_querybuf = vb2_ioctl_querybuf,
524 .vidioc_qbuf = vb2_ioctl_qbuf,
525 .vidioc_dqbuf = vb2_ioctl_dqbuf,
526 .vidioc_create_bufs = vb2_ioctl_create_bufs,
527 .vidioc_streamon = vb2_ioctl_streamon,
528 .vidioc_streamoff = vb2_ioctl_streamoff,
529 .vidioc_g_std = tw686x_g_std,
530 .vidioc_s_std = tw686x_s_std,
531 .vidioc_g_parm = tw686x_g_parm,
532 .vidioc_enum_input = tw686x_enum_input,
533 .vidioc_g_input = tw686x_g_input,
534 .vidioc_s_input = tw686x_s_input,
535 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
536 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
537};
538
539static int video_thread(void *arg)
540{
541 struct tw686x_dev *dev = arg;
542 DECLARE_WAITQUEUE(wait, current);
543
544 set_freezable();
545 add_wait_queue(&dev->video_thread_wait, &wait);
546
547 while (1) {
548 long timeout = schedule_timeout_interruptible(HZ);
549 unsigned int ch;
550
551 if (timeout == -ERESTARTSYS || kthread_should_stop())
552 break;
553
554 for (ch = 0; ch < max_channels(dev); ch++) {
555 struct tw686x_video_channel *vc;
556 unsigned long flags;
557 u32 request, n, stat = VB2_BUF_STATE_DONE;
558
559 vc = &dev->video_channels[ch];
560 if (!(dev->video_active & (1 << ch)))
561 continue;
562
563 spin_lock_irq(&dev->irq_lock);
564 request = dev->dma_requests & (0x01000001 << ch);
565 if (request)
566 dev->dma_requests &= ~request;
567 spin_unlock_irq(&dev->irq_lock);
568
569 if (!request)
570 continue;
571
572 request >>= ch;
573
574 /* handle channel events */
575 if ((request & 0x01000000) |
576 (reg_read(dev, VIDEO_FIFO_STATUS) & (0x01010001 << ch)) |
577 (reg_read(dev, VIDEO_PARSER_STATUS) & (0x00000101 << ch))) {
578 /* DMA Errors - reset channel */
579 u32 reg;
580
581 spin_lock_irqsave(&dev->irq_lock, flags);
582 reg = reg_read(dev, DMA_CMD);
583 /* Reset DMA channel */
584 reg_write(dev, DMA_CMD, reg & ~(1 << ch));
585 reg_write(dev, DMA_CMD, reg);
586 spin_unlock_irqrestore(&dev->irq_lock, flags);
587 stat = VB2_BUF_STATE_ERROR;
588 }
589
590 /* handle video stream */
591 mutex_lock(&vc->vb_mutex);
592 spin_lock(&vc->qlock);
593 n = !!(reg_read(dev, PB_STATUS) & (1 << ch));
594 if (vc->curr_bufs[n]) {
595 struct vb2_v4l2_buffer *vb;
596
597 vb = &vc->curr_bufs[n]->vb;
598 vb->vb2_buf.timestamp = ktime_get_ns();
599 vb->field = vc->field;
600 if (V4L2_FIELD_HAS_BOTH(vc->field))
601 vb->sequence = vc->seq++;
602 else
603 vb->sequence = (vc->seq++) / 2;
604 vb2_set_plane_payload(&vb->vb2_buf, 0,
605 vc->width * vc->height * vc->format->depth / 8);
606 vb2_buffer_done(&vb->vb2_buf, stat);
607 }
608 setup_descs(vc, n);
609 spin_unlock(&vc->qlock);
610 mutex_unlock(&vc->vb_mutex);
611 }
612 try_to_freeze();
613 }
614
615 remove_wait_queue(&dev->video_thread_wait, &wait);
616 return 0;
617}
618
619int tw686x_kh_video_irq(struct tw686x_dev *dev)
620{
621 unsigned long flags, handled = 0;
622 u32 requests;
623
624 spin_lock_irqsave(&dev->irq_lock, flags);
625 requests = dev->dma_requests;
626 spin_unlock_irqrestore(&dev->irq_lock, flags);
627
628 if (requests & dev->video_active) {
629 wake_up_interruptible_all(&dev->video_thread_wait);
630 handled = 1;
631 }
632 return handled;
633}
634
635void tw686x_kh_video_free(struct tw686x_dev *dev)
636{
637 unsigned int ch, n;
638
639 if (dev->video_thread)
640 kthread_stop(dev->video_thread);
641
642 for (ch = 0; ch < max_channels(dev); ch++) {
643 struct tw686x_video_channel *vc = &dev->video_channels[ch];
644
645 v4l2_ctrl_handler_free(&vc->ctrl_handler);
646 if (vc->device)
647 video_unregister_device(vc->device);
648 vb2_dma_sg_cleanup_ctx(vc->alloc_ctx);
649 for (n = 0; n < 2; n++) {
650 struct dma_desc *descs = &vc->sg_tables[n];
651
652 if (descs->virt)
653 pci_free_consistent(dev->pci_dev, descs->size,
654 descs->virt, descs->phys);
655 }
656 }
657
658 v4l2_device_unregister(&dev->v4l2_dev);
659}
660
661#define SG_TABLE_SIZE (MAX_SG_DESC_COUNT * sizeof(struct vdma_desc))
662
663int tw686x_kh_video_init(struct tw686x_dev *dev)
664{
665 unsigned int ch, n;
666 int err;
667
668 init_waitqueue_head(&dev->video_thread_wait);
669
670 err = v4l2_device_register(&dev->pci_dev->dev, &dev->v4l2_dev);
671 if (err)
672 return err;
673
674 reg_write(dev, VIDEO_CONTROL1, 0); /* NTSC, disable scaler */
675 reg_write(dev, PHASE_REF, 0x00001518); /* Scatter-gather DMA mode */
676
677 /* setup required SG table sizes */
678 for (n = 0; n < 2; n++)
679 if (is_second_gen(dev)) {
680 /* TW 6865, TW6869 - each channel needs a pair of
681 descriptor tables */
682 for (ch = 0; ch < max_channels(dev); ch++)
683 dev->video_channels[ch].sg_tables[n].size =
684 SG_TABLE_SIZE;
685
686 } else
687 /* TW 6864, TW6868 - we need to allocate a pair of
688 descriptor tables, common for all channels.
689 Each table will be bigger than 4 KB. */
690 dev->video_channels[0].sg_tables[n].size =
691 max_channels(dev) * SG_TABLE_SIZE;
692
693 /* allocate SG tables and initialize video channels */
694 for (ch = 0; ch < max_channels(dev); ch++) {
695 struct tw686x_video_channel *vc = &dev->video_channels[ch];
696 struct video_device *vdev;
697
698 mutex_init(&vc->vb_mutex);
699 spin_lock_init(&vc->qlock);
700 INIT_LIST_HEAD(&vc->vidq_queued);
701
702 vc->dev = dev;
703 vc->ch = ch;
704
705 /* default settings: NTSC */
706 vc->format = &formats[0];
707 vc->video_standard = V4L2_STD_NTSC;
708 reg_write(vc->dev, SDT[vc->ch], 0);
709 vc->field = V4L2_FIELD_SEQ_BT;
710 vc->width = 704;
711 vc->height = 480;
712
713 for (n = 0; n < 2; n++) {
714 void *cpu;
715
716 if (vc->sg_tables[n].size) {
717 unsigned int reg = n ? DMA_PAGE_TABLE1_ADDR[ch] :
718 DMA_PAGE_TABLE0_ADDR[ch];
719
720 cpu = pci_alloc_consistent(dev->pci_dev,
721 vc->sg_tables[n].size,
722 &vc->sg_tables[n].phys);
723 if (!cpu) {
724 pr_err("Error allocating video DMA scatter-gather tables\n");
725 err = -ENOMEM;
726 goto error;
727 }
728 vc->sg_tables[n].virt = cpu;
729 reg_write(dev, reg, vc->sg_tables[n].phys);
730 } else
731 cpu = dev->video_channels[0].sg_tables[n].virt +
732 ch * SG_TABLE_SIZE;
733
734 vc->sg_descs[n] = cpu;
735 }
736
737 reg_write(dev, VCTRL1[0], 0x24);
738 reg_write(dev, LOOP[0], 0xA5);
739 if (max_channels(dev) > 4) {
740 reg_write(dev, VCTRL1[1], 0x24);
741 reg_write(dev, LOOP[1], 0xA5);
742 }
743 reg_write(dev, VIDEO_FIELD_CTRL[ch], 0);
744 reg_write(dev, VDELAY_LO[ch], 0x14);
745
746 vdev = video_device_alloc();
747 if (!vdev) {
748 pr_warn("Unable to allocate video device\n");
749 err = -ENOMEM;
750 goto error;
751 }
752
753 vc->alloc_ctx = vb2_dma_sg_init_ctx(&dev->pci_dev->dev);
754 if (IS_ERR(vc->alloc_ctx)) {
755 pr_warn("Unable to initialize DMA scatter-gather context\n");
756 err = PTR_ERR(vc->alloc_ctx);
757 goto error;
758 }
759
760 vc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
761 vc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
762 vc->vidq.drv_priv = vc;
763 vc->vidq.buf_struct_size = sizeof(struct tw686x_vb2_buf);
764 vc->vidq.ops = &tw686x_video_qops;
765 vc->vidq.mem_ops = &vb2_dma_sg_memops;
766 vc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
767 vc->vidq.min_buffers_needed = 2;
768 vc->vidq.lock = &vc->vb_mutex;
769 vc->vidq.gfp_flags = GFP_DMA32;
770
771 err = vb2_queue_init(&vc->vidq);
772 if (err)
773 goto error;
774
775 strcpy(vdev->name, "TW686x-video");
776 snprintf(vdev->name, sizeof(vdev->name), "%s video", dev->name);
777 vdev->fops = &tw686x_video_fops;
778 vdev->ioctl_ops = &tw686x_video_ioctl_ops;
779 vdev->release = video_device_release;
780 vdev->v4l2_dev = &dev->v4l2_dev;
781 vdev->queue = &vc->vidq;
782 vdev->tvnorms = V4L2_STD_ALL;
783 vdev->minor = -1;
784 vdev->lock = &vc->vb_mutex;
785
786 dev->video_channels[ch].device = vdev;
787 video_set_drvdata(vdev, vc);
788 err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
789 if (err < 0)
790 goto error;
791
792 v4l2_ctrl_handler_init(&vc->ctrl_handler,
793 4 /* number of controls */);
794 vdev->ctrl_handler = &vc->ctrl_handler;
795 v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops,
796 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
797 v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops,
798 V4L2_CID_CONTRAST, 0, 255, 1, 64);
799 v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops,
800 V4L2_CID_SATURATION, 0, 255, 1, 128);
801 v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, V4L2_CID_HUE,
802 -124, 127, 1, 0);
803 err = vc->ctrl_handler.error;
804 if (err)
805 goto error;
806
807 v4l2_ctrl_handler_setup(&vc->ctrl_handler);
808 }
809
810 dev->video_thread = kthread_run(video_thread, dev, "tw686x_video");
811 if (IS_ERR(dev->video_thread)) {
812 err = PTR_ERR(dev->video_thread);
813 goto error;
814 }
815
816 return 0;
817
818error:
819 tw686x_kh_video_free(dev);
820 return err;
821}
diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh.h b/drivers/staging/media/tw686x-kh/tw686x-kh.h
new file mode 100644
index 000000000000..dc257967dbc7
--- /dev/null
+++ b/drivers/staging/media/tw686x-kh/tw686x-kh.h
@@ -0,0 +1,118 @@
1/*
2 * Copyright (C) 2015 Industrial Research Institute for Automation
3 * and Measurements PIAP
4 *
5 * Written by Krzysztof Ha?asa.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License
9 * as published by the Free Software Foundation.
10 */
11
12#include <linux/delay.h>
13#include <linux/freezer.h>
14#include <linux/interrupt.h>
15#include <linux/kthread.h>
16#include <linux/mutex.h>
17#include <linux/pci.h>
18#include <media/videobuf2-dma-sg.h>
19#include <linux/videodev2.h>
20#include <media/v4l2-common.h>
21#include <media/v4l2-ctrls.h>
22#include <media/v4l2-device.h>
23#include <media/v4l2-ioctl.h>
24
25#define TYPE_MAX_CHANNELS 0x0F
26#define TYPE_SECOND_GEN 0x10
27
28struct tw686x_format {
29 char *name;
30 unsigned int fourcc;
31 unsigned int depth;
32 unsigned int mode;
33};
34
35struct dma_desc {
36 dma_addr_t phys;
37 void *virt;
38 unsigned int size;
39};
40
41struct vdma_desc {
42 __le32 flags_length; /* 3 MSBits for flags, 13 LSBits for length */
43 __le32 phys;
44};
45
46struct tw686x_vb2_buf {
47 struct vb2_v4l2_buffer vb;
48 struct list_head list;
49};
50
51struct tw686x_video_channel {
52 struct tw686x_dev *dev;
53
54 struct vb2_queue vidq;
55 struct list_head vidq_queued;
56 struct video_device *device;
57 struct dma_desc sg_tables[2];
58 struct tw686x_vb2_buf *curr_bufs[2];
59 void *alloc_ctx;
60 struct vdma_desc *sg_descs[2];
61
62 struct v4l2_ctrl_handler ctrl_handler;
63 const struct tw686x_format *format;
64 struct mutex vb_mutex;
65 spinlock_t qlock;
66 v4l2_std_id video_standard;
67 unsigned int width, height;
68 enum v4l2_field field; /* supported TOP, BOTTOM, SEQ_TB and SEQ_BT */
69 unsigned int seq; /* video field or frame counter */
70 unsigned int ch;
71};
72
73/* global device status */
74struct tw686x_dev {
75 spinlock_t irq_lock;
76
77 struct v4l2_device v4l2_dev;
78 struct snd_card *card; /* sound card */
79
80 unsigned int video_active; /* active video channel mask */
81
82 char name[32];
83 unsigned int type;
84 struct pci_dev *pci_dev;
85 __u32 __iomem *mmio;
86
87 struct task_struct *video_thread;
88 wait_queue_head_t video_thread_wait;
89 u32 dma_requests;
90
91 struct tw686x_video_channel video_channels[0];
92};
93
94static inline uint32_t reg_read(struct tw686x_dev *dev, unsigned int reg)
95{
96 return readl(dev->mmio + reg);
97}
98
99static inline void reg_write(struct tw686x_dev *dev, unsigned int reg,
100 uint32_t value)
101{
102 writel(value, dev->mmio + reg);
103}
104
105static inline unsigned int max_channels(struct tw686x_dev *dev)
106{
107 return dev->type & TYPE_MAX_CHANNELS; /* 4 or 8 channels */
108}
109
110static inline unsigned int is_second_gen(struct tw686x_dev *dev)
111{
112 /* each channel has its own DMA SG table */
113 return dev->type & TYPE_SECOND_GEN;
114}
115
116int tw686x_kh_video_irq(struct tw686x_dev *dev);
117int tw686x_kh_video_init(struct tw686x_dev *dev);
118void tw686x_kh_video_free(struct tw686x_dev *dev);
diff --git a/include/media/media-device.h b/include/media/media-device.h
index df74cfa7da4a..a9b33c47310d 100644
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -25,7 +25,6 @@
25 25
26#include <linux/list.h> 26#include <linux/list.h>
27#include <linux/mutex.h> 27#include <linux/mutex.h>
28#include <linux/spinlock.h>
29 28
30#include <media/media-devnode.h> 29#include <media/media-devnode.h>
31#include <media/media-entity.h> 30#include <media/media-entity.h>
@@ -304,8 +303,7 @@ struct media_entity_notify {
304 * @pads: List of registered pads 303 * @pads: List of registered pads
305 * @links: List of registered links 304 * @links: List of registered links
306 * @entity_notify: List of registered entity_notify callbacks 305 * @entity_notify: List of registered entity_notify callbacks
307 * @lock: Entities list lock 306 * @graph_mutex: Protects access to struct media_device data
308 * @graph_mutex: Entities graph operation lock
309 * @pm_count_walk: Graph walk for power state walk. Access serialised using 307 * @pm_count_walk: Graph walk for power state walk. Access serialised using
310 * graph_mutex. 308 * graph_mutex.
311 * 309 *
@@ -313,7 +311,8 @@ struct media_entity_notify {
313 * @enable_source: Enable Source Handler function pointer 311 * @enable_source: Enable Source Handler function pointer
314 * @disable_source: Disable Source Handler function pointer 312 * @disable_source: Disable Source Handler function pointer
315 * 313 *
316 * @link_notify: Link state change notification callback 314 * @link_notify: Link state change notification callback. This callback is
315 * called with the graph_mutex held.
317 * 316 *
318 * This structure represents an abstract high-level media device. It allows easy 317 * This structure represents an abstract high-level media device. It allows easy
319 * access to entities and provides basic media device-level support. The 318 * access to entities and provides basic media device-level support. The
@@ -357,7 +356,7 @@ struct media_device {
357 u32 hw_revision; 356 u32 hw_revision;
358 u32 driver_version; 357 u32 driver_version;
359 358
360 u32 topology_version; 359 u64 topology_version;
361 360
362 u32 id; 361 u32 id;
363 struct ida entity_internal_idx; 362 struct ida entity_internal_idx;
@@ -371,8 +370,6 @@ struct media_device {
371 /* notify callback list invoked when a new entity is registered */ 370 /* notify callback list invoked when a new entity is registered */
372 struct list_head entity_notify; 371 struct list_head entity_notify;
373 372
374 /* Protects the graph objects creation/removal */
375 spinlock_t lock;
376 /* Serializes graph operations. */ 373 /* Serializes graph operations. */
377 struct mutex graph_mutex; 374 struct mutex graph_mutex;
378 struct media_entity_graph pm_count_walk; 375 struct media_entity_graph pm_count_walk;
@@ -494,7 +491,7 @@ int __must_check __media_device_register(struct media_device *mdev,
494#define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE) 491#define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE)
495 492
496/** 493/**
497 * __media_device_unregister() - Unegisters a media device element 494 * media_device_unregister() - Unregisters a media device element
498 * 495 *
499 * @mdev: pointer to struct &media_device 496 * @mdev: pointer to struct &media_device
500 * 497 *
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 6dc9e4e8cbd4..cbb266f7f2b5 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -179,6 +179,9 @@ struct media_pad {
179 * @link_validate: Return whether a link is valid from the entity point of 179 * @link_validate: Return whether a link is valid from the entity point of
180 * view. The media_entity_pipeline_start() function 180 * view. The media_entity_pipeline_start() function
181 * validates all links by calling this operation. Optional. 181 * validates all links by calling this operation. Optional.
182 *
183 * Note: Those these callbacks are called with struct media_device.@graph_mutex
184 * mutex held.
182 */ 185 */
183struct media_entity_operations { 186struct media_entity_operations {
184 int (*link_setup)(struct media_entity *entity, 187 int (*link_setup)(struct media_entity *entity,
@@ -188,10 +191,38 @@ struct media_entity_operations {
188}; 191};
189 192
190/** 193/**
194 * enum media_entity_type - Media entity type
195 *
196 * @MEDIA_ENTITY_TYPE_BASE:
197 * The entity isn't embedded in another subsystem structure.
198 * @MEDIA_ENTITY_TYPE_VIDEO_DEVICE:
199 * The entity is embedded in a struct video_device instance.
200 * @MEDIA_ENTITY_TYPE_V4L2_SUBDEV:
201 * The entity is embedded in a struct v4l2_subdev instance.
202 *
203 * Media entity objects are often not instantiated directly, but the media
204 * entity structure is inherited by (through embedding) other subsystem-specific
205 * structures. The media entity type identifies the type of the subclass
206 * structure that implements a media entity instance.
207 *
208 * This allows runtime type identification of media entities and safe casting to
209 * the correct object type. For instance, a media entity structure instance
210 * embedded in a v4l2_subdev structure instance will have the type
211 * MEDIA_ENTITY_TYPE_V4L2_SUBDEV and can safely be cast to a v4l2_subdev
212 * structure using the container_of() macro.
213 */
214enum media_entity_type {
215 MEDIA_ENTITY_TYPE_BASE,
216 MEDIA_ENTITY_TYPE_VIDEO_DEVICE,
217 MEDIA_ENTITY_TYPE_V4L2_SUBDEV,
218};
219
220/**
191 * struct media_entity - A media entity graph object. 221 * struct media_entity - A media entity graph object.
192 * 222 *
193 * @graph_obj: Embedded structure containing the media object common data. 223 * @graph_obj: Embedded structure containing the media object common data.
194 * @name: Entity name. 224 * @name: Entity name.
225 * @obj_type: Type of the object that implements the media_entity.
195 * @function: Entity main function, as defined in uapi/media.h 226 * @function: Entity main function, as defined in uapi/media.h
196 * (MEDIA_ENT_F_*) 227 * (MEDIA_ENT_F_*)
197 * @flags: Entity flags, as defined in uapi/media.h (MEDIA_ENT_FL_*) 228 * @flags: Entity flags, as defined in uapi/media.h (MEDIA_ENT_FL_*)
@@ -220,6 +251,7 @@ struct media_entity_operations {
220struct media_entity { 251struct media_entity {
221 struct media_gobj graph_obj; /* must be first field in struct */ 252 struct media_gobj graph_obj; /* must be first field in struct */
222 const char *name; 253 const char *name;
254 enum media_entity_type obj_type;
223 u32 function; 255 u32 function;
224 unsigned long flags; 256 unsigned long flags;
225 257
@@ -329,56 +361,29 @@ static inline u32 media_gobj_gen_id(enum media_gobj_type type, u64 local_id)
329} 361}
330 362
331/** 363/**
332 * is_media_entity_v4l2_io() - identify if the entity main function 364 * is_media_entity_v4l2_video_device() - Check if the entity is a video_device
333 * is a V4L2 I/O
334 *
335 * @entity: pointer to entity 365 * @entity: pointer to entity
336 * 366 *
337 * Return: true if the entity main function is one of the V4L2 I/O types 367 * Return: true if the entity is an instance of a video_device object and can
338 * (video, VBI or SDR radio); false otherwise. 368 * safely be cast to a struct video_device using the container_of() macro, or
369 * false otherwise.
339 */ 370 */
340static inline bool is_media_entity_v4l2_io(struct media_entity *entity) 371static inline bool is_media_entity_v4l2_video_device(struct media_entity *entity)
341{ 372{
342 if (!entity) 373 return entity && entity->obj_type == MEDIA_ENTITY_TYPE_VIDEO_DEVICE;
343 return false;
344
345 switch (entity->function) {
346 case MEDIA_ENT_F_IO_V4L:
347 case MEDIA_ENT_F_IO_VBI:
348 case MEDIA_ENT_F_IO_SWRADIO:
349 return true;
350 default:
351 return false;
352 }
353} 374}
354 375
355/** 376/**
356 * is_media_entity_v4l2_subdev - return true if the entity main function is 377 * is_media_entity_v4l2_subdev() - Check if the entity is a v4l2_subdev
357 * associated with the V4L2 API subdev usage
358 *
359 * @entity: pointer to entity 378 * @entity: pointer to entity
360 * 379 *
361 * This is an ancillary function used by subdev-based V4L2 drivers. 380 * Return: true if the entity is an instance of a v4l2_subdev object and can
362 * It checks if the entity function is one of functions used by a V4L2 subdev, 381 * safely be cast to a struct v4l2_subdev using the container_of() macro, or
363 * e. g. camera-relatef functions, analog TV decoder, TV tuner, V4L2 DSPs. 382 * false otherwise.
364 */ 383 */
365static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity) 384static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity)
366{ 385{
367 if (!entity) 386 return entity && entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV;
368 return false;
369
370 switch (entity->function) {
371 case MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN:
372 case MEDIA_ENT_F_CAM_SENSOR:
373 case MEDIA_ENT_F_FLASH:
374 case MEDIA_ENT_F_LENS:
375 case MEDIA_ENT_F_ATV_DECODER:
376 case MEDIA_ENT_F_TUNER:
377 return true;
378
379 default:
380 return false;
381 }
382} 387}
383 388
384/** 389/**
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 0f77b3dffb37..b6586a91129c 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -215,12 +215,9 @@ enum raw_event_type {
215struct ir_raw_event { 215struct ir_raw_event {
216 union { 216 union {
217 u32 duration; 217 u32 duration;
218 218 u32 carrier;
219 struct {
220 u32 carrier;
221 u8 duty_cycle;
222 };
223 }; 219 };
220 u8 duty_cycle;
224 221
225 unsigned pulse:1; 222 unsigned pulse:1;
226 unsigned reset:1; 223 unsigned reset:1;
@@ -228,13 +225,7 @@ struct ir_raw_event {
228 unsigned carrier_report:1; 225 unsigned carrier_report:1;
229}; 226};
230 227
231#define DEFINE_IR_RAW_EVENT(event) \ 228#define DEFINE_IR_RAW_EVENT(event) struct ir_raw_event event = {}
232 struct ir_raw_event event = { \
233 { .duration = 0 } , \
234 .pulse = 0, \
235 .reset = 0, \
236 .timeout = 0, \
237 .carrier_report = 0 }
238 229
239static inline void init_ir_raw_event(struct ir_raw_event *ev) 230static inline void init_ir_raw_event(struct ir_raw_event *ev)
240{ 231{
@@ -256,8 +247,7 @@ void ir_raw_event_set_idle(struct rc_dev *dev, bool idle);
256 247
257static inline void ir_raw_event_reset(struct rc_dev *dev) 248static inline void ir_raw_event_reset(struct rc_dev *dev)
258{ 249{
259 DEFINE_IR_RAW_EVENT(ev); 250 struct ir_raw_event ev = { .reset = true };
260 ev.reset = true;
261 251
262 ir_raw_event_store(dev, &ev); 252 ir_raw_event_store(dev, &ev);
263 ir_raw_event_handle(dev); 253 ir_raw_event_handle(dev);
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 76056ab5c5bd..25a3190308fb 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -92,6 +92,9 @@ struct video_device
92 /* device ops */ 92 /* device ops */
93 const struct v4l2_file_operations *fops; 93 const struct v4l2_file_operations *fops;
94 94
95 /* device capabilities as used in v4l2_capabilities */
96 u32 device_caps;
97
95 /* sysfs */ 98 /* sysfs */
96 struct device dev; /* v4l device */ 99 struct device dev; /* v4l device */
97 struct cdev *cdev; /* character device */ 100 struct cdev *cdev; /* character device */
diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index 9c581578783f..d5d45a8d3998 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -196,11 +196,64 @@ static inline void v4l2_subdev_notify(struct v4l2_subdev *sd,
196 ##args); \ 196 ##args); \
197}) 197})
198 198
199#define v4l2_device_has_op(v4l2_dev, o, f) \ 199/*
200 * Call the specified callback for all subdevs where grp_id & grpmsk != 0
201 * (if grpmsk == `0, then match them all). Ignore any errors. Note that you
202 * cannot add or delete a subdev while walking the subdevs list.
203 */
204#define v4l2_device_mask_call_all(v4l2_dev, grpmsk, o, f, args...) \
205 do { \
206 struct v4l2_subdev *__sd; \
207 \
208 __v4l2_device_call_subdevs_p(v4l2_dev, __sd, \
209 !(grpmsk) || (__sd->grp_id & (grpmsk)), o, f , \
210 ##args); \
211 } while (0)
212
213/*
214 * Call the specified callback for all subdevs where grp_id & grpmsk != 0
215 * (if grpmsk == `0, then match them all). If the callback returns an error
216 * other than 0 or -ENOIOCTLCMD, then return with that error code. Note that
217 * you cannot add or delete a subdev while walking the subdevs list.
218 */
219#define v4l2_device_mask_call_until_err(v4l2_dev, grpmsk, o, f, args...) \
220({ \
221 struct v4l2_subdev *__sd; \
222 __v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd, \
223 !(grpmsk) || (__sd->grp_id & (grpmsk)), o, f , \
224 ##args); \
225})
226
227/*
228 * Does any subdev with matching grpid (or all if grpid == 0) has the given
229 * op?
230 */
231#define v4l2_device_has_op(v4l2_dev, grpid, o, f) \
232({ \
233 struct v4l2_subdev *__sd; \
234 bool __result = false; \
235 list_for_each_entry(__sd, &(v4l2_dev)->subdevs, list) { \
236 if ((grpid) && __sd->grp_id != (grpid)) \
237 continue; \
238 if (v4l2_subdev_has_op(__sd, o, f)) { \
239 __result = true; \
240 break; \
241 } \
242 } \
243 __result; \
244})
245
246/*
247 * Does any subdev with matching grpmsk (or all if grpmsk == 0) has the given
248 * op?
249 */
250#define v4l2_device_mask_has_op(v4l2_dev, grpmsk, o, f) \
200({ \ 251({ \
201 struct v4l2_subdev *__sd; \ 252 struct v4l2_subdev *__sd; \
202 bool __result = false; \ 253 bool __result = false; \
203 list_for_each_entry(__sd, &(v4l2_dev)->subdevs, list) { \ 254 list_for_each_entry(__sd, &(v4l2_dev)->subdevs, list) { \
255 if ((grpmsk) && !(__sd->grp_id & (grpmsk))) \
256 continue; \
204 if (v4l2_subdev_has_op(__sd, o, f)) { \ 257 if (v4l2_subdev_has_op(__sd, o, f)) { \
205 __result = true; \ 258 __result = true; \
206 break; \ 259 break; \
diff --git a/include/media/v4l2-rect.h b/include/media/v4l2-rect.h
new file mode 100644
index 000000000000..d2125f0cc7cd
--- /dev/null
+++ b/include/media/v4l2-rect.h
@@ -0,0 +1,173 @@
1/*
2 * v4l2-rect.h - v4l2_rect helper functions
3 *
4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#ifndef _V4L2_RECT_H_
21#define _V4L2_RECT_H_
22
23#include <linux/videodev2.h>
24
25/**
26 * v4l2_rect_set_size_to() - copy the width/height values.
27 * @r: rect whose width and height fields will be set
28 * @size: rect containing the width and height fields you need.
29 */
30static inline void v4l2_rect_set_size_to(struct v4l2_rect *r,
31 const struct v4l2_rect *size)
32{
33 r->width = size->width;
34 r->height = size->height;
35}
36
37/**
38 * v4l2_rect_set_min_size() - width and height of r should be >= min_size.
39 * @r: rect whose width and height will be modified
40 * @min_size: rect containing the minimal width and height
41 */
42static inline void v4l2_rect_set_min_size(struct v4l2_rect *r,
43 const struct v4l2_rect *min_size)
44{
45 if (r->width < min_size->width)
46 r->width = min_size->width;
47 if (r->height < min_size->height)
48 r->height = min_size->height;
49}
50
51/**
52 * v4l2_rect_set_max_size() - width and height of r should be <= max_size
53 * @r: rect whose width and height will be modified
54 * @max_size: rect containing the maximum width and height
55 */
56static inline void v4l2_rect_set_max_size(struct v4l2_rect *r,
57 const struct v4l2_rect *max_size)
58{
59 if (r->width > max_size->width)
60 r->width = max_size->width;
61 if (r->height > max_size->height)
62 r->height = max_size->height;
63}
64
65/**
66 * v4l2_rect_map_inside()- r should be inside boundary.
67 * @r: rect that will be modified
68 * @boundary: rect containing the boundary for @r
69 */
70static inline void v4l2_rect_map_inside(struct v4l2_rect *r,
71 const struct v4l2_rect *boundary)
72{
73 v4l2_rect_set_max_size(r, boundary);
74 if (r->left < boundary->left)
75 r->left = boundary->left;
76 if (r->top < boundary->top)
77 r->top = boundary->top;
78 if (r->left + r->width > boundary->width)
79 r->left = boundary->width - r->width;
80 if (r->top + r->height > boundary->height)
81 r->top = boundary->height - r->height;
82}
83
84/**
85 * v4l2_rect_same_size() - return true if r1 has the same size as r2
86 * @r1: rectangle.
87 * @r2: rectangle.
88 *
89 * Return true if both rectangles have the same size.
90 */
91static inline bool v4l2_rect_same_size(const struct v4l2_rect *r1,
92 const struct v4l2_rect *r2)
93{
94 return r1->width == r2->width && r1->height == r2->height;
95}
96
97/**
98 * v4l2_rect_intersect() - calculate the intersection of two rects.
99 * @r: intersection of @r1 and @r2.
100 * @r1: rectangle.
101 * @r2: rectangle.
102 */
103static inline void v4l2_rect_intersect(struct v4l2_rect *r,
104 const struct v4l2_rect *r1,
105 const struct v4l2_rect *r2)
106{
107 int right, bottom;
108
109 r->top = max(r1->top, r2->top);
110 r->left = max(r1->left, r2->left);
111 bottom = min(r1->top + r1->height, r2->top + r2->height);
112 right = min(r1->left + r1->width, r2->left + r2->width);
113 r->height = max(0, bottom - r->top);
114 r->width = max(0, right - r->left);
115}
116
117/**
118 * v4l2_rect_scale() - scale rect r by to/from
119 * @r: rect to be scaled.
120 * @from: from rectangle.
121 * @to: to rectangle.
122 *
123 * This scales rectangle @r horizontally by @to->width / @from->width and
124 * vertically by @to->height / @from->height.
125 *
126 * Typically @r is a rectangle inside @from and you want the rectangle as
127 * it would appear after scaling @from to @to. So the resulting @r will
128 * be the scaled rectangle inside @to.
129 */
130static inline void v4l2_rect_scale(struct v4l2_rect *r,
131 const struct v4l2_rect *from,
132 const struct v4l2_rect *to)
133{
134 if (from->width == 0 || from->height == 0) {
135 r->left = r->top = r->width = r->height = 0;
136 return;
137 }
138 r->left = (((r->left - from->left) * to->width) / from->width) & ~1;
139 r->width = ((r->width * to->width) / from->width) & ~1;
140 r->top = ((r->top - from->top) * to->height) / from->height;
141 r->height = (r->height * to->height) / from->height;
142}
143
144/**
145 * v4l2_rect_overlap() - do r1 and r2 overlap?
146 * @r1: rectangle.
147 * @r2: rectangle.
148 *
149 * Returns true if @r1 and @r2 overlap.
150 */
151static inline bool v4l2_rect_overlap(const struct v4l2_rect *r1,
152 const struct v4l2_rect *r2)
153{
154 /*
155 * IF the left side of r1 is to the right of the right side of r2 OR
156 * the left side of r2 is to the right of the right side of r1 THEN
157 * they do not overlap.
158 */
159 if (r1->left >= r2->left + r2->width ||
160 r2->left >= r1->left + r1->width)
161 return false;
162 /*
163 * IF the top side of r1 is below the bottom of r2 OR
164 * the top side of r2 is below the bottom of r1 THEN
165 * they do not overlap.
166 */
167 if (r1->top >= r2->top + r2->height ||
168 r2->top >= r1->top + r1->height)
169 return false;
170 return true;
171}
172
173#endif
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 11e2dfec0198..32fc7a4beb5e 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -572,6 +572,7 @@ struct v4l2_subdev_pad_config {
572/** 572/**
573 * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations 573 * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations
574 * 574 *
575 * @init_cfg: initialize the pad config to default values
575 * @enum_mbus_code: callback for VIDIOC_SUBDEV_ENUM_MBUS_CODE ioctl handler 576 * @enum_mbus_code: callback for VIDIOC_SUBDEV_ENUM_MBUS_CODE ioctl handler
576 * code. 577 * code.
577 * @enum_frame_size: callback for VIDIOC_SUBDEV_ENUM_FRAME_SIZE ioctl handler 578 * @enum_frame_size: callback for VIDIOC_SUBDEV_ENUM_FRAME_SIZE ioctl handler
@@ -607,6 +608,8 @@ struct v4l2_subdev_pad_config {
607 * may be adjusted by the subdev driver to device capabilities. 608 * may be adjusted by the subdev driver to device capabilities.
608 */ 609 */
609struct v4l2_subdev_pad_ops { 610struct v4l2_subdev_pad_ops {
611 int (*init_cfg)(struct v4l2_subdev *sd,
612 struct v4l2_subdev_pad_config *cfg);
610 int (*enum_mbus_code)(struct v4l2_subdev *sd, 613 int (*enum_mbus_code)(struct v4l2_subdev *sd,
611 struct v4l2_subdev_pad_config *cfg, 614 struct v4l2_subdev_pad_config *cfg,
612 struct v4l2_subdev_mbus_code_enum *code); 615 struct v4l2_subdev_mbus_code_enum *code);
@@ -801,7 +804,12 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
801 struct v4l2_subdev_format *source_fmt, 804 struct v4l2_subdev_format *source_fmt,
802 struct v4l2_subdev_format *sink_fmt); 805 struct v4l2_subdev_format *sink_fmt);
803int v4l2_subdev_link_validate(struct media_link *link); 806int v4l2_subdev_link_validate(struct media_link *link);
807
808struct v4l2_subdev_pad_config *
809v4l2_subdev_alloc_pad_config(struct v4l2_subdev *sd);
810void v4l2_subdev_free_pad_config(struct v4l2_subdev_pad_config *cfg);
804#endif /* CONFIG_MEDIA_CONTROLLER */ 811#endif /* CONFIG_MEDIA_CONTROLLER */
812
805void v4l2_subdev_init(struct v4l2_subdev *sd, 813void v4l2_subdev_init(struct v4l2_subdev *sd,
806 const struct v4l2_subdev_ops *ops); 814 const struct v4l2_subdev_ops *ops);
807 815
diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.h b/include/media/v4l2-tpg-colors.h
index 4e5a76a1e25b..2a88d1fae0cd 100644
--- a/drivers/media/platform/vivid/vivid-tpg-colors.h
+++ b/include/media/v4l2-tpg-colors.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * vivid-color.h - Color definitions for the test pattern generator 2 * v4l2-tpg-colors.h - Color definitions for the test pattern generator
3 * 3 *
4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 * 5 *
@@ -17,8 +17,8 @@
17 * SOFTWARE. 17 * SOFTWARE.
18 */ 18 */
19 19
20#ifndef _VIVID_COLORS_H_ 20#ifndef _V4L2_TPG_COLORS_H_
21#define _VIVID_COLORS_H_ 21#define _V4L2_TPG_COLORS_H_
22 22
23struct color { 23struct color {
24 unsigned char r, g, b; 24 unsigned char r, g, b;
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/include/media/v4l2-tpg.h
index 93fbaee69675..329bebfa930c 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/include/media/v4l2-tpg.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * vivid-tpg.h - Test Pattern Generator 2 * v4l2-tpg.h - Test Pattern Generator
3 * 3 *
4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 * 5 *
@@ -17,8 +17,8 @@
17 * SOFTWARE. 17 * SOFTWARE.
18 */ 18 */
19 19
20#ifndef _VIVID_TPG_H_ 20#ifndef _V4L2_TPG_H_
21#define _VIVID_TPG_H_ 21#define _V4L2_TPG_H_
22 22
23#include <linux/types.h> 23#include <linux/types.h>
24#include <linux/errno.h> 24#include <linux/errno.h>
@@ -26,8 +26,7 @@
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/vmalloc.h> 27#include <linux/vmalloc.h>
28#include <linux/videodev2.h> 28#include <linux/videodev2.h>
29 29#include <media/v4l2-tpg-colors.h>
30#include "vivid-tpg-colors.h"
31 30
32enum tpg_pattern { 31enum tpg_pattern {
33 TPG_PAT_75_COLORBAR, 32 TPG_PAT_75_COLORBAR,
diff --git a/include/media/vsp1.h b/include/media/vsp1.h
index cc541753896f..3e654a0455bd 100644
--- a/include/media/vsp1.h
+++ b/include/media/vsp1.h
@@ -23,11 +23,22 @@ int vsp1_du_init(struct device *dev);
23int vsp1_du_setup_lif(struct device *dev, unsigned int width, 23int vsp1_du_setup_lif(struct device *dev, unsigned int width,
24 unsigned int height); 24 unsigned int height);
25 25
26int vsp1_du_atomic_begin(struct device *dev); 26void vsp1_du_atomic_begin(struct device *dev);
27int vsp1_du_atomic_update(struct device *dev, unsigned int rpf, u32 pixelformat, 27int vsp1_du_atomic_update_ext(struct device *dev, unsigned int rpf,
28 unsigned int pitch, dma_addr_t mem[2], 28 u32 pixelformat, unsigned int pitch,
29 const struct v4l2_rect *src, 29 dma_addr_t mem[2], const struct v4l2_rect *src,
30 const struct v4l2_rect *dst); 30 const struct v4l2_rect *dst, unsigned int alpha,
31int vsp1_du_atomic_flush(struct device *dev); 31 unsigned int zpos);
32void vsp1_du_atomic_flush(struct device *dev);
33
34static inline int vsp1_du_atomic_update(struct device *dev,
35 unsigned int rpf_index, u32 pixelformat,
36 unsigned int pitch, dma_addr_t mem[2],
37 const struct v4l2_rect *src,
38 const struct v4l2_rect *dst)
39{
40 return vsp1_du_atomic_update_ext(dev, rpf_index, pixelformat, pitch,
41 mem, src, dst, 255, 0);
42}
32 43
33#endif /* __MEDIA_VSP1_H__ */ 44#endif /* __MEDIA_VSP1_H__ */
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index e895975c5b0e..8f951917be74 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -138,10 +138,7 @@ enum v4l2_buf_type {
138 V4L2_BUF_TYPE_VBI_OUTPUT = 5, 138 V4L2_BUF_TYPE_VBI_OUTPUT = 5,
139 V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, 139 V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6,
140 V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, 140 V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7,
141#if 1
142 /* Experimental */
143 V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, 141 V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
144#endif
145 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9, 142 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
146 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10, 143 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = 10,
147 V4L2_BUF_TYPE_SDR_CAPTURE = 11, 144 V4L2_BUF_TYPE_SDR_CAPTURE = 11,
@@ -657,8 +654,7 @@ struct v4l2_fmtdesc {
657#define V4L2_FMT_FLAG_COMPRESSED 0x0001 654#define V4L2_FMT_FLAG_COMPRESSED 0x0001
658#define V4L2_FMT_FLAG_EMULATED 0x0002 655#define V4L2_FMT_FLAG_EMULATED 0x0002
659 656
660#if 1 657 /* Frame Size and frame rate enumeration */
661 /* Experimental Frame Size and frame rate enumeration */
662/* 658/*
663 * F R A M E S I Z E E N U M E R A T I O N 659 * F R A M E S I Z E E N U M E R A T I O N
664 */ 660 */
@@ -724,7 +720,6 @@ struct v4l2_frmivalenum {
724 720
725 __u32 reserved[2]; /* Reserved space for future use */ 721 __u32 reserved[2]; /* Reserved space for future use */
726}; 722};
727#endif
728 723
729/* 724/*
730 * T I M E C O D E 725 * T I M E C O D E
@@ -1728,8 +1723,6 @@ struct v4l2_audioout {
1728 1723
1729/* 1724/*
1730 * M P E G S E R V I C E S 1725 * M P E G S E R V I C E S
1731 *
1732 * NOTE: EXPERIMENTAL API
1733 */ 1726 */
1734#if 1 1727#if 1
1735#define V4L2_ENC_IDX_FRAME_I (0) 1728#define V4L2_ENC_IDX_FRAME_I (0)
@@ -2259,46 +2252,35 @@ struct v4l2_create_buffers {
2259#define VIDIOC_ENCODER_CMD _IOWR('V', 77, struct v4l2_encoder_cmd) 2252#define VIDIOC_ENCODER_CMD _IOWR('V', 77, struct v4l2_encoder_cmd)
2260#define VIDIOC_TRY_ENCODER_CMD _IOWR('V', 78, struct v4l2_encoder_cmd) 2253#define VIDIOC_TRY_ENCODER_CMD _IOWR('V', 78, struct v4l2_encoder_cmd)
2261 2254
2262/* Experimental, meant for debugging, testing and internal use. 2255/*
2263 Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. 2256 * Experimental, meant for debugging, testing and internal use.
2264 You must be root to use these ioctls. Never use these in applications! */ 2257 * Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined.
2258 * You must be root to use these ioctls. Never use these in applications!
2259 */
2265#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) 2260#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register)
2266#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) 2261#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register)
2267 2262
2268#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) 2263#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek)
2269
2270#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) 2264#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings)
2271#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) 2265#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings)
2272#define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event) 2266#define VIDIOC_DQEVENT _IOR('V', 89, struct v4l2_event)
2273#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription) 2267#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription)
2274#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription) 2268#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription)
2275
2276/* Experimental, the below two ioctls may change over the next couple of kernel
2277 versions */
2278#define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers) 2269#define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers)
2279#define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer) 2270#define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer)
2280
2281/* Experimental selection API */
2282#define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) 2271#define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection)
2283#define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) 2272#define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection)
2284
2285/* Experimental, these two ioctls may change over the next couple of kernel
2286 versions. */
2287#define VIDIOC_DECODER_CMD _IOWR('V', 96, struct v4l2_decoder_cmd) 2273#define VIDIOC_DECODER_CMD _IOWR('V', 96, struct v4l2_decoder_cmd)
2288#define VIDIOC_TRY_DECODER_CMD _IOWR('V', 97, struct v4l2_decoder_cmd) 2274#define VIDIOC_TRY_DECODER_CMD _IOWR('V', 97, struct v4l2_decoder_cmd)
2289
2290/* Experimental, these three ioctls may change over the next couple of kernel
2291 versions. */
2292#define VIDIOC_ENUM_DV_TIMINGS _IOWR('V', 98, struct v4l2_enum_dv_timings) 2275#define VIDIOC_ENUM_DV_TIMINGS _IOWR('V', 98, struct v4l2_enum_dv_timings)
2293#define VIDIOC_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings) 2276#define VIDIOC_QUERY_DV_TIMINGS _IOR('V', 99, struct v4l2_dv_timings)
2294#define VIDIOC_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap) 2277#define VIDIOC_DV_TIMINGS_CAP _IOWR('V', 100, struct v4l2_dv_timings_cap)
2295
2296/* Experimental, this ioctl may change over the next couple of kernel
2297 versions. */
2298#define VIDIOC_ENUM_FREQ_BANDS _IOWR('V', 101, struct v4l2_frequency_band) 2278#define VIDIOC_ENUM_FREQ_BANDS _IOWR('V', 101, struct v4l2_frequency_band)
2299 2279
2300/* Experimental, meant for debugging, testing and internal use. 2280/*
2301 Never use these in applications! */ 2281 * Experimental, meant for debugging, testing and internal use.
2282 * Never use this in applications!
2283 */
2302#define VIDIOC_DBG_G_CHIP_INFO _IOWR('V', 102, struct v4l2_dbg_chip_info) 2284#define VIDIOC_DBG_G_CHIP_INFO _IOWR('V', 102, struct v4l2_dbg_chip_info)
2303 2285
2304#define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl) 2286#define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl)
diff --git a/samples/Makefile b/samples/Makefile
index 48001d7e23f0..ad440d670cdb 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -2,4 +2,4 @@
2 2
3obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ 3obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \
4 hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ 4 hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \
5 configfs/ 5 configfs/ v4l/
diff --git a/Documentation/video4linux/Makefile b/samples/v4l/Makefile
index 65a351d75c95..65a351d75c95 100644
--- a/Documentation/video4linux/Makefile
+++ b/samples/v4l/Makefile
diff --git a/Documentation/video4linux/v4l2-pci-skeleton.c b/samples/v4l/v4l2-pci-skeleton.c
index 79af0c041056..a55cf94ac907 100644
--- a/Documentation/video4linux/v4l2-pci-skeleton.c
+++ b/samples/v4l/v4l2-pci-skeleton.c
@@ -308,9 +308,6 @@ static int skeleton_querycap(struct file *file, void *priv,
308 strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card)); 308 strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card));
309 snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", 309 snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
310 pci_name(skel->pdev)); 310 pci_name(skel->pdev));
311 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
312 V4L2_CAP_STREAMING;
313 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
314 return 0; 311 return 0;
315} 312}
316 313
@@ -872,6 +869,8 @@ static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
872 vdev->release = video_device_release_empty; 869 vdev->release = video_device_release_empty;
873 vdev->fops = &skel_fops, 870 vdev->fops = &skel_fops,
874 vdev->ioctl_ops = &skel_ioctl_ops, 871 vdev->ioctl_ops = &skel_ioctl_ops,
872 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
873 V4L2_CAP_STREAMING;
875 /* 874 /*
876 * The main serialization lock. All ioctls are serialized by this 875 * The main serialization lock. All ioctls are serialized by this
877 * lock. Exception: if q->lock is set, then the streaming ioctls 876 * lock. Exception: if q->lock is set, then the streaming ioctls